Snap for 11155123 from 4cdc32bd2129380ed311e7439281bdef16976796 to mainline-permission-release Change-Id: I7828281ef4253e727e87926f67c95aff876d6a83
diff --git a/apishim/common/com/android/networkstack/apishim/common/NetworkInformationShim.java b/apishim/common/com/android/networkstack/apishim/common/NetworkInformationShim.java index e7f7b3d..2fcd8c6 100644 --- a/apishim/common/com/android/networkstack/apishim/common/NetworkInformationShim.java +++ b/apishim/common/com/android/networkstack/apishim/common/NetworkInformationShim.java
@@ -100,7 +100,7 @@ } /** - * @see NetworkCapabilites#getUnderlyingNetworks() + * @see NetworkCapabilities#getUnderlyingNetworks() */ @Nullable default List<Network> getUnderlyingNetworks(@NonNull NetworkCapabilities nc) {
diff --git a/common/networkstackclient/Android.bp b/common/networkstackclient/Android.bp index 0571042..e056e3b 100644 --- a/common/networkstackclient/Android.bp +++ b/common/networkstackclient/Android.bp
@@ -160,6 +160,10 @@ version: "18", imports: ["ipmemorystore-aidl-interfaces-V10"], }, + { + version: "19", + imports: ["ipmemorystore-aidl-interfaces-V10"], + }, ], @@ -174,7 +178,7 @@ min_sdk_version: "30", static_libs: [ "ipmemorystore-aidl-interfaces-V10-java", - "networkstack-aidl-interfaces-V18-java", + "networkstack-aidl-interfaces-V19-java", ], visibility: ["//packages/modules/NetworkStack:__subpackages__"], apex_available: [
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/.hash b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/.hash new file mode 100644 index 0000000..5e94944 --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/.hash
@@ -0,0 +1 @@ +ffc74fbac5dcfe825bc16b9a3a91b43251476361
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/DataStallReportParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/DataStallReportParcelable.aidl new file mode 100644 index 0000000..771deda --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/DataStallReportParcelable.aidl
@@ -0,0 +1,42 @@ +/** + * Copyright (c) 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing perNmissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +@JavaDerive(toString=true) +parcelable DataStallReportParcelable { + long timestampMillis = 0; + int detectionMethod = 1; + int tcpPacketFailRate = 2; + int tcpMetricsCollectionPeriodMillis = 3; + int dnsConsecutiveTimeouts = 4; +}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/DhcpResultsParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/DhcpResultsParcelable.aidl new file mode 100644 index 0000000..31f2194 --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/DhcpResultsParcelable.aidl
@@ -0,0 +1,44 @@ +/** + * Copyright (c) 2019, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing perNmissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +@JavaDerive(toString=true) +parcelable DhcpResultsParcelable { + android.net.StaticIpConfiguration baseConfiguration; + int leaseDuration; + int mtu; + String serverAddress; + String vendorInfo; + @nullable String serverHostName; + @nullable String captivePortalApiUrl; +}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/INetworkMonitor.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/INetworkMonitor.aidl new file mode 100644 index 0000000..fb13c0c --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/INetworkMonitor.aidl
@@ -0,0 +1,60 @@ +/** + * Copyright (c) 2018, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing perNmissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +/* @hide */ +interface INetworkMonitor { + oneway void start(); + oneway void launchCaptivePortalApp(); + oneway void notifyCaptivePortalAppFinished(int response); + oneway void setAcceptPartialConnectivity(); + oneway void forceReevaluation(int uid); + oneway void notifyPrivateDnsChanged(in android.net.PrivateDnsConfigParcel config); + oneway void notifyDnsResponse(int returnCode); + oneway void notifyNetworkConnected(in android.net.LinkProperties lp, in android.net.NetworkCapabilities nc); + oneway void notifyNetworkDisconnected(); + oneway void notifyLinkPropertiesChanged(in android.net.LinkProperties lp); + oneway void notifyNetworkCapabilitiesChanged(in android.net.NetworkCapabilities nc); + oneway void notifyNetworkConnectedParcel(in android.net.networkstack.aidl.NetworkMonitorParameters params); + const int NETWORK_TEST_RESULT_VALID = 0; + const int NETWORK_TEST_RESULT_INVALID = 1; + const int NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY = 2; + const int NETWORK_VALIDATION_RESULT_VALID = 0x01; + const int NETWORK_VALIDATION_RESULT_PARTIAL = 0x02; + const int NETWORK_VALIDATION_RESULT_SKIPPED = 0x04; + const int NETWORK_VALIDATION_PROBE_DNS = 0x04; + const int NETWORK_VALIDATION_PROBE_HTTP = 0x08; + const int NETWORK_VALIDATION_PROBE_HTTPS = 0x10; + const int NETWORK_VALIDATION_PROBE_FALLBACK = 0x20; + const int NETWORK_VALIDATION_PROBE_PRIVDNS = 0x40; +}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/INetworkMonitorCallbacks.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/INetworkMonitorCallbacks.aidl new file mode 100644 index 0000000..36eda8e --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/INetworkMonitorCallbacks.aidl
@@ -0,0 +1,46 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +/* @hide */ +interface INetworkMonitorCallbacks { + oneway void onNetworkMonitorCreated(in android.net.INetworkMonitor networkMonitor) = 0; + oneway void notifyNetworkTested(int testResult, @nullable String redirectUrl) = 1; + oneway void notifyPrivateDnsConfigResolved(in android.net.PrivateDnsConfigParcel config) = 2; + oneway void showProvisioningNotification(String action, String packageName) = 3; + oneway void hideProvisioningNotification() = 4; + oneway void notifyProbeStatusChanged(int probesCompleted, int probesSucceeded) = 5; + oneway void notifyNetworkTestedWithExtras(in android.net.NetworkTestResultParcelable result) = 6; + oneway void notifyDataStallSuspected(in android.net.DataStallReportParcelable report) = 7; + oneway void notifyCaptivePortalDataChanged(in android.net.CaptivePortalData data) = 8; +}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/INetworkStackConnector.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/INetworkStackConnector.aidl new file mode 100644 index 0000000..8120ffc --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/INetworkStackConnector.aidl
@@ -0,0 +1,42 @@ +/** + * Copyright (c) 2018, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing perNmissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +/* @hide */ +interface INetworkStackConnector { + oneway void makeDhcpServer(in String ifName, in android.net.dhcp.DhcpServingParamsParcel params, in android.net.dhcp.IDhcpServerCallbacks cb); + oneway void makeNetworkMonitor(in android.net.Network network, String name, in android.net.INetworkMonitorCallbacks cb); + oneway void makeIpClient(in String ifName, in android.net.ip.IIpClientCallbacks callbacks); + oneway void fetchIpMemoryStore(in android.net.IIpMemoryStoreCallbacks cb); + oneway void allowTestUid(int uid, in android.net.INetworkStackStatusCallback cb); +}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/INetworkStackStatusCallback.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/INetworkStackStatusCallback.aidl new file mode 100644 index 0000000..0b6b778 --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/INetworkStackStatusCallback.aidl
@@ -0,0 +1,38 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +/* @hide */ +interface INetworkStackStatusCallback { + oneway void onStatusAvailable(int statusCode); +}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/InformationElementParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/InformationElementParcelable.aidl new file mode 100644 index 0000000..6103774 --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/InformationElementParcelable.aidl
@@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +@JavaDerive(toString=true) +parcelable InformationElementParcelable { + int id; + byte[] payload; +}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/InitialConfigurationParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/InitialConfigurationParcelable.aidl new file mode 100644 index 0000000..6a597e6 --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/InitialConfigurationParcelable.aidl
@@ -0,0 +1,41 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +@JavaDerive(toString=true) +parcelable InitialConfigurationParcelable { + android.net.LinkAddress[] ipAddresses; + android.net.IpPrefix[] directlyConnectedRoutes; + String[] dnsServers; + String gateway; +}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/Layer2InformationParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/Layer2InformationParcelable.aidl new file mode 100644 index 0000000..83796ee --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/Layer2InformationParcelable.aidl
@@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +@JavaDerive(toString=true) +parcelable Layer2InformationParcelable { + String l2Key; + String cluster; + android.net.MacAddress bssid; +}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/Layer2PacketParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/Layer2PacketParcelable.aidl new file mode 100644 index 0000000..4b3fff5 --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/Layer2PacketParcelable.aidl
@@ -0,0 +1,39 @@ +/** + * Copyright (c) 2019, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing perNmissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +@JavaDerive(toString=true) +parcelable Layer2PacketParcelable { + android.net.MacAddress dstMacAddress; + byte[] payload; +}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/NattKeepalivePacketDataParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/NattKeepalivePacketDataParcelable.aidl new file mode 100644 index 0000000..18cf954 --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/NattKeepalivePacketDataParcelable.aidl
@@ -0,0 +1,41 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +@JavaDerive(toString=true) +parcelable NattKeepalivePacketDataParcelable { + byte[] srcAddress; + int srcPort; + byte[] dstAddress; + int dstPort; +}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/NetworkTestResultParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/NetworkTestResultParcelable.aidl new file mode 100644 index 0000000..4d6d5a2 --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/NetworkTestResultParcelable.aidl
@@ -0,0 +1,42 @@ +/** + * Copyright (c) 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing perNmissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +@JavaDerive(toString=true) +parcelable NetworkTestResultParcelable { + long timestampMillis; + int result; + int probesSucceeded; + int probesAttempted; + String redirectUrl; +}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/PrivateDnsConfigParcel.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/PrivateDnsConfigParcel.aidl new file mode 100644 index 0000000..ab62fe7 --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/PrivateDnsConfigParcel.aidl
@@ -0,0 +1,44 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +@JavaDerive(equals=true, toString=true) +parcelable PrivateDnsConfigParcel { + String hostname; + String[] ips; + int privateDnsMode = (-1) /* -1 */; + String dohName = ""; + String[] dohIps = {}; + String dohPath = ""; + int dohPort = (-1) /* -1 */; +}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/ProvisioningConfigurationParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/ProvisioningConfigurationParcelable.aidl new file mode 100644 index 0000000..fba524b --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/ProvisioningConfigurationParcelable.aidl
@@ -0,0 +1,63 @@ +/* +** +** 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. +*/ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +@JavaDerive(toString=true) +parcelable ProvisioningConfigurationParcelable { + /** + * @deprecated use ipv4ProvisioningMode instead. + */ + boolean enableIPv4; + /** + * @deprecated use ipv6ProvisioningMode instead. + */ + boolean enableIPv6; + boolean usingMultinetworkPolicyTracker; + boolean usingIpReachabilityMonitor; + int requestedPreDhcpActionMs; + android.net.InitialConfigurationParcelable initialConfig; + android.net.StaticIpConfiguration staticIpConfig; + android.net.apf.ApfCapabilities apfCapabilities; + int provisioningTimeoutMs; + int ipv6AddrGenMode; + android.net.Network network; + String displayName; + boolean enablePreconnection; + @nullable android.net.ScanResultInfoParcelable scanResultInfo; + @nullable android.net.Layer2InformationParcelable layer2Info; + @nullable List<android.net.networkstack.aidl.dhcp.DhcpOption> options; + int ipv4ProvisioningMode; + int ipv6ProvisioningMode; + boolean uniqueEui64AddressesOnly; +}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/ScanResultInfoParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/ScanResultInfoParcelable.aidl new file mode 100644 index 0000000..94fc27f --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/ScanResultInfoParcelable.aidl
@@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +@JavaDerive(toString=true) +parcelable ScanResultInfoParcelable { + String ssid; + String bssid; + android.net.InformationElementParcelable[] informationElements; +}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/TcpKeepalivePacketDataParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/TcpKeepalivePacketDataParcelable.aidl new file mode 100644 index 0000000..0e1c21c --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/TcpKeepalivePacketDataParcelable.aidl
@@ -0,0 +1,47 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +@JavaDerive(toString=true) +parcelable TcpKeepalivePacketDataParcelable { + byte[] srcAddress; + int srcPort; + byte[] dstAddress; + int dstPort; + int seq; + int ack; + int rcvWnd; + int rcvWndScale; + int tos; + int ttl; +}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/dhcp/DhcpLeaseParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/dhcp/DhcpLeaseParcelable.aidl new file mode 100644 index 0000000..3cd8860 --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/dhcp/DhcpLeaseParcelable.aidl
@@ -0,0 +1,43 @@ +/** + * Copyright (c) 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing perNmissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net.dhcp; +@JavaDerive(toString=true) +parcelable DhcpLeaseParcelable { + byte[] clientId; + byte[] hwAddr; + int netAddr; + int prefixLength; + long expTime; + String hostname; +}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/dhcp/DhcpServingParamsParcel.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/dhcp/DhcpServingParamsParcel.aidl new file mode 100644 index 0000000..7997936 --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/dhcp/DhcpServingParamsParcel.aidl
@@ -0,0 +1,49 @@ +/** + * + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net.dhcp; +@JavaDerive(toString=true) +parcelable DhcpServingParamsParcel { + int serverAddr; + int serverAddrPrefixLength; + int[] defaultRouters; + int[] dnsServers; + int[] excludedAddrs; + long dhcpLeaseTimeSecs; + int linkMtu; + boolean metered; + int singleClientAddr = 0; + boolean changePrefixOnDecline = false; + int leasesSubnetPrefixLength = 0; +}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/dhcp/IDhcpEventCallbacks.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/dhcp/IDhcpEventCallbacks.aidl new file mode 100644 index 0000000..9312f47 --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/dhcp/IDhcpEventCallbacks.aidl
@@ -0,0 +1,38 @@ +/** + * Copyright (c) 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing perNmissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net.dhcp; +interface IDhcpEventCallbacks { + oneway void onLeasesChanged(in List<android.net.dhcp.DhcpLeaseParcelable> newLeases); + oneway void onNewPrefixRequest(in android.net.IpPrefix currentPrefix); +}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/dhcp/IDhcpServer.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/dhcp/IDhcpServer.aidl new file mode 100644 index 0000000..1109f35 --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/dhcp/IDhcpServer.aidl
@@ -0,0 +1,45 @@ +/** + * Copyright (c) 2018, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing perNmissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net.dhcp; +/* @hide */ +interface IDhcpServer { + oneway void start(in android.net.INetworkStackStatusCallback cb) = 0; + oneway void startWithCallbacks(in android.net.INetworkStackStatusCallback statusCb, in android.net.dhcp.IDhcpEventCallbacks eventCb) = 3; + oneway void updateParams(in android.net.dhcp.DhcpServingParamsParcel params, in android.net.INetworkStackStatusCallback cb) = 1; + oneway void stop(in android.net.INetworkStackStatusCallback cb) = 2; + const int STATUS_UNKNOWN = 0; + const int STATUS_SUCCESS = 1; + const int STATUS_INVALID_ARGUMENT = 2; + const int STATUS_UNKNOWN_ERROR = 3; +}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/dhcp/IDhcpServerCallbacks.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/dhcp/IDhcpServerCallbacks.aidl new file mode 100644 index 0000000..ab8577c --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/dhcp/IDhcpServerCallbacks.aidl
@@ -0,0 +1,38 @@ +/** + * Copyright (c) 2018, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing perNmissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net.dhcp; +/* @hide */ +interface IDhcpServerCallbacks { + oneway void onDhcpServerCreated(int statusCode, in android.net.dhcp.IDhcpServer server); +}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/ip/IIpClient.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/ip/IIpClient.aidl new file mode 100644 index 0000000..b81ec20 --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/ip/IIpClient.aidl
@@ -0,0 +1,59 @@ +/** + * Copyright (c) 2019, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing perNmissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net.ip; +/* @hide */ +interface IIpClient { + oneway void completedPreDhcpAction(); + oneway void confirmConfiguration(); + oneway void readPacketFilterComplete(in byte[] data); + oneway void shutdown(); + oneway void startProvisioning(in android.net.ProvisioningConfigurationParcelable req); + oneway void stop(); + oneway void setTcpBufferSizes(in String tcpBufferSizes); + oneway void setHttpProxy(in android.net.ProxyInfo proxyInfo); + oneway void setMulticastFilter(boolean enabled); + oneway void addKeepalivePacketFilter(int slot, in android.net.TcpKeepalivePacketDataParcelable pkt); + oneway void removeKeepalivePacketFilter(int slot); + oneway void setL2KeyAndGroupHint(in String l2Key, in String cluster); + oneway void addNattKeepalivePacketFilter(int slot, in android.net.NattKeepalivePacketDataParcelable pkt); + oneway void notifyPreconnectionComplete(boolean success); + oneway void updateLayer2Information(in android.net.Layer2InformationParcelable info); + oneway void updateApfCapabilities(in android.net.apf.ApfCapabilities apfCapabilities); + const int PROV_IPV4_DISABLED = 0x00; + const int PROV_IPV4_STATIC = 0x01; + const int PROV_IPV4_DHCP = 0x02; + const int PROV_IPV6_DISABLED = 0x00; + const int PROV_IPV6_SLAAC = 0x01; + const int PROV_IPV6_LINKLOCAL = 0x02; +}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/ip/IIpClientCallbacks.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/ip/IIpClientCallbacks.aidl new file mode 100644 index 0000000..9d36419 --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/ip/IIpClientCallbacks.aidl
@@ -0,0 +1,54 @@ +/** + * Copyright (c) 2019, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing perNmissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net.ip; +/* @hide */ +interface IIpClientCallbacks { + oneway void onIpClientCreated(in android.net.ip.IIpClient ipClient); + oneway void onPreDhcpAction(); + oneway void onPostDhcpAction(); + oneway void onNewDhcpResults(in android.net.DhcpResultsParcelable dhcpResults); + oneway void onProvisioningSuccess(in android.net.LinkProperties newLp); + oneway void onProvisioningFailure(in android.net.LinkProperties newLp); + oneway void onLinkPropertiesChange(in android.net.LinkProperties newLp); + oneway void onReachabilityLost(in String logMsg); + oneway void onQuit(); + oneway void installPacketFilter(in byte[] filter); + oneway void startReadPacketFilter(); + oneway void setFallbackMulticastFilter(boolean enabled); + oneway void setNeighborDiscoveryOffload(boolean enable); + oneway void onPreconnectionStart(in List<android.net.Layer2PacketParcelable> packets); + oneway void onReachabilityFailure(in android.net.networkstack.aidl.ip.ReachabilityLossInfoParcelable lossInfo); + oneway void setMaxDtimMultiplier(int multiplier); + const int DTIM_MULTIPLIER_RESET = 0; +}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/networkstack/aidl/NetworkMonitorParameters.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/networkstack/aidl/NetworkMonitorParameters.aidl new file mode 100644 index 0000000..2ab9db0 --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/networkstack/aidl/NetworkMonitorParameters.aidl
@@ -0,0 +1,41 @@ +/** + * + * Copyright (C) 2022 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net.networkstack.aidl; +@JavaDerive(equals=true, toString=true) +parcelable NetworkMonitorParameters { + android.net.NetworkAgentConfig networkAgentConfig; + android.net.NetworkCapabilities networkCapabilities; + android.net.LinkProperties linkProperties; +}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/networkstack/aidl/dhcp/DhcpOption.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/networkstack/aidl/dhcp/DhcpOption.aidl new file mode 100644 index 0000000..eea3e0d --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/networkstack/aidl/dhcp/DhcpOption.aidl
@@ -0,0 +1,39 @@ +/** + * Copyright (c) 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing perNmissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net.networkstack.aidl.dhcp; +@JavaDerive(toString=true) +parcelable DhcpOption { + byte type; + @nullable byte[] value; +}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/networkstack/aidl/ip/ReachabilityLossInfoParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/networkstack/aidl/ip/ReachabilityLossInfoParcelable.aidl new file mode 100644 index 0000000..bb88434 --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/networkstack/aidl/ip/ReachabilityLossInfoParcelable.aidl
@@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net.networkstack.aidl.ip; +@JavaDerive(equals=true, toString=true) @JavaOnlyImmutable +parcelable ReachabilityLossInfoParcelable { + String message; + android.net.networkstack.aidl.ip.ReachabilityLossReason reason; +}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/networkstack/aidl/ip/ReachabilityLossReason.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/networkstack/aidl/ip/ReachabilityLossReason.aidl new file mode 100644 index 0000000..f9bb3c4 --- /dev/null +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/19/android/net/networkstack/aidl/ip/ReachabilityLossReason.aidl
@@ -0,0 +1,40 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net.networkstack.aidl.ip; +@Backing(type="int") +enum ReachabilityLossReason { + ROAM, + CONFIRM, + ORGANIC, +}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/PrivateDnsConfigParcel.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/PrivateDnsConfigParcel.aidl index 1457caf..ab62fe7 100644 --- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/PrivateDnsConfigParcel.aidl +++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/PrivateDnsConfigParcel.aidl
@@ -32,8 +32,13 @@ // later when a module using the interface is updated, e.g., Mainline modules. package android.net; -@JavaDerive(toString=true) +@JavaDerive(equals=true, toString=true) parcelable PrivateDnsConfigParcel { String hostname; String[] ips; + int privateDnsMode = (-1) /* -1 */; + String dohName = ""; + String[] dohIps = {}; + String dohPath = ""; + int dohPort = (-1) /* -1 */; }
diff --git a/common/networkstackclient/src/android/net/PrivateDnsConfigParcel.aidl b/common/networkstackclient/src/android/net/PrivateDnsConfigParcel.aidl index 97bb697..e747d61 100644 --- a/common/networkstackclient/src/android/net/PrivateDnsConfigParcel.aidl +++ b/common/networkstackclient/src/android/net/PrivateDnsConfigParcel.aidl
@@ -16,8 +16,60 @@ package android.net; -@JavaDerive(toString=true) +@JavaDerive(equals=true, toString=true) parcelable PrivateDnsConfigParcel { + /** + * The hostname of private DNS provider. + */ String hostname; + + /** + * The DoT server IP addresses of `hostname`. They are not sorted. + */ String[] ips; + + /** + * The private DNS mode associated with this PrivateDnsConfigParcel. + * If it's set, the value must be one of the following constants defined in + * ConnectivitySettingsManager. + * - PRIVATE_DNS_MODE_OFF (1) + * - PRIVATE_DNS_MODE_OPPORTUNISTIC (2) + * - PRIVATE_DNS_MODE_PROVIDER_HOSTNAME (3) + * + * For compatibility with old PrivateDnsConfigParcel, set the default value to -1 to indicate + * that the sender is using an old version of PrivateDnsConfigParcel and that the receiver + * cannot determine the private DNS mode by reading this field. + */ + int privateDnsMode = -1; + + /** + * The following fields with the prefix "doh" store the DoH3 information discovered from + * DDR. The similar fields are defined in DnsResolver as well. Although duplicating code + * is not a good idea, it avoids the complexity and confusion of having a parcelable + * containing a nested parcelable where the client and server could have a different version + * of the nested parcelable. + */ + + /** + * The DoH server hostname derived from TargetName field of a DNS SVCB response. + */ + String dohName = ""; + + /** + * The DoH server IP addresses of `dohName`. They are not sorted. + */ + String[] dohIps = {}; + + /** + * A part of the URI template used to construct the URL for DNS resolution. + * It's derived only from DNS SVCB SvcParamKey "dohpath". + * The URI template for DNS resolution is as follows: + * https://<dohName>/<dohPath> + */ + String dohPath = ""; + + /** + * The port used to reach the DoH servers. + */ + int dohPort = -1; }
diff --git a/common/networkstackclient/src/android/net/shared/PrivateDnsConfig.java b/common/networkstackclient/src/android/net/shared/PrivateDnsConfig.java index 106ca1c..632d1d6 100644 --- a/common/networkstackclient/src/android/net/shared/PrivateDnsConfig.java +++ b/common/networkstackclient/src/android/net/shared/PrivateDnsConfig.java
@@ -16,9 +16,14 @@ package android.net.shared; +import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OFF; +import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OPPORTUNISTIC; +import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME; import static android.net.shared.ParcelableUtil.fromParcelableArray; import static android.net.shared.ParcelableUtil.toParcelableArray; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.net.PrivateDnsConfigParcel; import android.text.TextUtils; @@ -27,50 +32,116 @@ /** @hide */ public class PrivateDnsConfig { - public final boolean useTls; + // These fields store the private DNS configuration from setting. + public final int mode; + @NonNull public final String hostname; + + // Stores the DoT server IP addresses resolved from A/AAAA lookups. + @NonNull public final InetAddress[] ips; + // These fields store the DoH information discovered from SVCB lookups. + @NonNull + public final String dohName; + @NonNull + public final InetAddress[] dohIps; + @NonNull + public final String dohPath; + public final int dohPort; + + /** + * A constructor for off mode private DNS configuration. + * TODO(b/261404136): Consider simplifying the constructors. One possible way is to + * use constants to represent private DNS modes: + * public static PrivateDnsConfig OFF = new PrivateDnsConfig(false); + * public static PrivateDnsConfig OPPORTUNISTIC = new PrivateDnsConfig(true); + * public static PrivateDnsConfig STRICT = new PrivateDnsConfig(String hostname); + */ public PrivateDnsConfig() { this(false); } + /** + * A constructor for off/opportunistic mode private DNS configuration depending on `useTls`. + */ public PrivateDnsConfig(boolean useTls) { - this.useTls = useTls; - this.hostname = ""; - this.ips = new InetAddress[0]; + this(useTls ? PRIVATE_DNS_MODE_OPPORTUNISTIC : PRIVATE_DNS_MODE_OFF, null /* hostname */, + null /* ips */, null /* dohName */, null /* dohIps */, null /* dohPath */, + -1 /* dohPort */); } - public PrivateDnsConfig(String hostname, InetAddress[] ips) { - this.useTls = !TextUtils.isEmpty(hostname); - this.hostname = useTls ? hostname : ""; - this.ips = (ips != null) ? ips : new InetAddress[0]; + /** + * A constructor for off/strict mode private DNS configuration depending on `hostname`. + * If `hostname` is empty or null, this constructor creates a PrivateDnsConfig for off mode; + * otherwise, it creates a PrivateDnsConfig for strict mode. + */ + public PrivateDnsConfig(@Nullable String hostname, @Nullable InetAddress[] ips) { + this(TextUtils.isEmpty(hostname) ? PRIVATE_DNS_MODE_OFF : + PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, hostname, ips, null /* dohName */, + null /* dohIps */, null /* dohPath */, -1 /* dohPort */); + } + + /** + * A constructor for all kinds of private DNS configuration with given DoH information. + * It treats both null values and empty strings as equivalent. Similarly, treats null values + * and empty arrays as equivalent. + */ + public PrivateDnsConfig(int mode, @Nullable String hostname, @Nullable InetAddress[] ips, + @Nullable String dohName, @Nullable InetAddress[] dohIps, @Nullable String dohPath, + int dohPort) { + this.mode = mode; + this.hostname = (hostname != null) ? hostname : ""; + this.ips = (ips != null) ? ips.clone() : new InetAddress[0]; + this.dohName = (dohName != null) ? dohName : ""; + this.dohIps = (dohIps != null) ? dohIps.clone() : new InetAddress[0]; + this.dohPath = (dohPath != null) ? dohPath : ""; + this.dohPort = dohPort; } public PrivateDnsConfig(PrivateDnsConfig cfg) { - useTls = cfg.useTls; + mode = cfg.mode; hostname = cfg.hostname; ips = cfg.ips; + dohName = cfg.dohName; + dohIps = cfg.dohIps; + dohPath = cfg.dohPath; + dohPort = cfg.dohPort; } /** * Indicates whether this is a strict mode private DNS configuration. */ public boolean inStrictMode() { - return useTls && !TextUtils.isEmpty(hostname); + return mode == PRIVATE_DNS_MODE_PROVIDER_HOSTNAME; } /** * Indicates whether this is an opportunistic mode private DNS configuration. */ public boolean inOpportunisticMode() { - return useTls && TextUtils.isEmpty(hostname); + return mode == PRIVATE_DNS_MODE_OPPORTUNISTIC; } @Override public String toString() { return PrivateDnsConfig.class.getSimpleName() - + "{" + useTls + ":" + hostname + "/" + Arrays.toString(ips) + "}"; + + "{" + modeAsString(mode) + ":" + hostname + "/" + Arrays.toString(ips) + + ", dohName=" + dohName + + ", dohIps=" + Arrays.toString(dohIps) + + ", dohPath=" + dohPath + + ", dohPort=" + dohPort + + "}"; + } + + @NonNull + private static String modeAsString(int mode) { + switch (mode) { + case PRIVATE_DNS_MODE_OFF: return "off"; + case PRIVATE_DNS_MODE_OPPORTUNISTIC: return "opportunistic"; + case PRIVATE_DNS_MODE_PROVIDER_HOSTNAME: return "strict"; + default: return "unknown"; + } } /** @@ -81,7 +152,12 @@ parcel.hostname = hostname; parcel.ips = toParcelableArray( Arrays.asList(ips), IpConfigurationParcelableUtil::parcelAddress, String.class); - + parcel.privateDnsMode = mode; + parcel.dohName = dohName; + parcel.dohIps = toParcelableArray( + Arrays.asList(dohIps), IpConfigurationParcelableUtil::parcelAddress, String.class); + parcel.dohPath = dohPath; + parcel.dohPort = dohPort; return parcel; } @@ -92,6 +168,26 @@ InetAddress[] ips = new InetAddress[parcel.ips.length]; ips = fromParcelableArray(parcel.ips, IpConfigurationParcelableUtil::unparcelAddress) .toArray(ips); - return new PrivateDnsConfig(parcel.hostname, ips); + + // For compatibility. If the sender (Tethering module) is using an old version (< 19) of + // NetworkStack AIDL that `privateDnsMode` field is not present, `privateDnsMode` will be + // assigned from the default value -1. Let `privateDnsMode` assigned based on the hostname. + // In this case, there is a harmless bug that the receiver (NetworkStack module) can't + // convert the parcel to a PrivateDnsConfig that indicates opportunistic mode. + // The bug is harmless because 1) the bug exists for years without any problems and + // 2) NetworkMonitor cares PrivateDnsConfig that indicates strict/off mode only. + // If the sender is using new version (>=19) while the receiver is using an old version, + // the above mentioned harmless bug will persist. Except for that harmless bug, there + // should be no other issues. New version's toParcel() doesn't change how the pre-existing + // fields `hostname` and `ips` are assigned. + if (parcel.privateDnsMode == -1) { + return new PrivateDnsConfig(parcel.hostname, ips); + } + + InetAddress[] dohIps = new InetAddress[parcel.dohIps.length]; + dohIps = fromParcelableArray(parcel.dohIps, + IpConfigurationParcelableUtil::unparcelAddress).toArray(dohIps); + return new PrivateDnsConfig(parcel.privateDnsMode, parcel.hostname, ips, parcel.dohName, + dohIps, parcel.dohPath, parcel.dohPort); } }
diff --git a/src/android/net/apf/ApfFilter.java b/src/android/net/apf/ApfFilter.java index 41c6726..3ab5e0e 100644 --- a/src/android/net/apf/ApfFilter.java +++ b/src/android/net/apf/ApfFilter.java
@@ -17,6 +17,8 @@ package android.net.apf; import static android.net.util.SocketUtils.makePacketSocketAddress; +import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED; +import static android.os.PowerManager.ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED; import static android.system.OsConstants.AF_PACKET; import static android.system.OsConstants.ARPHRD_ETHER; import static android.system.OsConstants.ETH_P_ARP; @@ -54,6 +56,7 @@ import android.util.Log; import android.util.SparseArray; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.internal.annotations.GuardedBy; @@ -61,6 +64,7 @@ import com.android.internal.util.HexDump; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.TokenBucket; +import com.android.modules.utils.build.SdkLevel; import com.android.net.module.util.CollectionUtils; import com.android.net.module.util.ConnectivityUtils; import com.android.net.module.util.InterfaceParams; @@ -112,6 +116,7 @@ public int[] ethTypeBlackList; public int minRdnssLifetimeSec; public int acceptRaMinLft; + public boolean shouldHandleLightDoze; } /** @@ -132,8 +137,6 @@ PASSED_IPV4_UNICAST, PASSED_IPV6_ICMP, PASSED_IPV6_UNICAST_NON_ICMP, - PASSED_ARP_NON_IPV4, - PASSED_ARP_UNKNOWN, PASSED_ARP_UNICAST_REPLY, PASSED_NON_IP_UNICAST, PASSED_MDNS, @@ -156,7 +159,9 @@ DROPPED_IPV4_KEEPALIVE_ACK, DROPPED_IPV6_KEEPALIVE_ACK, DROPPED_IPV4_NATT_KEEPALIVE, - DROPPED_MDNS; + DROPPED_MDNS, + DROPPED_ARP_NON_IPV4, + DROPPED_ARP_UNKNOWN; // Returns the negative byte offset from the end of the APF data segment for // a given counter. @@ -323,16 +328,48 @@ // Tracks the value of /proc/sys/ipv6/conf/$iface/accept_ra_min_lft which affects router, RIO, // and PIO valid lifetimes. private final int mAcceptRaMinLft; + private final boolean mShouldHandleLightDoze; + + private static boolean isDeviceIdleModeChangedAction(Intent intent) { + return ACTION_DEVICE_IDLE_MODE_CHANGED.equals(intent.getAction()); + } + + private boolean isDeviceLightIdleModeChangedAction(Intent intent) { + // The ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED only exist since T. For lower platform version, + // the check should return false. The explicit SDK check is needed to make linter happy + // about accessing ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED in this function. + if (!SdkLevel.isAtLeastT()) { + return false; + } + if (!mShouldHandleLightDoze) { + return false; + } + return ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED.equals(intent.getAction()); + } + + private boolean isDeviceLightIdleMode(@NonNull PowerManager powerManager) { + // The powerManager.isDeviceLightIdleMode() only exist since T. For lower platform version, + // the check should return false. The explicit SDK check is needed to make linter happy + // about accessing powerManager.isDeviceLightIdleMode() in this function. + if (!SdkLevel.isAtLeastT()) { + return false; + } + if (!mShouldHandleLightDoze) { + return false; + } + + return powerManager.isDeviceLightIdleMode(); + } // Detects doze mode state transitions. private final BroadcastReceiver mDeviceIdleReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (action.equals(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)) { - PowerManager powerManager = - (PowerManager) context.getSystemService(Context.POWER_SERVICE); - final boolean deviceIdle = powerManager.isDeviceIdleMode(); + final PowerManager powerManager = context.getSystemService(PowerManager.class); + if (isDeviceIdleModeChangedAction(intent) + || isDeviceLightIdleModeChangedAction(intent)) { + final boolean deviceIdle = powerManager.isDeviceIdleMode() + || isDeviceLightIdleMode(powerManager); setDozeMode(deviceIdle); } } @@ -346,9 +383,16 @@ @GuardedBy("this") private int mIPv4PrefixLength; - @VisibleForTesting + private final Dependencies mDependencies; + public ApfFilter(Context context, ApfConfiguration config, InterfaceParams ifParams, IpClientCallbacksWrapper ipClientCallback) { + this(context, config, ifParams, ipClientCallback, new Dependencies(context)); + } + + @VisibleForTesting + public ApfFilter(Context context, ApfConfiguration config, InterfaceParams ifParams, + IpClientCallbacksWrapper ipClientCallback, Dependencies dependencies) { mApfCapabilities = config.apfCapabilities; mIpClientCallback = ipClientCallback; mInterfaceParams = ifParams; @@ -357,6 +401,8 @@ mMinRdnssLifetimeSec = config.minRdnssLifetimeSec; mAcceptRaMinLft = config.acceptRaMinLft; mContext = context; + mShouldHandleLightDoze = config.shouldHandleLightDoze; + mDependencies = dependencies; if (mApfCapabilities.hasDataAccess()) { mCountAndPassLabel = "countAndPass"; @@ -384,8 +430,33 @@ maybeStartFilter(); // Listen for doze-mode transition changes to enable/disable the IPv6 multicast filter. - mContext.registerReceiver(mDeviceIdleReceiver, - new IntentFilter(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)); + mDependencies.addDeviceIdleReceiver(mDeviceIdleReceiver, mShouldHandleLightDoze); + } + + /** + * Dependencies class for testing. + */ + @VisibleForTesting + public static class Dependencies { + private final Context mContext; + public Dependencies(final Context context) { + mContext = context; + } + + /** Add receiver for detecting doze mode change */ + public void addDeviceIdleReceiver(@NonNull final BroadcastReceiver receiver, + boolean shouldHandleLightDoze) { + final IntentFilter intentFilter = new IntentFilter(ACTION_DEVICE_IDLE_MODE_CHANGED); + if (SdkLevel.isAtLeastT() && shouldHandleLightDoze) { + intentFilter.addAction(ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED); + } + mContext.registerReceiver(receiver, intentFilter); + } + + /** Remove broadcast receiver. */ + public void removeBroadcastReceiver(@NonNull final BroadcastReceiver receiver) { + mContext.unregisterReceiver(receiver); + } } public synchronized void setDataSnapshot(byte[] data) { @@ -1360,9 +1431,9 @@ // Here's a basic summary of what the ARP filter program does: // // if not ARP IPv4 - // pass + // drop // if not ARP IPv4 reply or request - // pass + // drop // if ARP reply source ip is 0.0.0.0 // drop // if unicast ARP reply @@ -1377,28 +1448,28 @@ final String checkTargetIPv4 = "checkTargetIPv4"; - // Pass if not ARP IPv4. + // Drop if not ARP IPv4. gen.addLoadImmediate(Register.R0, ARP_HEADER_OFFSET); - maybeSetupCounter(gen, Counter.PASSED_ARP_NON_IPV4); - gen.addJumpIfBytesNotEqual(Register.R0, ARP_IPV4_HEADER, mCountAndPassLabel); + maybeSetupCounter(gen, Counter.DROPPED_ARP_NON_IPV4); + gen.addJumpIfBytesNotEqual(Register.R0, ARP_IPV4_HEADER, mCountAndDropLabel); - // Pass if unknown ARP opcode. + // Drop if unknown ARP opcode. gen.addLoad16(Register.R0, ARP_OPCODE_OFFSET); gen.addJumpIfR0Equals(ARP_OPCODE_REQUEST, checkTargetIPv4); // Skip to unicast check - maybeSetupCounter(gen, Counter.PASSED_ARP_UNKNOWN); - gen.addJumpIfR0NotEquals(ARP_OPCODE_REPLY, mCountAndPassLabel); + maybeSetupCounter(gen, Counter.DROPPED_ARP_UNKNOWN); + gen.addJumpIfR0NotEquals(ARP_OPCODE_REPLY, mCountAndDropLabel); // Drop if ARP reply source IP is 0.0.0.0 gen.addLoad32(Register.R0, ARP_SOURCE_IP_ADDRESS_OFFSET); maybeSetupCounter(gen, Counter.DROPPED_ARP_REPLY_SPA_NO_HOST); gen.addJumpIfR0Equals(IPV4_ANY_HOST_ADDRESS, mCountAndDropLabel); - // Pass if unicast reply. + // Pass if non-broadcast reply. gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET); maybeSetupCounter(gen, Counter.PASSED_ARP_UNICAST_REPLY); gen.addJumpIfBytesNotEqual(Register.R0, ETHER_BROADCAST, mCountAndPassLabel); - // Either a unicast request, a unicast reply, or a broadcast reply. + // Either a request, or a broadcast reply. gen.defineLabel(checkTargetIPv4); if (mIPv4Address == null) { // When there is no IPv4 address, drop GARP replies (b/29404209). @@ -2052,7 +2123,7 @@ mReceiveThread = null; } mRas.clear(); - mContext.unregisterReceiver(mDeviceIdleReceiver); + mDependencies.removeBroadcastReceiver(mDeviceIdleReceiver); } public synchronized void setMulticastFilter(boolean isEnabled) { @@ -2087,6 +2158,11 @@ installNewProgramLocked(); } + @VisibleForTesting + public synchronized boolean isInDozeMode() { + return mInDozeMode; + } + /** Find the single IPv4 LinkAddress if there is one, otherwise return null. */ private static LinkAddress findIPv4LinkAddress(LinkProperties lp) { LinkAddress ipv4Address = null;
diff --git a/src/android/net/dhcp6/Dhcp6Client.java b/src/android/net/dhcp6/Dhcp6Client.java index 7359c7c..1511669 100644 --- a/src/android/net/dhcp6/Dhcp6Client.java +++ b/src/android/net/dhcp6/Dhcp6Client.java
@@ -59,6 +59,7 @@ import com.android.net.module.util.InterfaceParams; import com.android.net.module.util.PacketReader; import com.android.net.module.util.netlink.NetlinkUtils; +import com.android.net.module.util.structs.IaPrefixOption; import java.io.FileDescriptor; import java.io.IOException; @@ -66,6 +67,7 @@ import java.net.SocketException; import java.nio.ByteBuffer; import java.util.Arrays; +import java.util.Collections; import java.util.Random; import java.util.function.IntSupplier; @@ -282,17 +284,27 @@ scheduleKick(); } - private void handleReceivedPacket(Dhcp6Packet packet) { + private void handleReceivedPacket(@NonNull final Dhcp6Packet packet) { // Technically it is valid for the server to not include a prefix in an IA in certain // scenarios (specifically in a reply to Renew / Rebind, which means: do not extend the - // prefix). However, while only supporting a single prefix, this never works well, so if - // the server decides to do so, ignore it. - // TODO: revisit this when adding multi-prefix support. - final boolean validIpo = packet.mPrefixDelegation.ipo != null - && packet.mPrefixDelegation.ipo.isValid(); - if (packet.isValid(mTransId, mClientDuid) && validIpo) { - receivePacket(packet); + // prefix, e.g. the list of prefix is empty). However, if prefix(es) do exist and all + // prefixes are invalid, then we should just ignore this packet. + if (!packet.isValid(mTransId, mClientDuid)) return; + if (!packet.mPrefixDelegation.ipos.isEmpty()) { + boolean allInvalidPrefixes = true; + for (IaPrefixOption ipo : packet.mPrefixDelegation.ipos) { + if (ipo != null && ipo.isValid()) { + allInvalidPrefixes = false; + break; + } + } + if (allInvalidPrefixes) { + Log.w(TAG, "All IA_Prefix options included in the " + + packet.getClass().getSimpleName() + " are invalid, ignore it."); + return; + } } + receivePacket(packet); } @Override @@ -377,17 +389,18 @@ // prevent packet storms due to low timeouts. int renewTimeout = mReply.t1; int rebindTimeout = mReply.t2; - final long expirationTimeout = mReply.ipo.valid; + final long preferredTimeout = mReply.getMinimalPreferredLifetime(); + final long expirationTimeout = mReply.getMinimalValidLifetime(); // rfc8415#section-14.2: if t1 and / or t2 are 0, the client chooses an appropriate value. // rfc8415#section-21.21: Recommended values for T1 and T2 are 0.5 and 0.8 times the // shortest preferred lifetime of the prefixes in the IA_PD that the server is willing to // extend, respectively. if (renewTimeout == 0) { - renewTimeout = (int) (mReply.ipo.preferred * 0.5); + renewTimeout = (int) (preferredTimeout * 0.5); } if (rebindTimeout == 0) { - rebindTimeout = (int) (mReply.ipo.preferred * 0.8); + rebindTimeout = (int) (preferredTimeout * 0.8); } // Note: message validation asserts that the received t1 <= t2 if both t1 > 0 and t2 > 0. @@ -461,16 +474,6 @@ return transmitPacket(packet, "rebind"); } - private ByteBuffer buildEmptyIaPdOption() { - return Dhcp6Packet.buildIaPdOption(IAID, 0 /* t1 */, 0 /* t2 */, 0 /* preferred */, - 0 /* valid */, new byte[16] /* empty prefix */, (byte) RFC7421_PREFIX_LENGTH); - } - - private ByteBuffer buildIaPdOption(@NonNull final PrefixDelegation pd) { - return Dhcp6Packet.buildIaPdOption(pd.iaid, pd.t1, pd.t2, pd.ipo.preferred, pd.ipo.valid, - pd.ipo.prefix, pd.ipo.prefixLen); - } - /** * Parent state at which client does initialization of interface and packet handler, also * processes the CMD_STOP_DHCP6 command in this state which child states don't handle. @@ -545,7 +548,12 @@ @Override protected boolean sendPacket(int transId, long elapsedTimeMs) { - return sendSolicitPacket(transId, elapsedTimeMs, buildEmptyIaPdOption()); + final IaPrefixOption hintOption = new IaPrefixOption((short) IaPrefixOption.LENGTH, + 0 /* preferred */, 0 /* valid */, (byte) RFC7421_PREFIX_LENGTH, + new byte[16] /* empty prefix */); + final PrefixDelegation pd = new PrefixDelegation(IAID, 0 /* t1 */, 0 /* t2 */, + Collections.singletonList(hintOption)); + return sendSolicitPacket(transId, elapsedTimeMs, pd.build()); } // TODO: support multiple prefixes. @@ -585,7 +593,7 @@ @Override protected boolean sendPacket(int transId, long elapsedTimeMs) { - return sendRequestPacket(transId, elapsedTimeMs, buildIaPdOption(mAdvertise)); + return sendRequestPacket(transId, elapsedTimeMs, mAdvertise.build()); } @Override @@ -646,7 +654,7 @@ // generation (with IFA_F_MANAGETEMPADDR), we always set the address prefix length to // 64, even if the delegated prefix length is less than 64. However, the unreachable // route should still use the assigned prefix length. - final IpPrefix routePrefix = mReply.ipo.getIpPrefix(); + final IpPrefix routePrefix = mReply.ipos.get(0).getIpPrefix(); final IpPrefix addressPrefix = new IpPrefix(routePrefix.getAddress(), RFC7421_PREFIX_LENGTH); // Create EUI-64, so we don't need to remember IPv6 addresses that need to extend the @@ -655,8 +663,9 @@ macAddressToEui64(mIface.macAddr)); final int flags = IFA_F_NOPREFIXROUTE | IFA_F_MANAGETEMPADDR | IFA_F_NODAD; final long now = SystemClock.elapsedRealtime(); - final long deprecationTime = now + mReply.ipo.preferred; - final long expirationTime = now + mReply.ipo.valid; + final IaPrefixOption ipo = mReply.ipos.get(0); + final long deprecationTime = now + ipo.preferred; + final long expirationTime = now + ipo.valid; final LinkAddress la = new LinkAddress(address, RFC7421_PREFIX_LENGTH, flags, RT_SCOPE_UNIVERSE /* scope */, deprecationTime, expirationTime); if (!la.isGlobalPreferred()) { @@ -666,7 +675,7 @@ if (!NetlinkUtils.sendRtmNewAddressRequest(mIface.index, address, (short) RFC7421_PREFIX_LENGTH, flags, (byte) RT_SCOPE_UNIVERSE /* scope */, - mReply.ipo.preferred, mReply.ipo.valid)) { + ipo.preferred, ipo.valid)) { Log.e(TAG, "Failed to set IPv6 address " + address.getHostAddress() + "%" + mIface.index); return; @@ -701,11 +710,13 @@ protected void receivePacket(Dhcp6Packet packet) { if (!(packet instanceof Dhcp6ReplyPacket)) return; final PrefixDelegation pd = packet.mPrefixDelegation; - if (!(Arrays.equals(pd.ipo.prefix, mReply.ipo.prefix) - && pd.ipo.prefixLen == mReply.ipo.prefixLen)) { - Log.i(TAG, "Renewal prefix " + HexDump.toHexString(pd.ipo.prefix) + final IaPrefixOption request = mReply.ipos.get(0); + final IaPrefixOption response = pd.ipos.get(0); + if (!(Arrays.equals(request.prefix, response.prefix) + && request.prefixLen == response.prefixLen)) { + Log.i(TAG, "Renewal prefix " + HexDump.toHexString(response.prefix) + " does not match current prefix " - + HexDump.toHexString(mReply.ipo.prefix)); + + HexDump.toHexString(request.prefix)); notifyPrefixDelegation(DHCP6_PD_PREFIX_CHANGED, null); transitionTo(mSolicitState); return; @@ -748,7 +759,7 @@ @Override protected boolean sendPacket(int transId, long elapsedTimeMs) { - return sendRenewPacket(transId, elapsedTimeMs, buildIaPdOption(mReply)); + return sendRenewPacket(transId, elapsedTimeMs, mReply.build()); } } @@ -764,7 +775,7 @@ @Override protected boolean sendPacket(int transId, long elapsedTimeMs) { - return sendRebindPacket(transId, elapsedTimeMs, buildIaPdOption(mReply)); + return sendRebindPacket(transId, elapsedTimeMs, mReply.build()); } }
diff --git a/src/android/net/dhcp6/Dhcp6Packet.java b/src/android/net/dhcp6/Dhcp6Packet.java index 540a670..250aa73 100644 --- a/src/android/net/dhcp6/Dhcp6Packet.java +++ b/src/android/net/dhcp6/Dhcp6Packet.java
@@ -22,8 +22,8 @@ import android.util.Log; import androidx.annotation.NonNull; -import androidx.annotation.VisibleForTesting; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.HexDump; import com.android.net.module.util.Struct; import com.android.net.module.util.structs.IaPdOption; @@ -33,7 +33,11 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Objects; import java.util.OptionalInt; /** @@ -120,6 +124,11 @@ protected PrefixDelegation mPrefixDelegation; /** + * DHCPv6 Optional Type: IA Prefix Option. + */ + public static final byte DHCP6_IAPREFIX = 26; + + /** * DHCPv6 Optional Type: SOL_MAX_RT. */ public static final byte DHCP6_SOL_MAX_RT = 82; @@ -155,6 +164,14 @@ } /** + * Returns decoded IA_PD options associated with IA_ID. + */ + @VisibleForTesting + public PrefixDelegation getPrefixDelegation() { + return mPrefixDelegation; + } + + /** * Returns IA_ID associated to IA_PD. */ public int getIaId() { @@ -188,16 +205,19 @@ * https://www.rfc-editor.org/rfc/rfc8415.html#section-21.21 */ public static class PrefixDelegation { - public int iaid; - public int t1; - public int t2; - public final IaPrefixOption ipo; + public final int iaid; + public final int t1; + public final int t2; + @NonNull + public final List<IaPrefixOption> ipos; - PrefixDelegation(int iaid, int t1, int t2, final IaPrefixOption ipo) { + public PrefixDelegation(int iaid, int t1, int t2, + @NonNull final List<IaPrefixOption> ipos) { + Objects.requireNonNull(ipos); this.iaid = iaid; this.t1 = t1; this.t2 = t2; - this.ipo = ipo; + this.ipos = ipos; } /** @@ -214,7 +234,6 @@ Log.e(TAG, "IA_PD option with invalid T1 " + t1 + " or T2 " + t2); return false; } - // Generally, t1 must be smaller or equal to t2 (except when t2 is 0). if (t2 != 0 && t1 > t2) { Log.e(TAG, "IA_PD option with T1 " + t1 + " greater than T2 " + t2); @@ -223,10 +242,95 @@ return true; } + /** + * Decode an IA_PD option from the byte buffer. + */ + public static PrefixDelegation decode(@NonNull final ByteBuffer buffer) + throws ParseException { + try { + final int iaid = buffer.getInt(); + final int t1 = buffer.getInt(); + final int t2 = buffer.getInt(); + final List<IaPrefixOption> ipos = new ArrayList<IaPrefixOption>(); + while (buffer.remaining() > 0) { + final int original = buffer.position(); + final short optionType = buffer.getShort(); + final int optionLen = buffer.getShort() & 0xFFFF; + switch (optionType) { + case DHCP6_IAPREFIX: + buffer.position(original); + final IaPrefixOption ipo = Struct.parse(IaPrefixOption.class, buffer); + Log.d(TAG, "IA Prefix Option: " + ipo); + ipos.add(ipo); + break; + // TODO: support DHCP6_STATUS_CODE option + default: + skipOption(buffer, optionLen); + } + } + return new PrefixDelegation(iaid, t1, t2, ipos); + } catch (BufferUnderflowException e) { + throw new ParseException(e.getMessage()); + } + } + + /** + * Build an IA_PD option from given specific parameters, including IA_PREFIX options. + */ + public ByteBuffer build() { + final ByteBuffer iapd = ByteBuffer.allocate(IaPdOption.LENGTH + + Struct.getSize(IaPrefixOption.class) * ipos.size()); + iapd.putInt(iaid); + iapd.putInt(t1); + iapd.putInt(t2); + for (IaPrefixOption ipo : ipos) { + ipo.writeToByteBuffer(iapd); + } + iapd.flip(); + return iapd; + } + + /** + * Return valid IA prefix options to be used and extended in the Reply message. It may + * return empty list if there isn't any valid IA prefix option in the Reply message. + * + * TODO: ensure that the prefix has a reasonable lifetime, and the timers aren't too short. + * and handle status code such as NoPrefixAvail. + */ + public List<IaPrefixOption> getValidIaPrefixes() { + final List<IaPrefixOption> validIpos = new ArrayList<IaPrefixOption>(); + for (IaPrefixOption ipo : ipos) { + if (!ipo.isValid()) continue; + validIpos.add(ipo); + } + return validIpos; + } + @Override public String toString() { return "Prefix Delegation: iaid " + iaid + ", t1 " + t1 + ", t2 " + t2 - + ", prefix " + ipo; + + ", IA prefix options: " + ipos; + } + + /** + * Compare the preferred lifetime in the IA prefix optin list and return the minimum one. + * TODO: exclude 0 preferred lifetime. + */ + public long getMinimalPreferredLifetime() { + final IaPrefixOption ipo = Collections.min(ipos, + (IaPrefixOption lhs, IaPrefixOption rhs) -> Long.compare(lhs.preferred, + rhs.preferred)); + return ipo.preferred; + } + + /** + * Compare the valid lifetime in the IA prefix optin list and return the minimum one. + * TODO: exclude 0 valid lifetime. + */ + public long getMinimalValidLifetime() { + final IaPrefixOption ipo = Collections.min(ipos, + (IaPrefixOption lhs, IaPrefixOption rhs) -> Long.compare(lhs.valid, rhs.valid)); + return ipo.valid; } } @@ -293,8 +397,7 @@ * | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ - @VisibleForTesting - static Dhcp6Packet decode(@NonNull final ByteBuffer packet) throws ParseException { + private static Dhcp6Packet decode(@NonNull final ByteBuffer packet) throws ParseException { int elapsedTime = 0; byte[] iapd = null; byte[] serverDuid = null; @@ -303,6 +406,7 @@ String statusMsg = null; boolean rapidCommit = false; int solMaxRt = 0; + PrefixDelegation pd = null; packet.order(ByteOrder.BIG_ENDIAN); @@ -347,6 +451,7 @@ final byte[] bytes = new byte[expectedLen]; packet.get(bytes, 0 /* offset */, expectedLen); iapd = bytes; + pd = PrefixDelegation.decode(ByteBuffer.wrap(iapd)); break; case DHCP6_RAPID_COMMIT: expectedLen = 0; @@ -410,14 +515,9 @@ throw new ParseException("Unimplemented DHCP6 message type %d" + messageType); } - if (iapd != null) { - final ByteBuffer buffer = ByteBuffer.wrap(iapd); - final int iaid = buffer.getInt(); - final int t1 = buffer.getInt(); - final int t2 = buffer.getInt(); - final IaPrefixOption ipo = Struct.parse(IaPrefixOption.class, buffer); - newPacket.mPrefixDelegation = new PrefixDelegation(iaid, t1, t2, ipo); - newPacket.mIaId = iaid; + if (pd != null) { + newPacket.mPrefixDelegation = pd; + newPacket.mIaId = pd.iaid; } newPacket.mStatusCode = statusCode; newPacket.mStatusMsg = statusMsg; @@ -528,23 +628,6 @@ } /** - * Build an IA_PD option from given specific parameters, including IA_PREFIX option. - */ - public static ByteBuffer buildIaPdOption(int iaid, int t1, int t2, long preferred, long valid, - final byte[] prefix, byte prefixLen) { - final ByteBuffer iapd = ByteBuffer.allocate(IaPdOption.LENGTH - + Struct.getSize(IaPrefixOption.class)); - iapd.putInt(iaid); - iapd.putInt(t1); - iapd.putInt(t2); - final ByteBuffer prefixOption = IaPrefixOption.build((short) IaPrefixOption.LENGTH, - preferred, valid, prefixLen, prefix); - iapd.put(prefixOption); - iapd.flip(); - return iapd; - } - - /** * Builds a DHCPv6 SOLICIT packet from the required specified parameters. */ public static ByteBuffer buildSolicitPacket(int transId, long millisecs,
diff --git a/src/android/net/ip/IpClient.java b/src/android/net/ip/IpClient.java index 11cdd20..9747c2c 100644 --- a/src/android/net/ip/IpClient.java +++ b/src/android/net/ip/IpClient.java
@@ -40,10 +40,12 @@ import static com.android.net.module.util.NetworkStackConstants.IPV6_ADDR_ALL_ROUTERS_MULTICAST; import static com.android.net.module.util.NetworkStackConstants.RFC7421_PREFIX_LENGTH; import static com.android.net.module.util.NetworkStackConstants.VENDOR_SPECIFIC_IE_ID; +import static com.android.networkstack.util.NetworkStackUtils.APF_HANDLE_LIGHT_DOZE_FORCE_DISABLE; +import static com.android.networkstack.util.NetworkStackUtils.APF_NEW_RA_FILTER_VERSION; import static com.android.networkstack.util.NetworkStackUtils.IPCLIENT_DHCPV6_PREFIX_DELEGATION_VERSION; import static com.android.networkstack.util.NetworkStackUtils.IPCLIENT_GARP_NA_ROAMING_VERSION; import static com.android.networkstack.util.NetworkStackUtils.IPCLIENT_GRATUITOUS_NA_VERSION; -import static com.android.networkstack.util.NetworkStackUtils.IPCLIENT_IGNORE_LOW_RA_LIFETIME_FORCE_DISABLE; +import static com.android.networkstack.util.NetworkStackUtils.IPCLIENT_IGNORE_LOW_RA_LIFETIME_VERSION; import static com.android.networkstack.util.NetworkStackUtils.IPCLIENT_MULTICAST_NS_VERSION; import static com.android.server.util.PermissionUtil.enforceNetworkStackCallingPermission; @@ -122,6 +124,7 @@ import com.android.net.module.util.arp.ArpPacket; import com.android.net.module.util.ip.InterfaceController; import com.android.net.module.util.netlink.NetlinkUtils; +import com.android.net.module.util.structs.IaPrefixOption; import com.android.networkstack.R; import com.android.networkstack.apishim.NetworkInformationShimImpl; import com.android.networkstack.apishim.SocketUtilsShimImpl; @@ -668,6 +671,9 @@ // Experiment flag read from device config. private final boolean mDhcp6PrefixDelegationEnabled; + private final boolean mUseNewApfFilter; + private final boolean mEnableIpClientIgnoreLowRaLifetime; + private final boolean mApfShouldHandleLightDoze; private InterfaceParams mInterfaceParams; @@ -822,8 +828,8 @@ */ public AndroidPacketFilter maybeCreateApfFilter(Context context, ApfFilter.ApfConfiguration config, InterfaceParams ifParams, - IpClientCallbacksWrapper cb) { - if (isFeatureEnabled(context, NetworkStackUtils.APF_NEW_RA_FILTER_VERSION)) { + IpClientCallbacksWrapper cb, boolean useNewApfFilter) { + if (useNewApfFilter) { return ApfFilter.maybeCreate(context, config, ifParams, cb); } else { return LegacyApfFilter.maybeCreate(context, config, ifParams, cb); @@ -884,6 +890,12 @@ CONFIG_MIN_RDNSS_LIFETIME, DEFAULT_MIN_RDNSS_LIFETIME); mAcceptRaMinLft = mDependencies.getDeviceConfigPropertyInt(CONFIG_ACCEPT_RA_MIN_LFT, DEFAULT_ACCEPT_RA_MIN_LFT); + mUseNewApfFilter = mDependencies.isFeatureEnabled(context, APF_NEW_RA_FILTER_VERSION); + mEnableIpClientIgnoreLowRaLifetime = mDependencies.isFeatureEnabled(context, + IPCLIENT_IGNORE_LOW_RA_LIFETIME_VERSION); + // Light doze mode status checking API is only available at T or later releases. + mApfShouldHandleLightDoze = SdkLevel.isAtLeastT() && mDependencies.isFeatureNotChickenedOut( + mContext, APF_HANDLE_LIGHT_DOZE_FORCE_DISABLE); IpClientLinkObserver.Configuration config = new IpClientLinkObserver.Configuration( mMinRdnssLifetimeSec); @@ -1293,7 +1305,8 @@ IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); pw.println(mTag + " APF dump:"); pw.increaseIndent(); - if (apfFilter != null) { + if (apfFilter != null && apfCapabilities != null + && apfCapabilities.apfVersionSupported > 0) { if (apfCapabilities.hasDataAccess()) { // Request a new snapshot, then wait for it. mApfDataSnapshotComplete.close(); @@ -1721,24 +1734,24 @@ // [4] Add in data from DHCPv6 Prefix Delegation, if available. if (mPrefixDelegation != null) { - try { - final IpPrefix destination = - new IpPrefix(Inet6Address.getByAddress(mPrefixDelegation.ipo.prefix), - mPrefixDelegation.ipo.prefixLen); - // Direct-connected route to delegated prefix. Add RTN_UNREACHABLE to this route - // based on the delegated prefix. To prevent the traffic loop between host and - // upstream delegated router. Because we specify the IFA_F_NOPREFIXROUTE when adding - // the IPv6 address, the kernel does not create a delegated prefix route, as a - // result, the user space won't receive any RTM_NEWROUTE message about the delegated - // prefix, we still need to install an unreachable route for the delegated prefix - // manually in LinkProperties to notify the caller this update. - // TODO: support RTN_BLACKHOLE in netd and use that on newer Android versions. - final RouteInfo route = new RouteInfo(destination, null /* gateway */, - mInterfaceName, RTN_UNREACHABLE); - newLp.addRoute(route); - } catch (UnknownHostException e) { - Log.wtf(mTag, "Invalid delegated prefix " - + HexDump.toHexString(mPrefixDelegation.ipo.prefix)); + for (IaPrefixOption ipo : mPrefixDelegation.ipos) { + try { + final IpPrefix destination = + new IpPrefix(Inet6Address.getByAddress(ipo.prefix), ipo.prefixLen); + // Direct-connected route to delegated prefix. Add RTN_UNREACHABLE to this route + // based on the delegated prefix. To prevent the traffic loop between host and + // upstream delegated router. Because we specify the IFA_F_NOPREFIXROUTE when + // adding the IPv6 address, the kernel does not create a delegated prefix route, + // as a result, the user space won't receive any RTM_NEWROUTE message about the + // delegated prefix, we still need to install an unreachable route for the + // delegated prefix manually in LinkProperties to notify the caller this update. + // TODO: support RTN_BLACKHOLE in netd and use that on newer Android versions. + final RouteInfo route = new RouteInfo(destination, null /* gateway */, + mInterfaceName, RTN_UNREACHABLE); + newLp.addRoute(route); + } catch (UnknownHostException e) { + Log.wtf(mTag, "Invalid delegated prefix " + HexDump.toHexString(ipo.prefix)); + } } } @@ -2160,10 +2173,10 @@ setIpv6Sysctl(DAD_TRANSMITS, 0 /* dad_transmits */); } } - // Check chickened out flag first before reading IPv6 sysctl, which can prevent from + // Check the feature flag first before reading IPv6 sysctl, which can prevent from // triggering a potential kernel bug about the sysctl. - if (mDependencies.isFeatureNotChickenedOut(mContext, - IPCLIENT_IGNORE_LOW_RA_LIFETIME_FORCE_DISABLE) + // TODO: add unit test to check if the setIpv6Sysctl() is called or not. + if (mEnableIpClientIgnoreLowRaLifetime && mUseNewApfFilter && mDependencies.hasIpv6Sysctl(mInterfaceName, ACCEPT_RA_MIN_LFT)) { setIpv6Sysctl(ACCEPT_RA_MIN_LFT, mAcceptRaMinLft); } @@ -2244,8 +2257,7 @@ setIpv6Sysctl(ACCEPT_RA, 2); setIpv6Sysctl(ACCEPT_RA_DEFRTR, 1); maybeRestoreDadTransmits(); - if (mDependencies.isFeatureNotChickenedOut(mContext, - IPCLIENT_IGNORE_LOW_RA_LIFETIME_FORCE_DISABLE) + if (mUseNewApfFilter && mEnableIpClientIgnoreLowRaLifetime && mDependencies.hasIpv6Sysctl(mInterfaceName, ACCEPT_RA_MIN_LFT)) { setIpv6Sysctl(ACCEPT_RA_MIN_LFT, 0 /* sysctl default */); } @@ -2353,8 +2365,9 @@ apfConfig.minRdnssLifetimeSec = mMinRdnssLifetimeSec; apfConfig.acceptRaMinLft = mAcceptRaMinLft; + apfConfig.shouldHandleLightDoze = mApfShouldHandleLightDoze; return mDependencies.maybeCreateApfFilter(mContext, apfConfig, mInterfaceParams, - mCallback); + mCallback, mUseNewApfFilter); } private boolean handleUpdateApfCapabilities(@NonNull final ApfCapabilities apfCapabilities) { @@ -2855,13 +2868,12 @@ Log.wtf(mTag, "PrefixDelegation shouldn't be null when DHCPv6 PD fails."); return; } + final IaPrefixOption ipo = mPrefixDelegation.ipos.get(0); final IpPrefix prefix; try { - prefix = new IpPrefix(Inet6Address.getByAddress(mPrefixDelegation.ipo.prefix), - RFC7421_PREFIX_LENGTH); + prefix = new IpPrefix(Inet6Address.getByAddress(ipo.prefix), RFC7421_PREFIX_LENGTH); } catch (UnknownHostException e) { - Log.wtf(TAG, "Invalid delegated prefix " - + HexDump.toHexString(mPrefixDelegation.ipo.prefix)); + Log.wtf(TAG, "Invalid delegated prefix " + HexDump.toHexString(ipo.prefix)); return; }
diff --git a/src/com/android/networkstack/netlink/TcpInfo.java b/src/com/android/networkstack/netlink/TcpInfo.java index 73d206e..de450e9 100644 --- a/src/com/android/networkstack/netlink/TcpInfo.java +++ b/src/com/android/networkstack/netlink/TcpInfo.java
@@ -170,7 +170,8 @@ } } - private static String decodeWscale(byte num) { + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + static String decodeWscale(byte num) { return String.valueOf((num >> 4) & 0x0f) + ":" + String.valueOf(num & 0x0f); }
diff --git a/src/com/android/networkstack/netlink/TcpSocketTracker.java b/src/com/android/networkstack/netlink/TcpSocketTracker.java index 0c54af0..4b66c0a 100644 --- a/src/com/android/networkstack/netlink/TcpSocketTracker.java +++ b/src/com/android/networkstack/netlink/TcpSocketTracker.java
@@ -214,9 +214,9 @@ final int netId = NetworkShimImpl.newInstance(mNetwork).getNetId(); return mNetd.getFwmarkForNetwork(netId); } catch (UnsupportedApiLevelException e) { - log("Get netId is not available in this API level."); + logd("Get netId is not available in this API level."); } catch (RemoteException e) { - Log.e(TAG, "Error getting fwmark for network, ", e); + loge("Error getting fwmark for network, ", e); } return null; } @@ -246,7 +246,7 @@ mDependencies.sendPollingRequest(fd, mSockDiagMsg.get(family)); while (parseMessage(mDependencies.recvMessage(fd), family, newSocketInfoList, time)) { - log("Pending info exist. Attempt to read more"); + logd("Pending info exist. Attempt to read more"); } } @@ -288,7 +288,7 @@ cleanupSocketInfo(time); return true; } catch (ErrnoException | SocketException | InterruptedIOException e) { - Log.e(TAG, "Fail to get TCP info via netlink.", e); + loge("Fail to get TCP info via netlink.", e); } finally { SocketUtils.closeSocketQuietly(fd); } @@ -302,11 +302,11 @@ // Return true if there are more pending messages to read @VisibleForTesting - static boolean parseMessage(ByteBuffer bytes, int family, + boolean parseMessage(ByteBuffer bytes, int family, ArrayList<SocketInfo> outputSocketInfoList, long time) { if (!NetlinkUtils.enoughBytesRemainForValidNlMsg(bytes)) { // This is unlikely to happen in real cases. Check this first for testing. - Log.e(TAG, "Size is less than header size. Ignored."); + loge("Size is less than header size. Ignored."); return false; } @@ -340,12 +340,12 @@ outputSocketInfoList.add(info); } while (NetlinkUtils.enoughBytesRemainForValidNlMsg(bytes)); } catch (IllegalArgumentException | BufferUnderflowException e) { - Log.wtf(TAG, "Unexpected socket info parsing, family " + family + logwtf("Unexpected socket info parsing, family " + family + " buffer:" + bytes + " " + Base64.getEncoder().encodeToString(bytes.array()), e); return false; } catch (IllegalStateException e) { - Log.e(TAG, "Unexpected socket info parsing, family " + family + loge("Unexpected socket info parsing, family " + family + " buffer:" + bytes + " " + Base64.getEncoder().encodeToString(bytes.array()), e); return false; @@ -354,21 +354,21 @@ return true; } - private static int getLengthAndVerifyMsgHeader(@NonNull ByteBuffer bytes, int family) { + private int getLengthAndVerifyMsgHeader(@NonNull ByteBuffer bytes, int family) { final StructNlMsgHdr nlmsghdr = StructNlMsgHdr.parse(bytes); if (nlmsghdr == null) { - Log.e(TAG, "Badly formatted data."); + loge("Badly formatted data."); return END_OF_PARSING; } - log("pollSocketsInfo: nlmsghdr=" + nlmsghdr + ", limit=" + bytes.limit()); + logd("pollSocketsInfo: nlmsghdr=" + nlmsghdr + ", limit=" + bytes.limit()); // End of the message. Stop parsing. if (nlmsghdr.nlmsg_type == NLMSG_DONE) { return END_OF_PARSING; } if (nlmsghdr.nlmsg_type != SOCK_DIAG_BY_FAMILY) { - Log.e(TAG, "Expect to get family " + family + loge("Expect to get family " + family + " SOCK_DIAG_BY_FAMILY message but get " + nlmsghdr.nlmsg_type); return END_OF_PARSING; @@ -393,7 +393,7 @@ /** Parse a {@code SocketInfo} from the given position of the given byte buffer. */ @NonNull - private static SocketInfo parseSockInfo(@NonNull final ByteBuffer bytes, final int family, + private SocketInfo parseSockInfo(@NonNull final ByteBuffer bytes, final int family, final int nlmsgLen, final long time, final int uid, final long cookie, final int dstPort) { final int remainingDataSize = bytes.position() + nlmsgLen - SOCKDIAG_MSG_HEADER_SIZE; @@ -411,7 +411,7 @@ } } final SocketInfo info = new SocketInfo(tcpInfo, family, mark, time, uid, cookie, dstPort); - log("parseSockInfo, " + info); + logd("parseSockInfo, " + info); return info; } @@ -429,7 +429,7 @@ } final boolean ret = (getLatestPacketFailPercentage() >= getTcpPacketsFailRateThreshold()); if (ret) { - Log.d(TAG, "data stall suspected, uids: " + mLatestReportedUids.toString()); + log("data stall suspected, uids: " + mLatestReportedUids.toString()); } return ret; } @@ -445,7 +445,7 @@ } if (current.tcpInfo == null) { - log("Current tcpInfo is null."); + logd("Current tcpInfo is null."); return null; } @@ -458,7 +458,7 @@ stat.receivedCount -= previous.tcpInfo.mSegsIn; stat.retransCount -= previous.tcpInfo.mTotalRetrans; } - log("calculateLatestPacketsStat, stat:" + stat); + logd("calculateLatestPacketsStat, stat:" + stat); return stat; } @@ -498,8 +498,24 @@ return mTcpPacketsFailRateThreshold; } - private static void log(final String str) { - if (DBG) Log.d(TAG, str); + private void logd(final String str) { + if (DBG) log(str); + } + + private void log(final String s) { + Log.d(TAG + "/" + mNetwork.toString(), s); + } + + private void loge(final String str) { + loge(str, null /* tr */); + } + + private void loge(final String str, @Nullable Throwable tr) { + Log.e(TAG + "/" + mNetwork.toString(), str, tr); + } + + private void logwtf(final String str, @Nullable Throwable tr) { + Log.wtf(TAG + "/" + mNetwork.toString(), str, tr); } /** Stops monitoring and releases resources. */ @@ -585,7 +601,7 @@ synchronized (mDozeModeLock) { if (mInDozeMode == isEnabled) return; mInDozeMode = isEnabled; - log("Doze mode enabled=" + mInDozeMode); + logd("Doze mode enabled=" + mInDozeMode); } } @@ -593,7 +609,7 @@ if (mInOpportunisticMode == isEnabled) return; mInOpportunisticMode = isEnabled; - log("Private DNS Opportunistic mode enabled=" + mInOpportunisticMode); + logd("Private DNS Opportunistic mode enabled=" + mInOpportunisticMode); } public void setLinkProperties(@NonNull LinkProperties lp) {
diff --git a/src/com/android/networkstack/util/NetworkStackUtils.java b/src/com/android/networkstack/util/NetworkStackUtils.java index 5777b5a..84a4491 100755 --- a/src/com/android/networkstack/util/NetworkStackUtils.java +++ b/src/com/android/networkstack/util/NetworkStackUtils.java
@@ -34,7 +34,6 @@ import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; -import java.net.SocketException; import java.net.UnknownHostException; /** @@ -250,6 +249,12 @@ * Experiment flag to enable new ra filter. */ public static final String APF_NEW_RA_FILTER_VERSION = "apf_new_ra_filter_version"; + /** + * Experiment flag to enable the feature of ignoring any individual RA section with lifetime + * below accept_ra_min_lft sysctl. + */ + public static final String IPCLIENT_IGNORE_LOW_RA_LIFETIME_VERSION = + "ipclient_ignore_low_ra_lifetime_version"; /**** BEGIN Feature Kill Switch Flags ****/ @@ -261,11 +266,10 @@ "ipclient_parse_netlink_events_force_disable"; /** - * Kill switch flag to disable the feature of ignoring any individual RA section with lifetime - * below accept_ra_min_lft sysctl. + * Kill switch flag to disable the feature of handle light doze mode in Apf. */ - public static final String IPCLIENT_IGNORE_LOW_RA_LIFETIME_FORCE_DISABLE = - "ipclient_ignore_low_ra_lifetime_force_disable"; + public static final String APF_HANDLE_LIGHT_DOZE_FORCE_DISABLE = + "apf_handle_light_doze_force_disable"; /** * Kill switch flag to disable the feature of skipping Tcp socket info polling when light @@ -273,6 +277,11 @@ */ public static final String SKIP_TCP_POLL_IN_LIGHT_DOZE = "skip_tcp_poll_in_light_doze_mode"; + /** + * Kill switch flag to disable the feature of re-evaluate when network resumes. + */ + public static final String REEVALUATE_WHEN_RESUME = "reevaluate_when_resume"; + static { System.loadLibrary("networkstackutilsjni"); }
diff --git a/src/com/android/server/connectivity/NetworkMonitor.java b/src/com/android/server/connectivity/NetworkMonitor.java index 5b551a0..5432a13 100755 --- a/src/com/android/server/connectivity/NetworkMonitor.java +++ b/src/com/android/server/connectivity/NetworkMonitor.java
@@ -36,6 +36,7 @@ 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.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED; import static android.net.captiveportal.CaptivePortalProbeSpec.parseCaptivePortalProbeSpecs; import static android.net.metrics.ValidationProbeEvent.DNS_FAILURE; import static android.net.metrics.ValidationProbeEvent.DNS_SUCCESS; @@ -542,6 +543,7 @@ private final boolean mPrivateIpNoInternetEnabled; private final boolean mMetricsEnabled; + private final boolean mReevaluateWhenResumeEnabled; @NonNull private final NetworkInformationShim mInfoShim = NetworkInformationShimImpl.newInstance(); @@ -628,6 +630,8 @@ mPrivateIpNoInternetEnabled = getIsPrivateIpNoInternetEnabled(); mMetricsEnabled = deps.isFeatureNotChickenedOut(context, NetworkStackUtils.VALIDATION_METRICS_VERSION); + mReevaluateWhenResumeEnabled = deps.isFeatureNotChickenedOut(context, + NetworkStackUtils.REEVALUATE_WHEN_RESUME); mUseHttps = getUseHttpsValidation(); mCaptivePortalUserAgent = getCaptivePortalUserAgent(); mCaptivePortalFallbackSpecs = @@ -1101,16 +1105,8 @@ } break; case EVENT_NETWORK_CAPABILITIES_CHANGED: - final NetworkCapabilities newCap = (NetworkCapabilities) message.obj; - // Reevaluate network if underlying network changes on the validation required - // VPN. - if (isVpnUnderlyingNetworkChangeReevaluationRequired( - newCap, mNetworkCapabilities)) { - sendMessage(CMD_FORCE_REEVALUATION, NO_UID, 0); - } - - mNetworkCapabilities = newCap; - suppressNotificationIfNetworkRestricted(); + handleCapabilitiesChanged((NetworkCapabilities) message.obj, + true /* reevaluateOnResume */); break; case EVENT_RESOURCE_CONFIG_CHANGED: // RRO generation does not happen during package installation and instead after @@ -1129,20 +1125,49 @@ return HANDLED; } - private boolean isVpnUnderlyingNetworkChangeReevaluationRequired( - final NetworkCapabilities newCap, final NetworkCapabilities oldCap) { - return !newCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) - && isValidationRequired() - && !Objects.equals(mInfoShim.getUnderlyingNetworks(newCap), - mInfoShim.getUnderlyingNetworks(oldCap)); - } - @Override public void exit() { mContext.unregisterReceiver(mConfigurationReceiver); } } + private void handleCapabilitiesChanged(@NonNull final NetworkCapabilities newCap, + boolean reevaluateOnResume) { + // Go to EvaluatingState to reset the network re-evaluation timer when + // the network resumes from suspended. + // This is because the network is expected to be down + // when the device is suspended, and if the delay timer falls back to + // the maximum interval, re-evaluation will be triggered slowly after + // the network resumes. + // Suppress re-evaluation in validated state, if the network has been validated, + // then it's in the expected state. + // TODO(b/287183389): Evaluate once but do not re-evaluate when suspended, to make + // exclamation mark visible by user but doesn't cause too much network traffic. + if (mReevaluateWhenResumeEnabled && reevaluateOnResume + && !mNetworkCapabilities.hasCapability(NET_CAPABILITY_NOT_SUSPENDED) + && newCap.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)) { + // Interrupt if waiting for next probe. + sendMessage(CMD_FORCE_REEVALUATION, NO_UID, 1 /* forceAccept */); + } else if (isVpnUnderlyingNetworkChangeReevaluationRequired(newCap, mNetworkCapabilities)) { + // If no re-evaluation is needed from the previous check, fall-through for lower + // priority checks. + // Reevaluate network if underlying network changes on the validation required + // VPN. + sendMessage(CMD_FORCE_REEVALUATION, NO_UID, 0 /* forceAccept */); + } + + mNetworkCapabilities = newCap; + suppressNotificationIfNetworkRestricted(); + } + + private boolean isVpnUnderlyingNetworkChangeReevaluationRequired( + final NetworkCapabilities newCap, final NetworkCapabilities oldCap) { + return !newCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) + && isValidationRequired() + && !Objects.equals(mInfoShim.getUnderlyingNetworks(newCap), + mInfoShim.getUnderlyingNetworks(oldCap)); + } + // Being in the ValidatedState State indicates a Network is: // - Successfully validated, or // - Wanted "as is" by the user, or @@ -1208,6 +1233,12 @@ sendTcpPollingEvent(); } break; + case EVENT_NETWORK_CAPABILITIES_CHANGED: + // The timer does not need to reset, and it won't need to re-evaluate if + // the network is already validated when resumes. + handleCapabilitiesChanged((NetworkCapabilities) message.obj, + false /* reevaluateOnResume */); + break; default: return NOT_HANDLED; } @@ -3456,6 +3487,11 @@ } @VisibleForTesting + public int getReevaluationDelayMs() { + return mReevaluateDelayMs; + } + + @VisibleForTesting protected boolean isDataStall() { if (!isDataStallDetectionRequired()) { return false;
diff --git a/tests/integration/common/android/net/ip/IpClientIntegrationTestCommon.java b/tests/integration/common/android/net/ip/IpClientIntegrationTestCommon.java index f604d5b..1dd5e40 100644 --- a/tests/integration/common/android/net/ip/IpClientIntegrationTestCommon.java +++ b/tests/integration/common/android/net/ip/IpClientIntegrationTestCommon.java
@@ -38,6 +38,7 @@ import static android.net.dhcp.DhcpPacket.INADDR_BROADCAST; import static android.net.dhcp.DhcpPacket.INFINITE_LEASE; import static android.net.dhcp.DhcpPacket.MIN_V6ONLY_WAIT_MS; +import static android.net.dhcp6.Dhcp6Packet.PrefixDelegation; import static android.net.ip.IIpClientCallbacks.DTIM_MULTIPLIER_RESET; import static android.net.ip.IpClient.CONFIG_IPV6_AUTOCONF_TIMEOUT; import static android.net.ip.IpClient.CONFIG_ACCEPT_RA_MIN_LFT; @@ -78,6 +79,7 @@ import static com.android.net.module.util.NetworkStackConstants.NEIGHBOR_ADVERTISEMENT_FLAG_SOLICITED; import static com.android.net.module.util.NetworkStackConstants.PIO_FLAG_AUTONOMOUS; import static com.android.net.module.util.NetworkStackConstants.PIO_FLAG_ON_LINK; +import static com.android.net.module.util.NetworkStackConstants.RFC7421_PREFIX_LENGTH; import static com.android.testutils.MiscAsserts.assertThrows; import static com.android.testutils.ParcelUtils.parcelingRoundTrip; import static com.android.testutils.TestPermissionUtil.runAsShell; @@ -151,6 +153,7 @@ import android.net.dhcp.DhcpRequestPacket; import android.net.dhcp6.Dhcp6Client; import android.net.dhcp6.Dhcp6Packet; +import android.net.dhcp6.Dhcp6Packet.PrefixDelegation; import android.net.dhcp6.Dhcp6RebindPacket; import android.net.dhcp6.Dhcp6RenewPacket; import android.net.dhcp6.Dhcp6RequestPacket; @@ -199,6 +202,7 @@ import com.android.net.module.util.netlink.NetlinkUtils; import com.android.net.module.util.netlink.StructNdOptPref64; import com.android.net.module.util.structs.EthernetHeader; +import com.android.net.module.util.structs.IaPrefixOption; import com.android.net.module.util.structs.Ipv6Header; import com.android.net.module.util.structs.LlaOption; import com.android.net.module.util.structs.PrefixInformationOption; @@ -3219,7 +3223,7 @@ for (LinkAddress la : lp.getLinkAddresses()) { final InetAddress addr = la.getAddress(); if ((addr instanceof Inet6Address) && !addr.isLinkLocalAddress()) { - return prefix.contains(addr); + if (prefix.contains(addr)) return true; } } return false; @@ -4803,18 +4807,27 @@ inOrder.verify(mCb, timeout(TEST_TIMEOUT_MS)).setMaxDtimMultiplier(DTIM_MULTIPLIER_RESET); } - private void handleDhcp6Packets(final IpPrefix prefix, boolean shouldReplyRapidCommit) - throws Exception { - handleDhcp6Packets(prefix, 3600 /* t1 */, 4500 /* t2 */, 4500 /* preferred */, - 7200 /* valid */, shouldReplyRapidCommit); + private IaPrefixOption buildIaPrefixOption(final IpPrefix prefix, int preferred, + int valid) { + return new IaPrefixOption((short) IaPrefixOption.LENGTH, preferred, valid, + (byte) RFC7421_PREFIX_LENGTH, prefix.getRawAddress() /* prefix */); } - private void handleDhcp6Packets(final IpPrefix prefix, int t1, int t2, int preferred, int valid, + private void handleDhcp6Packets(final IpPrefix prefix, boolean shouldReplyRapidCommit) + throws Exception { + final IaPrefixOption ipo = buildIaPrefixOption(prefix, 4500 /* preferred */, + 7200 /* valid */); + handleDhcp6Packets(Collections.singletonList(ipo), 3600 /* t1 */, 4500 /* t2 */, + shouldReplyRapidCommit); + } + + private void handleDhcp6Packets(final List<IaPrefixOption> ipos, int t1, int t2, boolean shouldReplyRapidCommit) throws Exception { + ByteBuffer iapd; Dhcp6Packet packet; while ((packet = getNextDhcp6Packet()) != null) { - final ByteBuffer iapd = Dhcp6Packet.buildIaPdOption(packet.getIaId(), t1, t2, - preferred, valid, prefix.getRawAddress(), (byte) prefix.getPrefixLength()); + final PrefixDelegation pd = new PrefixDelegation(packet.getIaId(), t1, t2, ipos); + iapd = pd.build(); if (packet instanceof Dhcp6SolicitPacket) { if (shouldReplyRapidCommit) { mPacketReader.sendResponse(buildDhcp6Reply(packet, iapd.array(), mClientMac, @@ -4874,7 +4887,11 @@ @Test public void testDhcp6Pd_longPrefixLength() throws Exception { prepareDhcp6PdTest(); - handleDhcp6Packets(new IpPrefix("2001:db8:1::/80"), true /* shouldReplyRapidCommit */); + final IpPrefix prefix = new IpPrefix("2001:db8:1::/80"); + final IaPrefixOption ipo = buildIaPrefixOption(prefix, 3600 /* preferred */, + 4000 /* valid */); + handleDhcp6Packets(Collections.singletonList(ipo), 3600 /* t1 */, 4500 /* t2 */, + true /* shouldReplyRapidCommit */); verify(mCb, never()).onProvisioningSuccess(any()); } @@ -4891,24 +4908,33 @@ @Test public void testDhcp6Pd_T1GreaterThanT2() throws Exception { prepareDhcp6PdTest(); - handleDhcp6Packets(new IpPrefix("2001:db8:1::/80"), 4500 /* t1 */, 3600 /* t2 */, - 4500 /* preferred */, 7200 /* valid */, true /* shouldReplyRapidCommit */); + final IpPrefix prefix = new IpPrefix("2001:db8:1::/64"); + final IaPrefixOption ipo = buildIaPrefixOption(prefix, 3600 /* preferred */, + 4000 /* valid */); + handleDhcp6Packets(Collections.singletonList(ipo), 4500 /* t1 */, 3600 /* t2 */, + true /* shouldReplyRapidCommit */); verify(mCb, never()).onProvisioningSuccess(any()); } @Test public void testDhcp6Pd_preferredLifetimeGreaterThanValidLifetime() throws Exception { prepareDhcp6PdTest(); - handleDhcp6Packets(new IpPrefix("2001:db8:1::/80"), 3600 /* t1 */, 4500 /* t2 */, - 7200 /* preferred */, 4500 /* valid */, true /* shouldReplyRapidCommit */); + final IpPrefix prefix = new IpPrefix("2001:db8:1::/64"); + final IaPrefixOption ipo = buildIaPrefixOption(prefix, 7200 /* preferred */, + 4500 /* valid */); + handleDhcp6Packets(Collections.singletonList(ipo), 3600 /* t1 */, 4500 /* t2 */, + true /* shouldReplyRapidCommit */); verify(mCb, never()).onProvisioningSuccess(any()); } @Test public void testDhcp6Pd_preferredLifetimeLessThanT2() throws Exception { prepareDhcp6PdTest(); - handleDhcp6Packets(new IpPrefix("2001:db8:1::/80"), 3600 /* t1 */, 4500 /* t2 */, - 3600 /* preferred */, 4000 /* valid */, true /* shouldReplyRapidCommit */); + final IpPrefix prefix = new IpPrefix("2001:db8:1::/64"); + final IaPrefixOption ipo = buildIaPrefixOption(prefix, 3600 /* preferred */, + 4000 /* valid */); + handleDhcp6Packets(Collections.singletonList(ipo), 3600 /* t1 */, 4500 /* t2 */, + true /* shouldReplyRapidCommit */); verify(mCb, never()).onProvisioningSuccess(any()); } @@ -5056,12 +5082,14 @@ Dhcp6Packet packet = getNextDhcp6Packet(); assertTrue(packet instanceof Dhcp6RenewPacket); - // Reply with a different prefix with requested one, check if all global IPv6 addresses - // will be deleted and loss the IPv6 provisioning. + // Reply with a different prefix with requested one, per RFC8415#section-18.2.10.1 + // any new prefix should be added. final IpPrefix prefix1 = new IpPrefix("2001:db8:2::/64"); - final ByteBuffer iapd = Dhcp6Packet.buildIaPdOption(packet.getIaId(), 3600 /* t1*/, - 4500 /* t2 */, 4500 /* preferred */, 7200 /* valid */, prefix1.getRawAddress(), - (byte) 64 /* prefix length */); + final IaPrefixOption ipo = buildIaPrefixOption(prefix1, 4500 /* preferred */, + 7200 /* valid */); + final PrefixDelegation pd = new PrefixDelegation(packet.getIaId(), 3600 /* t1 */, + 4500 /* t2 */, Collections.singletonList(ipo)); + final ByteBuffer iapd = pd.build(); mPacketReader.sendResponse(buildDhcp6Reply(packet, iapd.array(), mClientMac, (Inet6Address) mClientIpAddress, false /* rapidCommit */)); verify(mCb, timeout(TEST_TIMEOUT_MS)).onProvisioningFailure(any());
diff --git a/tests/integration/signature/android/net/NetworkStatsIntegrationTest.kt b/tests/integration/signature/android/net/NetworkStatsIntegrationTest.kt index 8b1b046..b10e6e1 100644 --- a/tests/integration/signature/android/net/NetworkStatsIntegrationTest.kt +++ b/tests/integration/signature/android/net/NetworkStatsIntegrationTest.kt
@@ -28,7 +28,9 @@ import android.net.NetworkStatsIntegrationTest.Direction.UPLOAD import android.net.NetworkTemplate.MATCH_TEST import android.os.Build +import android.os.ParcelFileDescriptor.AutoCloseInputStream import android.os.Process +import android.util.Log import androidx.test.platform.app.InstrumentationRegistry import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo import com.android.testutils.DevSdkIgnoreRunner @@ -42,6 +44,7 @@ import fi.iki.elonen.NanoHTTPD import java.io.BufferedInputStream import java.io.BufferedOutputStream +import java.io.BufferedReader import java.net.HttpURLConnection import java.net.HttpURLConnection.HTTP_OK import java.net.InetSocketAddress @@ -49,6 +52,7 @@ import java.nio.charset.Charset import kotlin.math.ceil import kotlin.test.assertEquals +import kotlin.test.assertNotNull import kotlin.test.assertTrue import org.junit.After import org.junit.Assume.assumeTrue @@ -62,6 +66,7 @@ @TargetApi(Build.VERSION_CODES.S) @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) class NetworkStatsIntegrationTest { + private val TAG = NetworkStatsIntegrationTest::class.java.simpleName private val INTERNAL_V6ADDR = LinkAddress(InetAddresses.parseNumericAddress("2001:db8::1234"), 64) private val EXTERNAL_V6ADDR = @@ -381,6 +386,7 @@ val taggedUid = getUidDetail(iface, TEST_TAG) val trafficStatsIface = getTrafficStatsIface(iface) val trafficStatsUid = getTrafficStatsUid(Process.myUid()) + val xtBpfStats = getXtBpfStatsInternal() private fun getUidDetail(iface: String, tag: Int): BareStats { return getNetworkStatsThat(iface, tag) { nsm, template -> @@ -447,6 +453,40 @@ TrafficStats.getUidTxBytes(uid), TrafficStats.getUidTxPackets(uid) ) + + private fun getXtBpfStatsInternal(): BareStats { + // The following pattern matches ip(6)tables-save -c output like below: + // [119:37802] -A bw_raw_PREROUTING -m bpf --object-pinned + // /sys/fs/bpf/netd_shared/prog_netd_skfilter_ingress_xtbpf + // [141:26439] -A bw_mangle_POSTROUTING -m bpf --object-pinned + // /sys/fs/bpf/netd_shared/prog_netd_skfilter_egress_xtbpf + val ingressRegex = Regex("""\[(?<rxPackets>\d+):(?<rxBytes>\d+)\]""" + + """.*prog_netd_skfilter_ingress_xtbpf""") + val egressRegex = Regex("""\[(?<txPackets>\d+):(?<txBytes>\d+)\]""" + + """.*prog_netd_skfilter_egress_xtbpf""") + val (v4Stats, v6Stats) = listOf("iptables-save -c", "ip6tables-save -c").map { + val output = runShellCommand(it) + val rxMatches = ingressRegex.find(output) + val txMatches = egressRegex.find(output) + assertNotNull(rxMatches) + assertNotNull(txMatches) + + BareStats( + rxBytes = rxMatches.groups["rxBytes"]!!.value.toLong(), + rxPackets = rxMatches.groups["rxPackets"]!!.value.toLong(), + txBytes = txMatches.groups["txBytes"]!!.value.toLong(), + txPackets = txMatches.groups["txPackets"]!!.value.toLong() + ) + } + return v4Stats.plus(v6Stats) + } + + private fun runShellCommand(cmd: String): String { + return InstrumentationRegistry.getInstrumentation().getUiAutomation() + .executeShellCommand(cmd).use { pfd -> + AutoCloseInputStream(pfd).bufferedReader().use(BufferedReader::readText) + } + } } private fun assertAllStatsIncreases( @@ -475,6 +515,15 @@ lower: BareStats, upper: BareStats ) { + // XtBpf iptables hook counted traffic on all interfaces. Thus, this might see traffic + // on other interfaces as well. Also, other thread/process could reload the relevant + // iptables table. Thus, instead of asserting the readings, print logs when it is + // unexpected to provide more debug information when failing other items. + if (!checkInRange(before.xtBpfStats, after.xtBpfStats, + lower + lower.reverse(), upper + upper.reverse())) { + Log.d(TAG, "Unexpected xtbpf stats: ${after.xtBpfStats} - ${before.xtBpfStats} " + + "is not within range [$lower, $upper]") + } assertInRange( "Unexpected iface traffic stats", after.iface, @@ -550,16 +599,24 @@ ) { // Passing the value after operation and the value before operation to dump the actual // numbers if it fails. - val value = after - before - assertTrue( - value.rxBytes in lower.rxBytes..upper.rxBytes && - value.rxPackets in lower.rxPackets..upper.rxPackets && - value.txBytes in lower.txBytes..upper.txBytes && - value.txPackets in lower.txPackets..upper.txPackets, + assertTrue(checkInRange(before, after, lower, upper), "$tag on $iface: $after - $before is not within range [$lower, $upper]" ) } + private fun checkInRange( + before: BareStats, + after: BareStats, + lower: BareStats, + upper: BareStats + ): Boolean { + val value = after - before + return value.rxBytes in lower.rxBytes..upper.rxBytes && + value.rxPackets in lower.rxPackets..upper.rxPackets && + value.txBytes in lower.txBytes..upper.txBytes && + value.txPackets in lower.txPackets..upper.txPackets + } + fun getRandomString(length: Long): String { val allowedChars = ('A'..'Z') + ('a'..'z') + ('0'..'9') return (1..length)
diff --git a/tests/unit/jni/apf_jni.cpp b/tests/unit/jni/apf_jni.cpp index 5ae3ada..84c5c1a 100644 --- a/tests/unit/jni/apf_jni.cpp +++ b/tests/unit/jni/apf_jni.cpp
@@ -41,7 +41,7 @@ filter_age); } else { return apf_run(program, program_len, ram_len, packet, packet_len, - filter_age); + filter_age << 14); } }
diff --git a/tests/unit/src/android/net/apf/ApfTest.java b/tests/unit/src/android/net/apf/ApfTest.java index 69c8917..6a54e1c 100644 --- a/tests/unit/src/android/net/apf/ApfTest.java +++ b/tests/unit/src/android/net/apf/ApfTest.java
@@ -25,7 +25,8 @@ import static android.net.apf.ApfTestUtils.MIN_PKT_SIZE; import static android.net.apf.ApfTestUtils.PASS; import static android.net.apf.ApfTestUtils.assertProgramEquals; -import static android.system.OsConstants.AF_UNIX; +import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED; +import static android.os.PowerManager.ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED; import static android.system.OsConstants.ARPHRD_ETHER; import static android.system.OsConstants.ETH_P_ARP; import static android.system.OsConstants.ETH_P_IP; @@ -34,7 +35,6 @@ import static android.system.OsConstants.IPPROTO_IPV6; import static android.system.OsConstants.IPPROTO_TCP; import static android.system.OsConstants.IPPROTO_UDP; -import static android.system.OsConstants.SOCK_STREAM; import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ECHO_REQUEST_TYPE; @@ -42,9 +42,13 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.verify; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; import android.net.InetAddresses; import android.net.IpPrefix; import android.net.LinkAddress; @@ -54,14 +58,12 @@ import android.net.TcpKeepalivePacketDataParcelable; import android.net.apf.ApfFilter.ApfConfiguration; import android.net.apf.ApfGenerator.IllegalInstructionException; -import android.net.ip.IIpClientCallbacks; -import android.net.ip.IpClient.IpClientCallbacksWrapper; -import android.os.ConditionVariable; -import android.os.SystemClock; +import android.net.apf.ApfTestUtils.MockIpClientCallback; +import android.net.apf.ApfTestUtils.TestApfFilter; +import android.os.Build; +import android.os.PowerManager; import android.system.ErrnoException; -import android.system.Os; import android.text.TextUtils; -import android.text.format.DateUtils; import android.util.Log; import android.util.Pair; @@ -71,27 +73,26 @@ import com.android.internal.util.HexDump; import com.android.net.module.util.DnsPacket; import com.android.net.module.util.Inet4AddressUtils; -import com.android.net.module.util.InterfaceParams; import com.android.net.module.util.NetworkStackConstants; import com.android.net.module.util.PacketBuilder; -import com.android.net.module.util.SharedLog; -import com.android.networkstack.apishim.NetworkInformationShimImpl; import com.android.server.networkstack.tests.R; +import com.android.testutils.DevSdkIgnoreRule; +import com.android.testutils.DevSdkIgnoreRunner; -import libcore.io.IoUtils; import libcore.io.Streams; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -112,12 +113,13 @@ * * The test cases will be executed by both APFv4 and APFv6 interpreter. */ -@RunWith(Parameterized.class) +@RunWith(DevSdkIgnoreRunner.class) @SmallTest public class ApfTest { - private static final int TIMEOUT_MS = 500; private static final int MIN_APF_VERSION = 2; + @Rule + public DevSdkIgnoreRule mDevSdkIgnoreRule = new DevSdkIgnoreRule(); // Indicates which apf interpreter to run. @Parameterized.Parameter() public int mApfVersion; @@ -127,10 +129,14 @@ return Arrays.asList(4, 6); } - @Mock Context mContext; + @Mock private Context mContext; + @Mock + private ApfFilter.Dependencies mDependencies; + @Mock private PowerManager mPowerManager; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); + doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class); } private static final String TAG = "ApfTest"; @@ -546,8 +552,8 @@ // Test filter age pre-filled memory. gen = new ApfGenerator(MIN_APF_VERSION); gen.addLoadFromMemory(R0, gen.FILTER_AGE_MEMORY_SLOT); - gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL); - assertDrop(gen, new byte[MIN_PKT_SIZE], 1234567890); + gen.addJumpIfR0Equals(123, gen.DROP_LABEL); + assertDrop(gen, new byte[MIN_PKT_SIZE], 123); // Test packet size pre-filled memory. gen = new ApfGenerator(MIN_APF_VERSION); @@ -915,96 +921,6 @@ apfFilter.shutdown(); } - private class MockIpClientCallback extends IpClientCallbacksWrapper { - private final ConditionVariable mGotApfProgram = new ConditionVariable(); - private byte[] mLastApfProgram; - - MockIpClientCallback() { - super(mock(IIpClientCallbacks.class), mock(SharedLog.class), - NetworkInformationShimImpl.newInstance()); - } - - @Override - public void installPacketFilter(byte[] filter) { - mLastApfProgram = filter; - mGotApfProgram.open(); - } - - public void resetApfProgramWait() { - mGotApfProgram.close(); - } - - public byte[] assertProgramUpdateAndGet() { - assertTrue(mGotApfProgram.block(TIMEOUT_MS)); - return mLastApfProgram; - } - - public void assertNoProgramUpdate() { - assertFalse(mGotApfProgram.block(TIMEOUT_MS)); - } - } - - private static class TestApfFilter extends ApfFilter { - public static final byte[] MOCK_MAC_ADDR = {1,2,3,4,5,6}; - - private FileDescriptor mWriteSocket; - private long mCurrentTimeMs = SystemClock.elapsedRealtime(); - private final MockIpClientCallback mMockIpClientCb; - - public TestApfFilter(Context context, ApfConfiguration config, - MockIpClientCallback ipClientCallback) throws Exception { - super(context, config, InterfaceParams.getByName("lo"), ipClientCallback); - mMockIpClientCb = ipClientCallback; - } - - // Pretend an RA packet has been received and show it to ApfFilter. - public void pretendPacketReceived(byte[] packet) throws IOException, ErrnoException { - mMockIpClientCb.resetApfProgramWait(); - // ApfFilter's ReceiveThread will be waiting to read this. - Os.write(mWriteSocket, packet, 0, packet.length); - } - - // Simulate current time changes - public void increaseCurrentTimeSeconds(int delta) { - mCurrentTimeMs += delta * DateUtils.SECOND_IN_MILLIS; - } - - @Override - protected int secondsSinceBoot() { - return (int) (mCurrentTimeMs / DateUtils.SECOND_IN_MILLIS); - } - - @Override - public synchronized void maybeStartFilter() { - mHardwareAddress = MOCK_MAC_ADDR; - installNewProgramLocked(); - - // Create two sockets, "readSocket" and "mWriteSocket" and connect them together. - FileDescriptor readSocket = new FileDescriptor(); - mWriteSocket = new FileDescriptor(); - try { - Os.socketpair(AF_UNIX, SOCK_STREAM, 0, mWriteSocket, readSocket); - } catch (ErrnoException e) { - fail(); - return; - } - // Now pass readSocket to ReceiveThread as if it was setup to read raw RAs. - // This allows us to pretend RA packets have been recieved via pretendPacketReceived(). - mReceiveThread = new ReceiveThread(readSocket); - mReceiveThread.start(); - } - - @Override - public void shutdown() { - super.shutdown(); - if (mReceiveThread != null) { - mReceiveThread.halt(); - mReceiveThread = null; - } - IoUtils.closeQuietly(mWriteSocket); - } - } - private static final int ETH_HEADER_LEN = 14; private static final int ETH_DEST_ADDR_OFFSET = 0; private static final int ETH_ETHERTYPE_OFFSET = 12; @@ -1134,17 +1050,6 @@ private static final int IPV6_UDP_DEST_PORT_OFFSET = IPV6_PAYLOAD_OFFSET + 2; private static final int MDNS_UDP_PORT = 5353; - // Helper to initialize a default apfFilter. - private ApfFilter setupApfFilter( - MockIpClientCallback ipClientCallback, ApfConfiguration config) throws Exception { - LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19); - LinkProperties lp = new LinkProperties(); - lp.addLinkAddress(link); - TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback); - apfFilter.setLinkProperties(lp); - return apfFilter; - } - private static void setIpv4VersionFields(ByteBuffer packet) { packet.putShort(ETH_ETHERTYPE_OFFSET, (short) ETH_P_IP); packet.put(IP_HEADER_OFFSET, (byte) 0x45); @@ -1800,20 +1705,60 @@ @Test public void testApfFilterMulticastPingWhileDozing() throws Exception { - MockIpClientCallback ipClientCallback = new MockIpClientCallback(); - ApfFilter apfFilter = setupApfFilter(ipClientCallback, getDefaultConfig()); + doTestApfFilterMulticastPingWhileDozing(false /* isLightDozing */); + } + + @Test + @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) + public void testApfFilterMulticastPingWhileLightDozing() throws Exception { + doTestApfFilterMulticastPingWhileDozing(true /* isLightDozing */); + } + + @Test + @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) + public void testShouldHandleLightDozeKillSwitch() throws Exception { + final MockIpClientCallback ipClientCallback = new MockIpClientCallback(); + final ApfConfiguration configuration = getDefaultConfig(); + configuration.shouldHandleLightDoze = false; + final ApfFilter apfFilter = TestApfFilter.createTestApfFilter(mContext, ipClientCallback, + configuration, mDependencies); + final ArgumentCaptor<BroadcastReceiver> receiverCaptor = + ArgumentCaptor.forClass(BroadcastReceiver.class); + verify(mDependencies).addDeviceIdleReceiver(receiverCaptor.capture(), anyBoolean()); + final BroadcastReceiver receiver = receiverCaptor.getValue(); + doReturn(true).when(mPowerManager).isDeviceLightIdleMode(); + receiver.onReceive(mContext, new Intent(ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED)); + assertFalse(apfFilter.isInDozeMode()); + } + + private void doTestApfFilterMulticastPingWhileDozing(boolean isLightDozing) throws Exception { + final MockIpClientCallback ipClientCallback = new MockIpClientCallback(); + final ApfConfiguration configuration = getDefaultConfig(); + configuration.shouldHandleLightDoze = true; + final ApfFilter apfFilter = TestApfFilter.createTestApfFilter(mContext, ipClientCallback, + configuration, mDependencies); + final ArgumentCaptor<BroadcastReceiver> receiverCaptor = + ArgumentCaptor.forClass(BroadcastReceiver.class); + verify(mDependencies).addDeviceIdleReceiver(receiverCaptor.capture(), anyBoolean()); + final BroadcastReceiver receiver = receiverCaptor.getValue(); // Construct a multicast ICMPv6 ECHO request. final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb}; - ByteBuffer packet = makeIpv6Packet(IPPROTO_ICMPV6); + final ByteBuffer packet = makeIpv6Packet(IPPROTO_ICMPV6); packet.put(ICMP6_TYPE_OFFSET, (byte)ICMPV6_ECHO_REQUEST_TYPE); put(packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr); // Normally, we let multicast pings alone... assertPass(ipClientCallback.assertProgramUpdateAndGet(), packet.array()); + if (isLightDozing) { + doReturn(true).when(mPowerManager).isDeviceLightIdleMode(); + receiver.onReceive(mContext, new Intent(ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED)); + } else { + doReturn(true).when(mPowerManager).isDeviceIdleMode(); + receiver.onReceive(mContext, new Intent(ACTION_DEVICE_IDLE_MODE_CHANGED)); + } // ...and even while dozing... - apfFilter.setDozeMode(true); assertPass(ipClientCallback.assertProgramUpdateAndGet(), packet.array()); // ...but when the multicast filter is also enabled, drop the multicast pings to save power. @@ -1829,7 +1774,13 @@ // Now wake up from doze mode to ensure that we no longer drop the packets. // (The multicast filter is still enabled at this point). - apfFilter.setDozeMode(false); + if (isLightDozing) { + doReturn(false).when(mPowerManager).isDeviceLightIdleMode(); + receiver.onReceive(mContext, new Intent(ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED)); + } else { + doReturn(false).when(mPowerManager).isDeviceIdleMode(); + receiver.onReceive(mContext, new Intent(ACTION_DEVICE_IDLE_MODE_CHANGED)); + } assertPass(ipClientCallback.assertProgramUpdateAndGet(), packet.array()); apfFilter.shutdown(); @@ -1839,7 +1790,8 @@ public void testApfFilter802_3() throws Exception { MockIpClientCallback ipClientCallback = new MockIpClientCallback(); ApfConfiguration config = getDefaultConfig(); - ApfFilter apfFilter = setupApfFilter(ipClientCallback, config); + ApfFilter apfFilter = TestApfFilter.createTestApfFilter(mContext, ipClientCallback, config, + mDependencies); byte[] program = ipClientCallback.assertProgramUpdateAndGet(); // Verify empty packet of 100 zero bytes is passed @@ -1859,7 +1811,8 @@ ipClientCallback.resetApfProgramWait(); apfFilter.shutdown(); config.ieee802_3Filter = DROP_802_3_FRAMES; - apfFilter = setupApfFilter(ipClientCallback, config); + apfFilter = TestApfFilter.createTestApfFilter(mContext, ipClientCallback, config, + mDependencies); program = ipClientCallback.assertProgramUpdateAndGet(); // Verify that IEEE802.3 frame is dropped @@ -1886,7 +1839,8 @@ MockIpClientCallback ipClientCallback = new MockIpClientCallback(); ApfConfiguration config = getDefaultConfig(); - ApfFilter apfFilter = setupApfFilter(ipClientCallback, config); + ApfFilter apfFilter = TestApfFilter.createTestApfFilter(mContext, ipClientCallback, config, + mDependencies); byte[] program = ipClientCallback.assertProgramUpdateAndGet(); // Verify empty packet of 100 zero bytes is passed @@ -1906,7 +1860,8 @@ ipClientCallback.resetApfProgramWait(); apfFilter.shutdown(); config.ethTypeBlackList = ipv4BlackList; - apfFilter = setupApfFilter(ipClientCallback, config); + apfFilter = TestApfFilter.createTestApfFilter(mContext, ipClientCallback, config, + mDependencies); program = ipClientCallback.assertProgramUpdateAndGet(); // Verify that IPv4 frame will be dropped @@ -1921,7 +1876,8 @@ ipClientCallback.resetApfProgramWait(); apfFilter.shutdown(); config.ethTypeBlackList = ipv4Ipv6BlackList; - apfFilter = setupApfFilter(ipClientCallback, config); + apfFilter = TestApfFilter.createTestApfFilter(mContext, ipClientCallback, config, + mDependencies); program = ipClientCallback.assertProgramUpdateAndGet(); // Verify that IPv4 frame will be dropped
diff --git a/tests/unit/src/android/net/apf/ApfTestUtils.java b/tests/unit/src/android/net/apf/ApfTestUtils.java index 555b92e..69c4079 100644 --- a/tests/unit/src/android/net/apf/ApfTestUtils.java +++ b/tests/unit/src/android/net/apf/ApfTestUtils.java
@@ -16,17 +16,43 @@ package android.net.apf; import static android.net.apf.ApfJniUtils.apfSimulate; +import static android.system.OsConstants.AF_UNIX; +import static android.system.OsConstants.SOCK_STREAM; 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.mock; + +import android.content.Context; +import android.net.LinkAddress; +import android.net.LinkProperties; +import android.net.ip.IIpClientCallbacks; +import android.net.ip.IpClient; +import android.os.ConditionVariable; +import android.os.SystemClock; +import android.system.ErrnoException; +import android.system.Os; +import android.text.format.DateUtils; import com.android.internal.util.HexDump; +import com.android.net.module.util.InterfaceParams; +import com.android.net.module.util.SharedLog; +import com.android.networkstack.apishim.NetworkInformationShimImpl; +import libcore.io.IoUtils; + +import java.io.FileDescriptor; +import java.io.IOException; +import java.net.InetAddress; import java.util.Arrays; /** * The util class for calling the APF interpreter and check the return value */ public class ApfTestUtils { + public static final int TIMEOUT_MS = 500; public static final int PASS = 1; public static final int DROP = 0; // Interpreter will just accept packets without link layer headers, so pad fake packet to at @@ -137,6 +163,15 @@ } } + /** + * Runs the APF program with customized data region and checks the return code. + */ + public static void assertVerdict(int apfVersion, int expected, byte[] program, byte[] packet, + byte[] data) { + assertReturnCodesEqual(expected, + apfSimulate(apfVersion, program, packet, data, 0 /* filterAge */)); + } + private static void assertVerdict(int apfVersion, int expected, ApfGenerator gen, byte[] packet, int filterAge) throws ApfGenerator.IllegalInstructionException { assertReturnCodesEqual(expected, @@ -174,4 +209,134 @@ throws ApfGenerator.IllegalInstructionException { assertVerdict(apfVersion, DROP, gen, new byte[MIN_PKT_SIZE], 0); } + + /** + * The Mock ip client callback class. + */ + public static class MockIpClientCallback extends IpClient.IpClientCallbacksWrapper { + private final ConditionVariable mGotApfProgram = new ConditionVariable(); + private byte[] mLastApfProgram; + + MockIpClientCallback() { + super(mock(IIpClientCallbacks.class), mock(SharedLog.class), + NetworkInformationShimImpl.newInstance()); + } + + @Override + public void installPacketFilter(byte[] filter) { + mLastApfProgram = filter; + mGotApfProgram.open(); + } + + /** + * Reset the apf program and wait for the next update. + */ + public void resetApfProgramWait() { + mGotApfProgram.close(); + } + + /** + * Assert the program is update within TIMEOUT_MS and return the program. + */ + public byte[] assertProgramUpdateAndGet() { + assertTrue(mGotApfProgram.block(TIMEOUT_MS)); + return mLastApfProgram; + } + + /** + * Assert the program is not update within TIMEOUT_MS. + */ + public void assertNoProgramUpdate() { + assertFalse(mGotApfProgram.block(TIMEOUT_MS)); + } + } + + /** + * The test apf filter class. + */ + public static class TestApfFilter extends ApfFilter { + public static final byte[] MOCK_MAC_ADDR = {1, 2, 3, 4, 5, 6}; + private static final byte[] MOCK_IPV4_ADDR = {10, 0, 0, 1}; + + private FileDescriptor mWriteSocket; + private long mCurrentTimeMs = SystemClock.elapsedRealtime(); + private final MockIpClientCallback mMockIpClientCb; + + public TestApfFilter(Context context, ApfConfiguration config, + MockIpClientCallback ipClientCallback) throws Exception { + this(context, config, ipClientCallback, new Dependencies(context)); + } + + public TestApfFilter(Context context, ApfConfiguration config, + MockIpClientCallback ipClientCallback, Dependencies dependencies) { + super(context, config, InterfaceParams.getByName("lo"), ipClientCallback, dependencies); + mMockIpClientCb = ipClientCallback; + } + + /** + * Create a new test ApfFiler. + */ + public static ApfFilter createTestApfFilter(Context context, + MockIpClientCallback ipClientCallback, ApfConfiguration config, + ApfFilter.Dependencies dependencies) throws Exception { + LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19); + LinkProperties lp = new LinkProperties(); + lp.addLinkAddress(link); + TestApfFilter apfFilter = new TestApfFilter(context, config, ipClientCallback, + dependencies); + apfFilter.setLinkProperties(lp); + return apfFilter; + } + + /** + * Pretend an RA packet has been received and show it to ApfFilter. + */ + public void pretendPacketReceived(byte[] packet) throws IOException, ErrnoException { + mMockIpClientCb.resetApfProgramWait(); + // ApfFilter's ReceiveThread will be waiting to read this. + Os.write(mWriteSocket, packet, 0, packet.length); + } + + /** + * Simulate current time changes. + */ + public void increaseCurrentTimeSeconds(int delta) { + mCurrentTimeMs += delta * DateUtils.SECOND_IN_MILLIS; + } + + @Override + protected int secondsSinceBoot() { + return (int) (mCurrentTimeMs / DateUtils.SECOND_IN_MILLIS); + } + + @Override + public synchronized void maybeStartFilter() { + mHardwareAddress = MOCK_MAC_ADDR; + installNewProgramLocked(); + + // Create two sockets, "readSocket" and "mWriteSocket" and connect them together. + FileDescriptor readSocket = new FileDescriptor(); + mWriteSocket = new FileDescriptor(); + try { + Os.socketpair(AF_UNIX, SOCK_STREAM, 0, mWriteSocket, readSocket); + } catch (ErrnoException e) { + fail(); + return; + } + // Now pass readSocket to ReceiveThread as if it was setup to read raw RAs. + // This allows us to pretend RA packets have been received via pretendPacketReceived(). + mReceiveThread = new ReceiveThread(readSocket); + mReceiveThread.start(); + } + + @Override + public void shutdown() { + super.shutdown(); + if (mReceiveThread != null) { + mReceiveThread.halt(); + mReceiveThread = null; + } + IoUtils.closeQuietly(mWriteSocket); + } + } }
diff --git a/tests/unit/src/android/net/dhcp6/Dhcp6PacketTest.kt b/tests/unit/src/android/net/dhcp6/Dhcp6PacketTest.kt index de97ed4..00e480b 100644 --- a/tests/unit/src/android/net/dhcp6/Dhcp6PacketTest.kt +++ b/tests/unit/src/android/net/dhcp6/Dhcp6PacketTest.kt
@@ -20,7 +20,7 @@ import androidx.test.runner.AndroidJUnit4 import com.android.net.module.util.HexDump import com.android.testutils.assertThrows -import java.nio.ByteBuffer +import kotlin.test.assertEquals import kotlin.test.assertTrue import org.junit.Test import org.junit.runner.RunWith @@ -42,7 +42,7 @@ // IA prefix option(option_len=25) "001A001900000000000000004000000000000000000000000000000000" val bytes = HexDump.hexStringToByteArray(solicitHex) - val packet = Dhcp6Packet.decode(ByteBuffer.wrap(bytes)) + val packet = Dhcp6Packet.decode(bytes, bytes.size) assertTrue(packet is Dhcp6SolicitPacket) } @@ -61,7 +61,7 @@ "001A001900000000000000004000000000000000000000000000000000" val bytes = HexDump.hexStringToByteArray(solicitHex) assertThrows(Dhcp6Packet.ParseException::class.java) { - Dhcp6Packet.decode(ByteBuffer.wrap(bytes)) + Dhcp6Packet.decode(bytes, bytes.size) } } @@ -80,7 +80,7 @@ "001A0019000000000000000040000000000000000000000000000000" val bytes = HexDump.hexStringToByteArray(solicitHex) assertThrows(Dhcp6Packet.ParseException::class.java) { - Dhcp6Packet.decode(ByteBuffer.wrap(bytes)) + Dhcp6Packet.decode(bytes, bytes.size) } } @@ -99,7 +99,7 @@ "001A001900000000000000004000000000000000000000000000000000" val bytes = HexDump.hexStringToByteArray(solicitHex) assertThrows(Dhcp6Packet.ParseException::class.java) { - Dhcp6Packet.decode(ByteBuffer.wrap(bytes)) + Dhcp6Packet.decode(bytes, bytes.size) } } @@ -119,7 +119,7 @@ // IA prefix option(option_len=25, prefix="fdfd:9ed6:7950:2::/64") "001A00190000019F0000A8C040FDFD9ED6795000010000000000000000" val bytes = HexDump.hexStringToByteArray(advertiseHex) - val packet = Dhcp6Packet.decode(ByteBuffer.wrap(bytes)) + val packet = Dhcp6Packet.decode(bytes, bytes.size) assertTrue(packet is Dhcp6AdvertisePacket) } @@ -142,7 +142,37 @@ "001A00190000019F0000A8C040FDFD9ED6795000010000000000000000" val bytes = HexDump.hexStringToByteArray(advertiseHex) // The unsupported option will be skipped normally and won't throw ParseException. - val packet = Dhcp6Packet.decode(ByteBuffer.wrap(bytes)) + val packet = Dhcp6Packet.decode(bytes, bytes.size) assertTrue(packet is Dhcp6AdvertisePacket) } + + @Test + fun testDecodeDhcp6ReplyPacket() { + val replyHex = + // Reply, Transaction ID + "07000A47" + + // server identifier option(option_len=10) + "0002000A0003000186C9B26AED4D" + + // client identifier option(option_len=12) + "0001000C0003001B02FBBAFFFEB7BC71" + + // SOL_MAX_RT (don't support this option yet) + "005200040000003c" + + // Rapid Commit + "000e0000" + + // DNS recursive server (don't support this opton yet) + "00170010fdfd9ed6795000000000000000000001" + + // IA_PD option(option_len=70, including IA prefix option) + "0019004629cc56c7000000d300000152" + + // IA prefix option(option_len=25, prefix="2401:fa00:49c:412::/64", preferred=400, + // valid=1623) + "001a00190000019000000657402401fa00049c04120000000000000000" + + // IA prefix option(option_len=25, prefix="fdfd:9ed6:7950:2::/64", preferred=423, + // valid=43200) + "001a0019000001a70000a8c040fdfd9ed6795000020000000000000000" + val bytes = HexDump.hexStringToByteArray(replyHex) + val packet = Dhcp6Packet.decode(bytes, bytes.size) + assertTrue(packet is Dhcp6ReplyPacket) + assertEquals(400, packet.prefixDelegation.minimalPreferredLifetime) + assertEquals(1623, packet.prefixDelegation.minimalValidLifetime) + } }
diff --git a/tests/unit/src/android/net/ip/IpClientTest.java b/tests/unit/src/android/net/ip/IpClientTest.java index d8b2cc2..4e40fa2 100644 --- a/tests/unit/src/android/net/ip/IpClientTest.java +++ b/tests/unit/src/android/net/ip/IpClientTest.java
@@ -25,6 +25,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.clearInvocations; @@ -86,6 +87,8 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.io.FileDescriptor; +import java.io.PrintWriter; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; @@ -147,6 +150,8 @@ @Mock private IpMemoryStoreService mIpMemoryStoreService; @Mock private InterfaceParams mInterfaceParams; @Mock private IpConnectivityLog mMetricsLog; + @Mock private FileDescriptor mFd; + @Mock private PrintWriter mWriter; private NetworkObserver mObserver; private InterfaceParams mIfParams; @@ -702,7 +707,7 @@ final ArgumentCaptor<ApfConfiguration> configCaptor = ArgumentCaptor.forClass( ApfConfiguration.class); verify(mDependencies, timeout(TEST_TIMEOUT_MS)).maybeCreateApfFilter( - any(), configCaptor.capture(), any(), any()); + any(), configCaptor.capture(), any(), any(), anyBoolean()); return configCaptor.getValue(); } @@ -771,7 +776,7 @@ final ArgumentCaptor<ApfConfiguration> configCaptor = ArgumentCaptor.forClass( ApfConfiguration.class); verify(mDependencies, timeout(TEST_TIMEOUT_MS)).maybeCreateApfFilter( - any(), configCaptor.capture(), any(), any()); + any(), configCaptor.capture(), any(), any(), anyBoolean()); final ApfConfiguration actual = configCaptor.getValue(); assertNotNull(actual); assertEquals(4, actual.apfCapabilities.apfVersionSupported); @@ -782,6 +787,17 @@ } @Test + public void testDumpApfFilter_withNoException() throws Exception { + final IpClient ipc = makeIpClient(TEST_IFNAME); + final ApfConfiguration config = verifyApfFilterCreatedOnStart(ipc, + false /* isApfSupported */); + assertNull(config.apfCapabilities); + clearInvocations(mDependencies); + ipc.dump(mFd, mWriter, null /* args */); + verifyShutdown(ipc); + } + + @Test public void testApfUpdateCapabilities_nonNullInitialApfCapabilities() throws Exception { final IpClient ipc = makeIpClient(TEST_IFNAME); final ApfConfiguration config = verifyApfFilterCreatedOnStart(ipc, @@ -793,7 +809,8 @@ 8192 /* maxProgramSize */, 4 /* format */); ipc.updateApfCapabilities(newApfCapabilities); HandlerUtils.waitForIdle(ipc.getHandler(), TEST_TIMEOUT_MS); - verify(mDependencies, never()).maybeCreateApfFilter(any(), any(), any(), any()); + verify(mDependencies, never()).maybeCreateApfFilter(any(), any(), any(), any(), + anyBoolean()); verifyShutdown(ipc); } @@ -807,7 +824,8 @@ ipc.updateApfCapabilities(null /* apfCapabilities */); HandlerUtils.waitForIdle(ipc.getHandler(), TEST_TIMEOUT_MS); - verify(mDependencies, never()).maybeCreateApfFilter(any(), any(), any(), any()); + verify(mDependencies, never()).maybeCreateApfFilter(any(), any(), any(), any(), + anyBoolean()); verifyShutdown(ipc); }
diff --git a/tests/unit/src/android/net/shared/PrivateDnsConfigTest.java b/tests/unit/src/android/net/shared/PrivateDnsConfigTest.java new file mode 100644 index 0000000..94f04d5 --- /dev/null +++ b/tests/unit/src/android/net/shared/PrivateDnsConfigTest.java
@@ -0,0 +1,133 @@ +/* + * Copyright (C) 2023 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.shared; + +import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OFF; +import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OPPORTUNISTIC; +import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +import android.net.PrivateDnsConfigParcel; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import java.net.InetAddress; + +@RunWith(JUnit4.class) +public final class PrivateDnsConfigTest { + private static final int OFF_MODE = PRIVATE_DNS_MODE_OFF; + private static final int OPPORTUNISTIC_MODE = PRIVATE_DNS_MODE_OPPORTUNISTIC; + private static final int STRICT_MODE = PRIVATE_DNS_MODE_PROVIDER_HOSTNAME; + + private static final InetAddress[] TEST_ADDRS = new InetAddress[] { + InetAddress.parseNumericAddress("1.2.3.4"), + InetAddress.parseNumericAddress("2001:db8::2"), + }; + + private String[] toStringArray(InetAddress[] ips) { + String[] out = new String[ips.length]; + int i = 0; + for (InetAddress ip : ips) { + out[i++] = ip.getHostAddress(); + } + return out; + } + + private void assertPrivateDnsConfigEquals(PrivateDnsConfig a, PrivateDnsConfig b) { + assertEquals(a.mode, b.mode); + assertEquals(a.hostname, b.hostname); + assertArrayEquals(a.ips, b.ips); + assertEquals(a.dohName, b.dohName); + assertArrayEquals(a.dohIps, b.dohIps); + assertEquals(a.dohPath, b.dohPath); + assertEquals(a.dohPort, b.dohPort); + } + + private void assertParcelEquals(PrivateDnsConfig cfg, PrivateDnsConfigParcel parcel) { + assertEquals(parcel.privateDnsMode, cfg.mode); + assertEquals(parcel.hostname, cfg.hostname); + assertArrayEquals(parcel.ips, toStringArray(cfg.ips)); + assertEquals(parcel.dohName, cfg.dohName); + assertEquals(parcel.dohPath, cfg.dohPath); + assertEquals(parcel.dohPort, cfg.dohPort); + assertArrayEquals(parcel.dohIps, toStringArray(cfg.dohIps)); + } + + // Tests both toParcel() and fromParcel() together. + private void testPrivateDnsConfigConversion(PrivateDnsConfig cfg) { + final PrivateDnsConfigParcel parcel = cfg.toParcel(); + assertParcelEquals(cfg, parcel); + + final PrivateDnsConfig convertedCfg = PrivateDnsConfig.fromParcel(parcel); + assertPrivateDnsConfigEquals(cfg, convertedCfg); + } + + // Tests that a PrivateDnsConfig and a PrivateDnsConfig that is converted from + // PrivateDnsConfigParcel are equal. + @Test + public void testParcelableConversion() { + // Test the constructor: PrivateDnsConfig() + testPrivateDnsConfigConversion(new PrivateDnsConfig()); + + // Test the constructor: PrivateDnsConfig(boolean useTls) + testPrivateDnsConfigConversion(new PrivateDnsConfig(true)); + testPrivateDnsConfigConversion(new PrivateDnsConfig(false)); + + // Test the constructor: PrivateDnsConfig(String hostname, InetAddress[] ips) + testPrivateDnsConfigConversion(new PrivateDnsConfig(null, null)); + testPrivateDnsConfigConversion(new PrivateDnsConfig(null, TEST_ADDRS)); + testPrivateDnsConfigConversion(new PrivateDnsConfig("dns.com", null)); + testPrivateDnsConfigConversion(new PrivateDnsConfig("dns.com", TEST_ADDRS)); + + // Test the constructor: + // PrivateDnsConfig(int mode, String hostname, InetAddress[] ips, + // String dohName, InetAddress[] dohIps, String dohPath, int dohPort) + for (int mode : new int[] { OFF_MODE, OPPORTUNISTIC_MODE, STRICT_MODE }) { + testPrivateDnsConfigConversion(new PrivateDnsConfig(mode, null, null, + null, null, null, -1)); + testPrivateDnsConfigConversion(new PrivateDnsConfig(mode, "dns.com", null, + null, null, null, -1)); + testPrivateDnsConfigConversion(new PrivateDnsConfig(mode, "dns.com", TEST_ADDRS, + null, null, null, -1)); + testPrivateDnsConfigConversion(new PrivateDnsConfig(mode, "dns.com", TEST_ADDRS, + "doh.com", null, null, -1)); + testPrivateDnsConfigConversion(new PrivateDnsConfig(mode, "dns.com", TEST_ADDRS, + "doh.com", TEST_ADDRS, null, -1)); + testPrivateDnsConfigConversion(new PrivateDnsConfig(mode, "dns.com", TEST_ADDRS, + "doh.com", TEST_ADDRS, "dohpath=/some-path{?dns}", -1)); + testPrivateDnsConfigConversion(new PrivateDnsConfig(mode, "dns.com", TEST_ADDRS, + "doh.com", TEST_ADDRS, "dohpath=/some-path{?dns}", 443)); + } + } + + @Test + public void testIpAddressArrayIsCopied() { + final InetAddress ip = InetAddress.parseNumericAddress("1.2.3.4"); + final InetAddress[] ipArray = new InetAddress[] { ip }; + final PrivateDnsConfig cfg = new PrivateDnsConfig(OPPORTUNISTIC_MODE, null /* hostname */, + ipArray /* ips */, null /* dohName */, ipArray /* dohIps */, null /* dohPath */, + -1 /* dohPort */); + + ipArray[0] = InetAddress.parseNumericAddress("2001:db8::2"); + assertArrayEquals(new InetAddress[] { ip }, cfg.ips); + assertArrayEquals(new InetAddress[] { ip }, cfg.dohIps); + } +}
diff --git a/tests/unit/src/com/android/networkstack/netlink/TcpInfoTest.java b/tests/unit/src/com/android/networkstack/netlink/TcpInfoTest.java index 380f4ec..ff56f5f 100644 --- a/tests/unit/src/com/android/networkstack/netlink/TcpInfoTest.java +++ b/tests/unit/src/com/android/networkstack/netlink/TcpInfoTest.java
@@ -242,4 +242,20 @@ return info; } + + @Test + public void testHashCode() { + final TcpInfo info = new TcpInfo(2, 1, 5); + final TcpInfo info2 = new TcpInfo(2, 1, 5); + + assertEquals(info, info2); + assertEquals(info.hashCode(), info2.hashCode()); + } + + @Test + public void testDecodeWscale() { + assertEquals("0:0", TcpInfo.decodeWscale((byte) 0)); + assertEquals("15:15", TcpInfo.decodeWscale((byte) 255)); + assertEquals("15:0", TcpInfo.decodeWscale((byte) 240)); + } }
diff --git a/tests/unit/src/com/android/networkstack/netlink/TcpSocketTrackerTest.java b/tests/unit/src/com/android/networkstack/netlink/TcpSocketTrackerTest.java index 165deab..ab9816c 100644 --- a/tests/unit/src/com/android/networkstack/netlink/TcpSocketTrackerTest.java +++ b/tests/unit/src/com/android/networkstack/netlink/TcpSocketTrackerTest.java
@@ -180,7 +180,8 @@ public void testParseSockInfo() { final ByteBuffer buffer = getByteBuffer(SOCK_DIAG_TCP_INET_TEST_BYTES); final ArrayList<TcpSocketTracker.SocketInfo> infoList = new ArrayList<>(); - TcpSocketTracker.parseMessage(buffer, AF_INET, infoList, 100L); + final TcpSocketTracker tst = new TcpSocketTracker(mDependencies, mNetwork); + tst.parseMessage(buffer, AF_INET, infoList, 100L); assertEquals(1, infoList.size()); final TcpSocketTracker.SocketInfo parsed = infoList.get(0);
diff --git a/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java b/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java index 3f2ff31..b29ea16 100644 --- a/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java +++ b/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java
@@ -32,6 +32,7 @@ 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_NOT_SUSPENDED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID; import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED; @@ -62,6 +63,7 @@ import static com.android.networkstack.util.NetworkStackUtils.CAPTIVE_PORTAL_USE_HTTPS; import static com.android.networkstack.util.NetworkStackUtils.DEFAULT_CAPTIVE_PORTAL_DNS_PROBE_TIMEOUT; import static com.android.networkstack.util.NetworkStackUtils.DNS_PROBE_PRIVATE_IP_NO_INTERNET_VERSION; +import static com.android.networkstack.util.NetworkStackUtils.REEVALUATE_WHEN_RESUME; import static com.android.server.connectivity.NetworkMonitor.INITIAL_REEVALUATE_DELAY_MS; import static com.android.server.connectivity.NetworkMonitor.extractCharset; @@ -319,10 +321,17 @@ return lp; } - private static final NetworkCapabilities CELL_METERED_CAPABILITIES = new NetworkCapabilities() + private static final NetworkCapabilities CELL_SUSPENDED_METERED_CAPABILITIES = + new NetworkCapabilities() .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) .addCapability(NET_CAPABILITY_INTERNET); + private static final NetworkCapabilities CELL_METERED_CAPABILITIES = + new NetworkCapabilities() + .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) + .addCapability(NET_CAPABILITY_INTERNET) + .addCapability(NET_CAPABILITY_NOT_SUSPENDED); + private static final NetworkCapabilities CELL_NOT_METERED_CAPABILITIES = new NetworkCapabilities() .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) @@ -554,6 +563,7 @@ initHttpConnection(mHttpConnection); initHttpConnection(mHttpsConnection); initHttpConnection(mFallbackConnection); + initHttpConnection(mOtherFallbackConnection); mFakeDns = new FakeDns(); mFakeDns.startMocking(); @@ -2290,6 +2300,51 @@ } @Test + public void testReevaluationInterval_networkResume() throws Exception { + // Setup nothing and expect validation to fail. + doReturn(true).when(mDependencies) + .isFeatureNotChickenedOut(any(), eq(REEVALUATE_WHEN_RESUME)); + final NetworkMonitor nm = runFailedNetworkTest(); + verifyNetworkTested(VALIDATION_RESULT_INVALID, 0 /* probesSucceeded */, + 1 /* interactions */); + // Reevaluation delay doubled right after 1st validation failure. + assertEquals(INITIAL_REEVALUATE_DELAY_MS * 2, nm.getReevaluationDelayMs()); + + // Suspend the network. Verify re-evaluation count does not increase. + setNetworkCapabilities(nm, CELL_SUSPENDED_METERED_CAPABILITIES); + verifyNetworkTested(VALIDATION_RESULT_INVALID, 0 /* probesSucceeded */, + 1 /* interactions */); + // Verify the count does not increase. + assertEquals(INITIAL_REEVALUATE_DELAY_MS * 2, nm.getReevaluationDelayMs()); + + // Resume the network, verify re-evaluation runs immediately and the timer resets. + setNetworkCapabilities(nm, CELL_METERED_CAPABILITIES); + // Wait for another idle to prevent from flaky because the handler fires another message + // to re-evaluate. + HandlerUtils.waitForIdle(nm.getHandler(), HANDLER_TIMEOUT_MS); + assertEquals(INITIAL_REEVALUATE_DELAY_MS, nm.getReevaluationDelayMs()); + verifyNetworkTested(VALIDATION_RESULT_INVALID, 0 /* probesSucceeded */, + 2 /* interactions */); + } + + @Test + public void testReevaluationInterval_verifiedNetwork() throws Exception { + final WrappedNetworkMonitor wnm = prepareValidatedStateNetworkMonitor( + CELL_METERED_CAPABILITIES); + assertEquals(INITIAL_REEVALUATE_DELAY_MS, wnm.getReevaluationDelayMs()); + + // Suspend the network. Verify re-evaluation count does not increase. + setNetworkCapabilities(wnm, CELL_SUSPENDED_METERED_CAPABILITIES); + verifyNetworkTestedValidFromHttps(1 /* interactions */); + assertEquals(INITIAL_REEVALUATE_DELAY_MS, wnm.getReevaluationDelayMs()); + + // Resume the network. Verify re-evaluation count does not increase. + setNetworkCapabilities(wnm, CELL_METERED_CAPABILITIES); + verifyNetworkTestedValidFromHttps(1 /* interactions */); + assertEquals(INITIAL_REEVALUATE_DELAY_MS, wnm.getReevaluationDelayMs()); + } + + @Test public void testDataStall_setOpportunisticMode() { setDataStallEvaluationType(DATA_STALL_EVALUATION_TYPE_TCP); WrappedNetworkMonitor wnm = makeCellNotMeteredNetworkMonitor(); @@ -2328,7 +2383,7 @@ private void testDataStall_StallDnsSuspectedAndSendMetrics(int transport, NetworkCapabilities nc) throws Exception { // NM suspects data stall from DNS signal and sends data stall metrics. - final WrappedNetworkMonitor nm = prepareNetworkMonitorForVerifyDataStall(nc); + final WrappedNetworkMonitor nm = prepareValidatedStateNetworkMonitor(nc); makeDnsTimeoutEvent(nm, 5); // Trigger a dns signal to start evaluate data stall and upload metrics. nm.notifyDnsResponse(RETURN_CODE_DNS_TIMEOUT); @@ -2338,7 +2393,7 @@ @Test public void testDataStall_NoStallSuspectedAndSendMetrics() throws Exception { - final WrappedNetworkMonitor nm = prepareNetworkMonitorForVerifyDataStall( + final WrappedNetworkMonitor nm = prepareValidatedStateNetworkMonitor( CELL_METERED_CAPABILITIES); // Setup no data stall dns signal. makeDnsTimeoutEvent(nm, 3); @@ -2360,12 +2415,11 @@ private void testDataStall_StallTcpSuspectedAndSendMetrics(NetworkCapabilities nc) throws Exception { - assumeTrue(ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q)); setupTcpDataStall(); - setTcpPollingInterval(0); + setTcpPollingInterval(1); // NM suspects data stall from TCP signal and sends data stall metrics. setDataStallEvaluationType(DATA_STALL_EVALUATION_TYPE_TCP); - final WrappedNetworkMonitor nm = prepareNetworkMonitorForVerifyDataStall(nc); + final WrappedNetworkMonitor nm = prepareValidatedStateNetworkMonitor(nc); // Trigger a tcp event immediately. nm.sendTcpPollingEvent(); // Allow only one transport type in the context of this test for simplification. @@ -2374,7 +2428,7 @@ verifySendDataStallDetectionStats(nm, DATA_STALL_EVALUATION_TYPE_TCP, transports[0]); } - private WrappedNetworkMonitor prepareNetworkMonitorForVerifyDataStall(NetworkCapabilities nc) + private WrappedNetworkMonitor prepareValidatedStateNetworkMonitor(NetworkCapabilities nc) throws Exception { // Connect a VALID network to simulate the data stall detection because data stall // evaluation will only start from validated state. @@ -2411,7 +2465,9 @@ ArgumentCaptor.forClass(CaptivePortalProbeResult.class); final ArgumentCaptor<DataStallDetectionStats> statsCaptor = ArgumentCaptor.forClass(DataStallDetectionStats.class); - verify(mDependencies, timeout(HANDLER_TIMEOUT_MS).times(1)) + // TCP data stall detection may be triggered more than once because NM stays in the + // ValidatedState and polling timer is set to 0. + verify(mDependencies, timeout(HANDLER_TIMEOUT_MS).atLeast(1)) .writeDataStallDetectionStats(statsCaptor.capture(), probeResultCaptor.capture()); // Ensure probe will not stop due to rate-limiting mechanism. nm.setLastProbeTime(SystemClock.elapsedRealtime() - STALL_EXPECTED_LAST_PROBE_TIME_MS); @@ -2566,26 +2622,22 @@ @Test public void testCollectDataStallMetrics_TcpWithCellular() { - assumeTrue(ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q)); testDataStallMetricsWithCellular(DATA_STALL_EVALUATION_TYPE_TCP); } @Test public void testCollectDataStallMetrics_TcpWithWiFi() { - assumeTrue(ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q)); testDataStallMetricsWithWiFi(DATA_STALL_EVALUATION_TYPE_TCP); } @Test public void testCollectDataStallMetrics_TcpAndDnsWithWifi() { - assumeTrue(ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q)); testDataStallMetricsWithWiFi( DATA_STALL_EVALUATION_TYPE_TCP | DATA_STALL_EVALUATION_TYPE_DNS); } @Test public void testCollectDataStallMetrics_TcpAndDnsWithCellular() { - assumeTrue(ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q)); testDataStallMetricsWithCellular( DATA_STALL_EVALUATION_TYPE_TCP | DATA_STALL_EVALUATION_TYPE_DNS); } @@ -2672,19 +2724,17 @@ @Test public void testNotifyNetwork_WithforceReevaluation() throws Exception { + // Set validated result for both HTTP and HTTPS probes. setValidProbes(); final NetworkMonitor nm = runValidatedNetworkTest(); // Verify forceReevaluation will not reset the validation result but only probe result until // getting the validation result. setSslException(mHttpsConnection); - setStatus(mHttpConnection, 500); - setStatus(mFallbackConnection, 204); nm.forceReevaluation(Process.myUid()); // Expect to send HTTP, HTTPs, FALLBACK and evaluation results. - verifyNetworkTested(VALIDATION_RESULT_INVALID, - NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_FALLBACK, + verifyNetworkTested(NETWORK_VALIDATION_RESULT_PARTIAL, + NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP, 1 /* interactions */); - HandlerUtils.waitForIdle(nm.getHandler(), HANDLER_TIMEOUT_MS); } @Test