diff --git a/Android.bp b/Android.bp index 4a2236980fa33..9023a19b72825 100644 --- a/Android.bp +++ b/Android.bp @@ -284,10 +284,11 @@ java_defaults { generate_get_transaction_name: true, local_include_dirs: [ "media/aidl", - // TODO: move to include_dirs when migrated to packages/modules - "packages/Connectivity/framework/aidl-export", ], - include_dirs: ["frameworks/av/aidl"], + include_dirs: [ + "frameworks/av/aidl", + "packages/modules/Connectivity/framework/aidl-export", + ], }, dxflags: [ "--core-library", @@ -524,12 +525,12 @@ stubs_defaults { local_include_dirs: [ "apex/media/aidl/stable", "media/aidl", - // TODO: move to include-dirs for packages/modules/Connectivity when this moves out of - // frameworks/base - "packages/Connectivity/framework/aidl-export", "telephony/java", ], - include_dirs: ["frameworks/av/aidl"], + include_dirs: [ + "frameworks/av/aidl", + "packages/modules/Connectivity/framework/aidl-export", + ], }, // These are libs from framework-internal-utils that are required (i.e. being referenced) // from framework-non-updatable-sources. Add more here when there's a need. diff --git a/packages/Connectivity/OWNERS b/packages/Connectivity/OWNERS deleted file mode 100644 index 48e54da82cc2b..0000000000000 --- a/packages/Connectivity/OWNERS +++ /dev/null @@ -1,3 +0,0 @@ -set noparent - -include platform/frameworks/base:/services/core/java/com/android/server/net/OWNERS diff --git a/packages/Connectivity/TEST_MAPPING b/packages/Connectivity/TEST_MAPPING deleted file mode 100644 index 94f9232bc4820..0000000000000 --- a/packages/Connectivity/TEST_MAPPING +++ /dev/null @@ -1,19 +0,0 @@ -{ - "imports": [ - { - "path": "frameworks/base/core/java/android/net" - }, - { - "path": "packages/modules/NetworkStack" - }, - { - "path": "packages/modules/CaptivePortalLogin" - }, - { - "path": "packages/modules/Connectivity" - }, - { - "path": "packages/modules/Connectivity/Tethering" - } - ] -} \ No newline at end of file diff --git a/packages/Connectivity/framework/Android.bp b/packages/Connectivity/framework/Android.bp deleted file mode 100644 index 6eb83484ccc84..0000000000000 --- a/packages/Connectivity/framework/Android.bp +++ /dev/null @@ -1,165 +0,0 @@ -// -// Copyright (C) 2020 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_base_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_base_license"], -} - -filegroup { - name: "framework-connectivity-internal-sources", - srcs: [ - "src/**/*.java", - "src/**/*.aidl", - ], - path: "src", - visibility: [ - "//visibility:private", - ], -} - -filegroup { - name: "framework-connectivity-aidl-export-sources", - srcs: [ - "aidl-export/**/*.aidl", - ], - path: "aidl-export", - visibility: [ - "//visibility:private", - ], -} - -// TODO: use a java_library in the bootclasspath instead -filegroup { - name: "framework-connectivity-sources", - srcs: [ - ":framework-connectivity-internal-sources", - ":framework-connectivity-aidl-export-sources", - ], - visibility: [ - "//frameworks/base", - "//packages/modules/Connectivity:__subpackages__", - ], -} - -java_library { - name: "framework-connectivity-annotations", - sdk_version: "module_current", - srcs: [ - "src/android/net/ConnectivityAnnotations.java", - ], - libs: [ - "framework-annotations-lib", - "framework-connectivity", - ], - visibility: [ - "//frameworks/base:__subpackages__", - "//packages/modules/Connectivity:__subpackages__", - ], -} - -java_sdk_library { - name: "framework-connectivity", - sdk_version: "module_current", - min_sdk_version: "30", - defaults: ["framework-module-defaults"], - installable: true, - srcs: [ - ":framework-connectivity-sources", - ":net-utils-framework-common-srcs", - ], - aidl: { - include_dirs: [ - // Include directories for parcelables that are part of the stable API, and need a - // one-line "parcelable X" .aidl declaration to be used in AIDL interfaces. - // TODO(b/180293679): remove these dependencies as they should not be necessary once - // the module builds against API (the parcelable declarations exist in framework.aidl) - "frameworks/base/core/java", // For framework parcelables - "frameworks/native/aidl/binder", // For PersistableBundle.aidl - ], - }, - impl_only_libs: [ - // TODO (b/183097033) remove once module_current includes core_platform - "stable.core.platform.api.stubs", - "framework-tethering.stubs.module_lib", - "framework-wifi.stubs.module_lib", - "net-utils-device-common", - ], - libs: [ - "unsupportedappusage", - ], - jarjar_rules: "jarjar-rules.txt", - permitted_packages: ["android.net"], - impl_library_visibility: [ - "//packages/modules/Connectivity/Tethering/apex", - // In preparation for future move - "//packages/modules/Connectivity/apex", - "//packages/modules/Connectivity/service", - "//frameworks/base/packages/Connectivity/service", - "//frameworks/base", - - // Tests using hidden APIs - "//cts/tests/netlegacy22.api", - "//external/sl4a:__subpackages__", - "//frameworks/base/packages/Connectivity/tests:__subpackages__", - "//frameworks/libs/net/common/testutils", - "//frameworks/libs/net/common/tests:__subpackages__", - "//frameworks/opt/telephony/tests/telephonytests", - "//packages/modules/CaptivePortalLogin/tests", - "//packages/modules/Connectivity/Tethering/tests:__subpackages__", - "//packages/modules/Connectivity/tests:__subpackages__", - "//packages/modules/NetworkStack/tests:__subpackages__", - "//packages/modules/Wifi/service/tests/wifitests", - ], - apex_available: [ - "com.android.tethering", - ], -} - -cc_library_shared { - name: "libframework-connectivity-jni", - min_sdk_version: "30", - cflags: [ - "-Wall", - "-Werror", - "-Wno-unused-parameter", - // Don't warn about S API usage even with - // min_sdk 30: the library is only loaded - // on S+ devices - "-Wno-unguarded-availability", - "-Wthread-safety", - ], - srcs: [ - "jni/android_net_NetworkUtils.cpp", - "jni/onload.cpp", - ], - shared_libs: [ - "libandroid", - "liblog", - "libnativehelper", - ], - header_libs: [ - "dnsproxyd_protocol_headers", - ], - stl: "none", - apex_available: [ - "com.android.tethering", - ], -} diff --git a/packages/Connectivity/framework/aidl-export/android/net/CaptivePortalData.aidl b/packages/Connectivity/framework/aidl-export/android/net/CaptivePortalData.aidl deleted file mode 100644 index 1d57ee7591360..0000000000000 --- a/packages/Connectivity/framework/aidl-export/android/net/CaptivePortalData.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -@JavaOnlyStableParcelable parcelable CaptivePortalData; diff --git a/packages/Connectivity/framework/aidl-export/android/net/ConnectivityDiagnosticsManager.aidl b/packages/Connectivity/framework/aidl-export/android/net/ConnectivityDiagnosticsManager.aidl deleted file mode 100644 index 82ba0ca113c56..0000000000000 --- a/packages/Connectivity/framework/aidl-export/android/net/ConnectivityDiagnosticsManager.aidl +++ /dev/null @@ -1,21 +0,0 @@ -/** - * - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -parcelable ConnectivityDiagnosticsManager.ConnectivityReport; -parcelable ConnectivityDiagnosticsManager.DataStallReport; \ No newline at end of file diff --git a/packages/Connectivity/framework/aidl-export/android/net/DhcpInfo.aidl b/packages/Connectivity/framework/aidl-export/android/net/DhcpInfo.aidl deleted file mode 100644 index 29cd21fe76522..0000000000000 --- a/packages/Connectivity/framework/aidl-export/android/net/DhcpInfo.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (c) 2008, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -parcelable DhcpInfo; diff --git a/packages/Connectivity/framework/aidl-export/android/net/IpConfiguration.aidl b/packages/Connectivity/framework/aidl-export/android/net/IpConfiguration.aidl deleted file mode 100644 index 7a30f0e79cad9..0000000000000 --- a/packages/Connectivity/framework/aidl-export/android/net/IpConfiguration.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -parcelable IpConfiguration; diff --git a/packages/Connectivity/framework/aidl-export/android/net/IpPrefix.aidl b/packages/Connectivity/framework/aidl-export/android/net/IpPrefix.aidl deleted file mode 100644 index 3495efc1f1d03..0000000000000 --- a/packages/Connectivity/framework/aidl-export/android/net/IpPrefix.aidl +++ /dev/null @@ -1,22 +0,0 @@ -/** - * - * Copyright (C) 2014 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; - -// @JavaOnlyStableParcelable only affects the parcelable when built as stable aidl (aidl_interface -// build rule). -@JavaOnlyStableParcelable parcelable IpPrefix; diff --git a/packages/Connectivity/framework/aidl-export/android/net/KeepalivePacketData.aidl b/packages/Connectivity/framework/aidl-export/android/net/KeepalivePacketData.aidl deleted file mode 100644 index d456b53fd1880..0000000000000 --- a/packages/Connectivity/framework/aidl-export/android/net/KeepalivePacketData.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -parcelable KeepalivePacketData; diff --git a/packages/Connectivity/framework/aidl-export/android/net/LinkAddress.aidl b/packages/Connectivity/framework/aidl-export/android/net/LinkAddress.aidl deleted file mode 100644 index 9c804db08d617..0000000000000 --- a/packages/Connectivity/framework/aidl-export/android/net/LinkAddress.aidl +++ /dev/null @@ -1,21 +0,0 @@ -/** - * - * Copyright (C) 2010 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; - -@JavaOnlyStableParcelable parcelable LinkAddress; - diff --git a/packages/Connectivity/framework/aidl-export/android/net/LinkProperties.aidl b/packages/Connectivity/framework/aidl-export/android/net/LinkProperties.aidl deleted file mode 100644 index a8b3c7b0392fb..0000000000000 --- a/packages/Connectivity/framework/aidl-export/android/net/LinkProperties.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* -** -** Copyright (C) 2010 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; - -@JavaOnlyStableParcelable parcelable LinkProperties; diff --git a/packages/Connectivity/framework/aidl-export/android/net/MacAddress.aidl b/packages/Connectivity/framework/aidl-export/android/net/MacAddress.aidl deleted file mode 100644 index 48a18a7ac8218..0000000000000 --- a/packages/Connectivity/framework/aidl-export/android/net/MacAddress.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/** - * - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -@JavaOnlyStableParcelable parcelable MacAddress; diff --git a/packages/Connectivity/framework/aidl-export/android/net/Network.aidl b/packages/Connectivity/framework/aidl-export/android/net/Network.aidl deleted file mode 100644 index 05622025bf33c..0000000000000 --- a/packages/Connectivity/framework/aidl-export/android/net/Network.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* -** -** Copyright (C) 2014 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; - -@JavaOnlyStableParcelable parcelable Network; diff --git a/packages/Connectivity/framework/aidl-export/android/net/NetworkAgentConfig.aidl b/packages/Connectivity/framework/aidl-export/android/net/NetworkAgentConfig.aidl deleted file mode 100644 index cb70bdd312605..0000000000000 --- a/packages/Connectivity/framework/aidl-export/android/net/NetworkAgentConfig.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -parcelable NetworkAgentConfig; diff --git a/packages/Connectivity/framework/aidl-export/android/net/NetworkCapabilities.aidl b/packages/Connectivity/framework/aidl-export/android/net/NetworkCapabilities.aidl deleted file mode 100644 index 01d328605de49..0000000000000 --- a/packages/Connectivity/framework/aidl-export/android/net/NetworkCapabilities.aidl +++ /dev/null @@ -1,21 +0,0 @@ -/* -** -** Copyright (C) 2014 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; - -@JavaOnlyStableParcelable parcelable NetworkCapabilities; - diff --git a/packages/Connectivity/framework/aidl-export/android/net/NetworkInfo.aidl b/packages/Connectivity/framework/aidl-export/android/net/NetworkInfo.aidl deleted file mode 100644 index f501873029669..0000000000000 --- a/packages/Connectivity/framework/aidl-export/android/net/NetworkInfo.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (c) 2007, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -parcelable NetworkInfo; diff --git a/packages/Connectivity/framework/aidl-export/android/net/NetworkRequest.aidl b/packages/Connectivity/framework/aidl-export/android/net/NetworkRequest.aidl deleted file mode 100644 index 508defc6b497f..0000000000000 --- a/packages/Connectivity/framework/aidl-export/android/net/NetworkRequest.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) 2014, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -parcelable NetworkRequest; - diff --git a/packages/Connectivity/framework/aidl-export/android/net/NetworkScore.aidl b/packages/Connectivity/framework/aidl-export/android/net/NetworkScore.aidl deleted file mode 100644 index af12dcf7f17a5..0000000000000 --- a/packages/Connectivity/framework/aidl-export/android/net/NetworkScore.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) 2021, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -parcelable NetworkScore; - diff --git a/packages/Connectivity/framework/aidl-export/android/net/OemNetworkPreferences.aidl b/packages/Connectivity/framework/aidl-export/android/net/OemNetworkPreferences.aidl deleted file mode 100644 index 2b6a4ceef592b..0000000000000 --- a/packages/Connectivity/framework/aidl-export/android/net/OemNetworkPreferences.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -parcelable OemNetworkPreferences; diff --git a/packages/Connectivity/framework/aidl-export/android/net/ProxyInfo.aidl b/packages/Connectivity/framework/aidl-export/android/net/ProxyInfo.aidl deleted file mode 100644 index a5d0c120e7474..0000000000000 --- a/packages/Connectivity/framework/aidl-export/android/net/ProxyInfo.aidl +++ /dev/null @@ -1,21 +0,0 @@ -/* -** -** Copyright (C) 2010 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; - -@JavaOnlyStableParcelable parcelable ProxyInfo; - diff --git a/packages/Connectivity/framework/aidl-export/android/net/QosFilterParcelable.aidl b/packages/Connectivity/framework/aidl-export/android/net/QosFilterParcelable.aidl deleted file mode 100644 index 312d6352ee920..0000000000000 --- a/packages/Connectivity/framework/aidl-export/android/net/QosFilterParcelable.aidl +++ /dev/null @@ -1,21 +0,0 @@ -/* -** -** Copyright (C) 2020 The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -package android.net; - -parcelable QosFilterParcelable; - diff --git a/packages/Connectivity/framework/aidl-export/android/net/QosSession.aidl b/packages/Connectivity/framework/aidl-export/android/net/QosSession.aidl deleted file mode 100644 index c2cf36624b554..0000000000000 --- a/packages/Connectivity/framework/aidl-export/android/net/QosSession.aidl +++ /dev/null @@ -1,21 +0,0 @@ -/* -** -** Copyright (C) 2020 The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -package android.net; - -parcelable QosSession; - diff --git a/packages/Connectivity/framework/aidl-export/android/net/QosSocketInfo.aidl b/packages/Connectivity/framework/aidl-export/android/net/QosSocketInfo.aidl deleted file mode 100644 index 476c0900e23ee..0000000000000 --- a/packages/Connectivity/framework/aidl-export/android/net/QosSocketInfo.aidl +++ /dev/null @@ -1,21 +0,0 @@ -/* -** -** Copyright (C) 2020 The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -package android.net; - -parcelable QosSocketInfo; - diff --git a/packages/Connectivity/framework/aidl-export/android/net/RouteInfo.aidl b/packages/Connectivity/framework/aidl-export/android/net/RouteInfo.aidl deleted file mode 100644 index 7af9fdaef3420..0000000000000 --- a/packages/Connectivity/framework/aidl-export/android/net/RouteInfo.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2011 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; - -@JavaOnlyStableParcelable parcelable RouteInfo; diff --git a/packages/Connectivity/framework/aidl-export/android/net/StaticIpConfiguration.aidl b/packages/Connectivity/framework/aidl-export/android/net/StaticIpConfiguration.aidl deleted file mode 100644 index 8aac701fe7e19..0000000000000 --- a/packages/Connectivity/framework/aidl-export/android/net/StaticIpConfiguration.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* -** -** Copyright (C) 2019 The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -package android.net; - -@JavaOnlyStableParcelable parcelable StaticIpConfiguration; \ No newline at end of file diff --git a/packages/Connectivity/framework/aidl-export/android/net/TestNetworkInterface.aidl b/packages/Connectivity/framework/aidl-export/android/net/TestNetworkInterface.aidl deleted file mode 100644 index e1f4f9f794eb6..0000000000000 --- a/packages/Connectivity/framework/aidl-export/android/net/TestNetworkInterface.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -/** @hide */ -parcelable TestNetworkInterface; diff --git a/packages/Connectivity/framework/aidl-export/android/net/apf/ApfCapabilities.aidl b/packages/Connectivity/framework/aidl-export/android/net/apf/ApfCapabilities.aidl deleted file mode 100644 index 7c4d4c2da4bce..0000000000000 --- a/packages/Connectivity/framework/aidl-export/android/net/apf/ApfCapabilities.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* -** -** Copyright (C) 2019 The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -package android.net.apf; - -@JavaOnlyStableParcelable parcelable ApfCapabilities; \ No newline at end of file diff --git a/packages/Connectivity/framework/api/current.txt b/packages/Connectivity/framework/api/current.txt deleted file mode 100644 index 33f4d14148e09..0000000000000 --- a/packages/Connectivity/framework/api/current.txt +++ /dev/null @@ -1,476 +0,0 @@ -// Signature format: 2.0 -package android.net { - - public class CaptivePortal implements android.os.Parcelable { - method public int describeContents(); - method public void ignoreNetwork(); - method public void reportCaptivePortalDismissed(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator CREATOR; - } - - public class ConnectivityDiagnosticsManager { - method public void registerConnectivityDiagnosticsCallback(@NonNull android.net.NetworkRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback); - method public void unregisterConnectivityDiagnosticsCallback(@NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback); - } - - public abstract static class ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback { - ctor public ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback(); - method public void onConnectivityReportAvailable(@NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityReport); - method public void onDataStallSuspected(@NonNull android.net.ConnectivityDiagnosticsManager.DataStallReport); - method public void onNetworkConnectivityReported(@NonNull android.net.Network, boolean); - } - - public static final class ConnectivityDiagnosticsManager.ConnectivityReport implements android.os.Parcelable { - ctor public ConnectivityDiagnosticsManager.ConnectivityReport(@NonNull android.net.Network, long, @NonNull android.net.LinkProperties, @NonNull android.net.NetworkCapabilities, @NonNull android.os.PersistableBundle); - method public int describeContents(); - method @NonNull public android.os.PersistableBundle getAdditionalInfo(); - method @NonNull public android.net.LinkProperties getLinkProperties(); - method @NonNull public android.net.Network getNetwork(); - method @NonNull public android.net.NetworkCapabilities getNetworkCapabilities(); - method public long getReportTimestamp(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator CREATOR; - field public static final String KEY_NETWORK_PROBES_ATTEMPTED_BITMASK = "networkProbesAttempted"; - field public static final String KEY_NETWORK_PROBES_SUCCEEDED_BITMASK = "networkProbesSucceeded"; - field public static final String KEY_NETWORK_VALIDATION_RESULT = "networkValidationResult"; - field public static final int NETWORK_PROBE_DNS = 4; // 0x4 - field public static final int NETWORK_PROBE_FALLBACK = 32; // 0x20 - field public static final int NETWORK_PROBE_HTTP = 8; // 0x8 - field public static final int NETWORK_PROBE_HTTPS = 16; // 0x10 - field public static final int NETWORK_PROBE_PRIVATE_DNS = 64; // 0x40 - field public static final int NETWORK_VALIDATION_RESULT_INVALID = 0; // 0x0 - field public static final int NETWORK_VALIDATION_RESULT_PARTIALLY_VALID = 2; // 0x2 - field public static final int NETWORK_VALIDATION_RESULT_SKIPPED = 3; // 0x3 - field public static final int NETWORK_VALIDATION_RESULT_VALID = 1; // 0x1 - } - - public static final class ConnectivityDiagnosticsManager.DataStallReport implements android.os.Parcelable { - ctor public ConnectivityDiagnosticsManager.DataStallReport(@NonNull android.net.Network, long, int, @NonNull android.net.LinkProperties, @NonNull android.net.NetworkCapabilities, @NonNull android.os.PersistableBundle); - method public int describeContents(); - method public int getDetectionMethod(); - method @NonNull public android.net.LinkProperties getLinkProperties(); - method @NonNull public android.net.Network getNetwork(); - method @NonNull public android.net.NetworkCapabilities getNetworkCapabilities(); - method public long getReportTimestamp(); - method @NonNull public android.os.PersistableBundle getStallDetails(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator CREATOR; - field public static final int DETECTION_METHOD_DNS_EVENTS = 1; // 0x1 - field public static final int DETECTION_METHOD_TCP_METRICS = 2; // 0x2 - field public static final String KEY_DNS_CONSECUTIVE_TIMEOUTS = "dnsConsecutiveTimeouts"; - field public static final String KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS = "tcpMetricsCollectionPeriodMillis"; - field public static final String KEY_TCP_PACKET_FAIL_RATE = "tcpPacketFailRate"; - } - - public class ConnectivityManager { - method public void addDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener); - method public boolean bindProcessToNetwork(@Nullable android.net.Network); - method @NonNull public android.net.SocketKeepalive createSocketKeepalive(@NonNull android.net.Network, @NonNull android.net.IpSecManager.UdpEncapsulationSocket, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback); - method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.Network getActiveNetwork(); - method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getActiveNetworkInfo(); - method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo[] getAllNetworkInfo(); - method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.Network[] getAllNetworks(); - method @Deprecated public boolean getBackgroundDataSetting(); - method @Nullable public android.net.Network getBoundNetworkForProcess(); - method public int getConnectionOwnerUid(int, @NonNull java.net.InetSocketAddress, @NonNull java.net.InetSocketAddress); - method @Nullable public android.net.ProxyInfo getDefaultProxy(); - method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.LinkProperties getLinkProperties(@Nullable android.net.Network); - method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public int getMultipathPreference(@Nullable android.net.Network); - method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkCapabilities getNetworkCapabilities(@Nullable android.net.Network); - method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getNetworkInfo(int); - method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getNetworkInfo(@Nullable android.net.Network); - method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public int getNetworkPreference(); - method @Nullable public byte[] getNetworkWatchlistConfigHash(); - method @Deprecated @Nullable public static android.net.Network getProcessDefaultNetwork(); - method public int getRestrictBackgroundStatus(); - method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public boolean isActiveNetworkMetered(); - method public boolean isDefaultNetworkActive(); - method @Deprecated public static boolean isNetworkTypeValid(int); - method public void registerBestMatchingNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); - method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback); - method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); - method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback); - method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); - method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.app.PendingIntent); - method public void releaseNetworkRequest(@NonNull android.app.PendingIntent); - method public void removeDefaultNetworkActiveListener(@NonNull android.net.ConnectivityManager.OnNetworkActiveListener); - method @Deprecated public void reportBadNetwork(@Nullable android.net.Network); - method public void reportNetworkConnectivity(@Nullable android.net.Network, boolean); - method public boolean requestBandwidthUpdate(@NonNull android.net.Network); - method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback); - method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); - method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, int); - method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler, int); - method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.app.PendingIntent); - method @Deprecated public void setNetworkPreference(int); - method @Deprecated public static boolean setProcessDefaultNetwork(@Nullable android.net.Network); - method public void unregisterNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback); - method public void unregisterNetworkCallback(@NonNull android.app.PendingIntent); - field @Deprecated public static final String ACTION_BACKGROUND_DATA_SETTING_CHANGED = "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED"; - field public static final String ACTION_CAPTIVE_PORTAL_SIGN_IN = "android.net.conn.CAPTIVE_PORTAL"; - field public static final String ACTION_RESTRICT_BACKGROUND_CHANGED = "android.net.conn.RESTRICT_BACKGROUND_CHANGED"; - field @Deprecated public static final String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE"; - field @Deprecated public static final int DEFAULT_NETWORK_PREFERENCE = 1; // 0x1 - field public static final String EXTRA_CAPTIVE_PORTAL = "android.net.extra.CAPTIVE_PORTAL"; - field public static final String EXTRA_CAPTIVE_PORTAL_URL = "android.net.extra.CAPTIVE_PORTAL_URL"; - field @Deprecated public static final String EXTRA_EXTRA_INFO = "extraInfo"; - field @Deprecated public static final String EXTRA_IS_FAILOVER = "isFailover"; - field public static final String EXTRA_NETWORK = "android.net.extra.NETWORK"; - field @Deprecated public static final String EXTRA_NETWORK_INFO = "networkInfo"; - field public static final String EXTRA_NETWORK_REQUEST = "android.net.extra.NETWORK_REQUEST"; - field @Deprecated public static final String EXTRA_NETWORK_TYPE = "networkType"; - field public static final String EXTRA_NO_CONNECTIVITY = "noConnectivity"; - field @Deprecated public static final String EXTRA_OTHER_NETWORK_INFO = "otherNetwork"; - field public static final String EXTRA_REASON = "reason"; - field public static final int MULTIPATH_PREFERENCE_HANDOVER = 1; // 0x1 - field public static final int MULTIPATH_PREFERENCE_PERFORMANCE = 4; // 0x4 - field public static final int MULTIPATH_PREFERENCE_RELIABILITY = 2; // 0x2 - field public static final int RESTRICT_BACKGROUND_STATUS_DISABLED = 1; // 0x1 - field public static final int RESTRICT_BACKGROUND_STATUS_ENABLED = 3; // 0x3 - field public static final int RESTRICT_BACKGROUND_STATUS_WHITELISTED = 2; // 0x2 - field @Deprecated public static final int TYPE_BLUETOOTH = 7; // 0x7 - field @Deprecated public static final int TYPE_DUMMY = 8; // 0x8 - field @Deprecated public static final int TYPE_ETHERNET = 9; // 0x9 - field @Deprecated public static final int TYPE_MOBILE = 0; // 0x0 - field @Deprecated public static final int TYPE_MOBILE_DUN = 4; // 0x4 - field @Deprecated public static final int TYPE_MOBILE_HIPRI = 5; // 0x5 - field @Deprecated public static final int TYPE_MOBILE_MMS = 2; // 0x2 - field @Deprecated public static final int TYPE_MOBILE_SUPL = 3; // 0x3 - field @Deprecated public static final int TYPE_VPN = 17; // 0x11 - field @Deprecated public static final int TYPE_WIFI = 1; // 0x1 - field @Deprecated public static final int TYPE_WIMAX = 6; // 0x6 - } - - public static class ConnectivityManager.NetworkCallback { - ctor public ConnectivityManager.NetworkCallback(); - ctor public ConnectivityManager.NetworkCallback(int); - method public void onAvailable(@NonNull android.net.Network); - method public void onBlockedStatusChanged(@NonNull android.net.Network, boolean); - method public void onCapabilitiesChanged(@NonNull android.net.Network, @NonNull android.net.NetworkCapabilities); - method public void onLinkPropertiesChanged(@NonNull android.net.Network, @NonNull android.net.LinkProperties); - method public void onLosing(@NonNull android.net.Network, int); - method public void onLost(@NonNull android.net.Network); - method public void onUnavailable(); - field public static final int FLAG_INCLUDE_LOCATION_INFO = 1; // 0x1 - } - - public static interface ConnectivityManager.OnNetworkActiveListener { - method public void onNetworkActive(); - } - - public class DhcpInfo implements android.os.Parcelable { - ctor public DhcpInfo(); - method public int describeContents(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator CREATOR; - field public int dns1; - field public int dns2; - field public int gateway; - field public int ipAddress; - field public int leaseDuration; - field public int netmask; - field public int serverAddress; - } - - public final class DnsResolver { - method @NonNull public static android.net.DnsResolver getInstance(); - method public void query(@Nullable android.net.Network, @NonNull String, int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.Callback>); - method public void query(@Nullable android.net.Network, @NonNull String, int, int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.Callback>); - method public void rawQuery(@Nullable android.net.Network, @NonNull byte[], int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.Callback); - method public void rawQuery(@Nullable android.net.Network, @NonNull String, int, int, int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.Callback); - field public static final int CLASS_IN = 1; // 0x1 - field public static final int ERROR_PARSE = 0; // 0x0 - field public static final int ERROR_SYSTEM = 1; // 0x1 - field public static final int FLAG_EMPTY = 0; // 0x0 - field public static final int FLAG_NO_CACHE_LOOKUP = 4; // 0x4 - field public static final int FLAG_NO_CACHE_STORE = 2; // 0x2 - field public static final int FLAG_NO_RETRY = 1; // 0x1 - field public static final int TYPE_A = 1; // 0x1 - field public static final int TYPE_AAAA = 28; // 0x1c - } - - public static interface DnsResolver.Callback { - method public void onAnswer(@NonNull T, int); - method public void onError(@NonNull android.net.DnsResolver.DnsException); - } - - public static class DnsResolver.DnsException extends java.lang.Exception { - field public final int code; - } - - public class InetAddresses { - method public static boolean isNumericAddress(@NonNull String); - method @NonNull public static java.net.InetAddress parseNumericAddress(@NonNull String); - } - - public final class IpPrefix implements android.os.Parcelable { - method public boolean contains(@NonNull java.net.InetAddress); - method public int describeContents(); - method @NonNull public java.net.InetAddress getAddress(); - method @IntRange(from=0, to=128) public int getPrefixLength(); - method @NonNull public byte[] getRawAddress(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator CREATOR; - } - - public class LinkAddress implements android.os.Parcelable { - method public int describeContents(); - method public java.net.InetAddress getAddress(); - method public int getFlags(); - method @IntRange(from=0, to=128) public int getPrefixLength(); - method public int getScope(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator CREATOR; - } - - public final class LinkProperties implements android.os.Parcelable { - ctor public LinkProperties(); - method public boolean addRoute(@NonNull android.net.RouteInfo); - method public void clear(); - method public int describeContents(); - method @Nullable public java.net.Inet4Address getDhcpServerAddress(); - method @NonNull public java.util.List getDnsServers(); - method @Nullable public String getDomains(); - method @Nullable public android.net.ProxyInfo getHttpProxy(); - method @Nullable public String getInterfaceName(); - method @NonNull public java.util.List getLinkAddresses(); - method public int getMtu(); - method @Nullable public android.net.IpPrefix getNat64Prefix(); - method @Nullable public String getPrivateDnsServerName(); - method @NonNull public java.util.List getRoutes(); - method public boolean isPrivateDnsActive(); - method public boolean isWakeOnLanSupported(); - method public void setDhcpServerAddress(@Nullable java.net.Inet4Address); - method public void setDnsServers(@NonNull java.util.Collection); - method public void setDomains(@Nullable String); - method public void setHttpProxy(@Nullable android.net.ProxyInfo); - method public void setInterfaceName(@Nullable String); - method public void setLinkAddresses(@NonNull java.util.Collection); - method public void setMtu(int); - method public void setNat64Prefix(@Nullable android.net.IpPrefix); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator CREATOR; - } - - public final class MacAddress implements android.os.Parcelable { - method public int describeContents(); - method @NonNull public static android.net.MacAddress fromBytes(@NonNull byte[]); - method @NonNull public static android.net.MacAddress fromString(@NonNull String); - method public int getAddressType(); - method @Nullable public java.net.Inet6Address getLinkLocalIpv6FromEui48Mac(); - method public boolean isLocallyAssigned(); - method public boolean matches(@NonNull android.net.MacAddress, @NonNull android.net.MacAddress); - method @NonNull public byte[] toByteArray(); - method @NonNull public String toOuiString(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.net.MacAddress BROADCAST_ADDRESS; - field @NonNull public static final android.os.Parcelable.Creator CREATOR; - field public static final int TYPE_BROADCAST = 3; // 0x3 - field public static final int TYPE_MULTICAST = 2; // 0x2 - field public static final int TYPE_UNICAST = 1; // 0x1 - } - - public class Network implements android.os.Parcelable { - method public void bindSocket(java.net.DatagramSocket) throws java.io.IOException; - method public void bindSocket(java.net.Socket) throws java.io.IOException; - method public void bindSocket(java.io.FileDescriptor) throws java.io.IOException; - method public int describeContents(); - method public static android.net.Network fromNetworkHandle(long); - method public java.net.InetAddress[] getAllByName(String) throws java.net.UnknownHostException; - method public java.net.InetAddress getByName(String) throws java.net.UnknownHostException; - method public long getNetworkHandle(); - method public javax.net.SocketFactory getSocketFactory(); - method public java.net.URLConnection openConnection(java.net.URL) throws java.io.IOException; - method public java.net.URLConnection openConnection(java.net.URL, java.net.Proxy) throws java.io.IOException; - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator CREATOR; - } - - public final class NetworkCapabilities implements android.os.Parcelable { - ctor public NetworkCapabilities(); - ctor public NetworkCapabilities(android.net.NetworkCapabilities); - method public int describeContents(); - method @NonNull public int[] getCapabilities(); - method public int getLinkDownstreamBandwidthKbps(); - method public int getLinkUpstreamBandwidthKbps(); - method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier(); - method public int getOwnerUid(); - method public int getSignalStrength(); - method @Nullable public android.net.TransportInfo getTransportInfo(); - method public boolean hasCapability(int); - method public boolean hasTransport(int); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator CREATOR; - field public static final int NET_CAPABILITY_CAPTIVE_PORTAL = 17; // 0x11 - field public static final int NET_CAPABILITY_CBS = 5; // 0x5 - field public static final int NET_CAPABILITY_DUN = 2; // 0x2 - field public static final int NET_CAPABILITY_EIMS = 10; // 0xa - field public static final int NET_CAPABILITY_ENTERPRISE = 29; // 0x1d - field public static final int NET_CAPABILITY_FOREGROUND = 19; // 0x13 - field public static final int NET_CAPABILITY_FOTA = 3; // 0x3 - field public static final int NET_CAPABILITY_HEAD_UNIT = 32; // 0x20 - field public static final int NET_CAPABILITY_IA = 7; // 0x7 - field public static final int NET_CAPABILITY_IMS = 4; // 0x4 - field public static final int NET_CAPABILITY_INTERNET = 12; // 0xc - field public static final int NET_CAPABILITY_MCX = 23; // 0x17 - field public static final int NET_CAPABILITY_MMS = 0; // 0x0 - field public static final int NET_CAPABILITY_NOT_CONGESTED = 20; // 0x14 - field public static final int NET_CAPABILITY_NOT_METERED = 11; // 0xb - field public static final int NET_CAPABILITY_NOT_RESTRICTED = 13; // 0xd - field public static final int NET_CAPABILITY_NOT_ROAMING = 18; // 0x12 - field public static final int NET_CAPABILITY_NOT_SUSPENDED = 21; // 0x15 - field public static final int NET_CAPABILITY_NOT_VPN = 15; // 0xf - field public static final int NET_CAPABILITY_RCS = 8; // 0x8 - field public static final int NET_CAPABILITY_SUPL = 1; // 0x1 - field public static final int NET_CAPABILITY_TEMPORARILY_NOT_METERED = 25; // 0x19 - field public static final int NET_CAPABILITY_TRUSTED = 14; // 0xe - field public static final int NET_CAPABILITY_VALIDATED = 16; // 0x10 - field public static final int NET_CAPABILITY_WIFI_P2P = 6; // 0x6 - field public static final int NET_CAPABILITY_XCAP = 9; // 0x9 - field public static final int SIGNAL_STRENGTH_UNSPECIFIED = -2147483648; // 0x80000000 - field public static final int TRANSPORT_BLUETOOTH = 2; // 0x2 - field public static final int TRANSPORT_CELLULAR = 0; // 0x0 - field public static final int TRANSPORT_ETHERNET = 3; // 0x3 - field public static final int TRANSPORT_LOWPAN = 6; // 0x6 - field public static final int TRANSPORT_USB = 8; // 0x8 - field public static final int TRANSPORT_VPN = 4; // 0x4 - field public static final int TRANSPORT_WIFI = 1; // 0x1 - field public static final int TRANSPORT_WIFI_AWARE = 5; // 0x5 - } - - @Deprecated public class NetworkInfo implements android.os.Parcelable { - ctor @Deprecated public NetworkInfo(int, int, @Nullable String, @Nullable String); - method @Deprecated public int describeContents(); - method @Deprecated @NonNull public android.net.NetworkInfo.DetailedState getDetailedState(); - method @Deprecated public String getExtraInfo(); - method @Deprecated public String getReason(); - method @Deprecated public android.net.NetworkInfo.State getState(); - method @Deprecated public int getSubtype(); - method @Deprecated public String getSubtypeName(); - method @Deprecated public int getType(); - method @Deprecated public String getTypeName(); - method @Deprecated public boolean isAvailable(); - method @Deprecated public boolean isConnected(); - method @Deprecated public boolean isConnectedOrConnecting(); - method @Deprecated public boolean isFailover(); - method @Deprecated public boolean isRoaming(); - method @Deprecated public void setDetailedState(@NonNull android.net.NetworkInfo.DetailedState, @Nullable String, @Nullable String); - method @Deprecated public void writeToParcel(android.os.Parcel, int); - field @Deprecated @NonNull public static final android.os.Parcelable.Creator CREATOR; - } - - @Deprecated public enum NetworkInfo.DetailedState { - enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState AUTHENTICATING; - enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState BLOCKED; - enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState CAPTIVE_PORTAL_CHECK; - enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState CONNECTED; - enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState CONNECTING; - enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState DISCONNECTED; - enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState DISCONNECTING; - enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState FAILED; - enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState IDLE; - enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState OBTAINING_IPADDR; - enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState SCANNING; - enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState SUSPENDED; - enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState VERIFYING_POOR_LINK; - } - - @Deprecated public enum NetworkInfo.State { - enum_constant @Deprecated public static final android.net.NetworkInfo.State CONNECTED; - enum_constant @Deprecated public static final android.net.NetworkInfo.State CONNECTING; - enum_constant @Deprecated public static final android.net.NetworkInfo.State DISCONNECTED; - enum_constant @Deprecated public static final android.net.NetworkInfo.State DISCONNECTING; - enum_constant @Deprecated public static final android.net.NetworkInfo.State SUSPENDED; - enum_constant @Deprecated public static final android.net.NetworkInfo.State UNKNOWN; - } - - public class NetworkRequest implements android.os.Parcelable { - method public boolean canBeSatisfiedBy(@Nullable android.net.NetworkCapabilities); - method public int describeContents(); - method @NonNull public int[] getCapabilities(); - method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier(); - method @NonNull public int[] getTransportTypes(); - method public boolean hasCapability(int); - method public boolean hasTransport(int); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator CREATOR; - } - - public static class NetworkRequest.Builder { - ctor public NetworkRequest.Builder(); - ctor public NetworkRequest.Builder(@NonNull android.net.NetworkRequest); - method public android.net.NetworkRequest.Builder addCapability(int); - method public android.net.NetworkRequest.Builder addTransportType(int); - method public android.net.NetworkRequest build(); - method @NonNull public android.net.NetworkRequest.Builder clearCapabilities(); - method public android.net.NetworkRequest.Builder removeCapability(int); - method public android.net.NetworkRequest.Builder removeTransportType(int); - method @NonNull public android.net.NetworkRequest.Builder setIncludeOtherUidNetworks(boolean); - method @Deprecated public android.net.NetworkRequest.Builder setNetworkSpecifier(String); - method public android.net.NetworkRequest.Builder setNetworkSpecifier(android.net.NetworkSpecifier); - } - - public class ParseException extends java.lang.RuntimeException { - ctor public ParseException(@NonNull String); - ctor public ParseException(@NonNull String, @NonNull Throwable); - field public String response; - } - - public class ProxyInfo implements android.os.Parcelable { - ctor public ProxyInfo(@Nullable android.net.ProxyInfo); - method public static android.net.ProxyInfo buildDirectProxy(String, int); - method public static android.net.ProxyInfo buildDirectProxy(String, int, java.util.List); - method public static android.net.ProxyInfo buildPacProxy(android.net.Uri); - method @NonNull public static android.net.ProxyInfo buildPacProxy(@NonNull android.net.Uri, int); - method public int describeContents(); - method public String[] getExclusionList(); - method public String getHost(); - method public android.net.Uri getPacFileUrl(); - method public int getPort(); - method public boolean isValid(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator CREATOR; - } - - public final class RouteInfo implements android.os.Parcelable { - method public int describeContents(); - method @NonNull public android.net.IpPrefix getDestination(); - method @Nullable public java.net.InetAddress getGateway(); - method @Nullable public String getInterface(); - method public boolean hasGateway(); - method public boolean isDefaultRoute(); - method public boolean matches(java.net.InetAddress); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator CREATOR; - } - - public abstract class SocketKeepalive implements java.lang.AutoCloseable { - method public final void close(); - method public final void start(@IntRange(from=0xa, to=0xe10) int); - method public final void stop(); - field public static final int ERROR_HARDWARE_ERROR = -31; // 0xffffffe1 - field public static final int ERROR_INSUFFICIENT_RESOURCES = -32; // 0xffffffe0 - field public static final int ERROR_INVALID_INTERVAL = -24; // 0xffffffe8 - field public static final int ERROR_INVALID_IP_ADDRESS = -21; // 0xffffffeb - field public static final int ERROR_INVALID_LENGTH = -23; // 0xffffffe9 - field public static final int ERROR_INVALID_NETWORK = -20; // 0xffffffec - field public static final int ERROR_INVALID_PORT = -22; // 0xffffffea - field public static final int ERROR_INVALID_SOCKET = -25; // 0xffffffe7 - field public static final int ERROR_SOCKET_NOT_IDLE = -26; // 0xffffffe6 - field public static final int ERROR_UNSUPPORTED = -30; // 0xffffffe2 - } - - public static class SocketKeepalive.Callback { - ctor public SocketKeepalive.Callback(); - method public void onDataReceived(); - method public void onError(int); - method public void onStarted(); - method public void onStopped(); - } - - public interface TransportInfo { - } - -} - diff --git a/packages/Connectivity/framework/api/lint-baseline.txt b/packages/Connectivity/framework/api/lint-baseline.txt deleted file mode 100644 index 2f4004ab723d0..0000000000000 --- a/packages/Connectivity/framework/api/lint-baseline.txt +++ /dev/null @@ -1,4 +0,0 @@ -// Baseline format: 1.0 -VisiblySynchronized: android.net.NetworkInfo#toString(): - Internal locks must not be exposed (synchronizing on this or class is still - externally observable): method android.net.NetworkInfo.toString() diff --git a/packages/Connectivity/framework/api/module-lib-current.txt b/packages/Connectivity/framework/api/module-lib-current.txt deleted file mode 100644 index 6c454bcd4cd78..0000000000000 --- a/packages/Connectivity/framework/api/module-lib-current.txt +++ /dev/null @@ -1,179 +0,0 @@ -// Signature format: 2.0 -package android.net { - - public final class ConnectivityFrameworkInitializer { - method public static void registerServiceWrappers(); - } - - public class ConnectivityManager { - method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void factoryReset(); - method @NonNull @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public java.util.List getAllNetworkStateSnapshots(); - method @Nullable public android.net.ProxyInfo getGlobalProxy(); - method @NonNull public static android.util.Range getIpSecNetIdRange(); - method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerDefaultNetworkCallbackForUid(int, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); - method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); - method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); - method @Deprecated public boolean requestRouteToHostAddress(int, java.net.InetAddress); - method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void setAcceptPartialConnectivity(@NonNull android.net.Network, boolean, boolean); - method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void setAcceptUnvalidated(@NonNull android.net.Network, boolean, boolean); - method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void setAvoidUnvalidated(@NonNull android.net.Network); - method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setGlobalProxy(@Nullable android.net.ProxyInfo); - method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void setLegacyLockdownVpnEnabled(boolean); - method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setProfileNetworkPreference(@NonNull android.os.UserHandle, int, @Nullable java.util.concurrent.Executor, @Nullable Runnable); - method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void setRequireVpnForUids(boolean, @NonNull java.util.Collection>); - method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle); - method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void startCaptivePortalApp(@NonNull android.net.Network); - method public void systemReady(); - field public static final String ACTION_CLEAR_DNS_CACHE = "android.net.action.CLEAR_DNS_CACHE"; - field public static final String ACTION_PROMPT_LOST_VALIDATION = "android.net.action.PROMPT_LOST_VALIDATION"; - field public static final String ACTION_PROMPT_PARTIAL_CONNECTIVITY = "android.net.action.PROMPT_PARTIAL_CONNECTIVITY"; - field public static final String ACTION_PROMPT_UNVALIDATED = "android.net.action.PROMPT_UNVALIDATED"; - field public static final int BLOCKED_METERED_REASON_ADMIN_DISABLED = 262144; // 0x40000 - field public static final int BLOCKED_METERED_REASON_DATA_SAVER = 65536; // 0x10000 - field public static final int BLOCKED_METERED_REASON_MASK = -65536; // 0xffff0000 - field public static final int BLOCKED_METERED_REASON_USER_RESTRICTED = 131072; // 0x20000 - field public static final int BLOCKED_REASON_APP_STANDBY = 4; // 0x4 - field public static final int BLOCKED_REASON_BATTERY_SAVER = 1; // 0x1 - field public static final int BLOCKED_REASON_DOZE = 2; // 0x2 - field public static final int BLOCKED_REASON_LOCKDOWN_VPN = 16; // 0x10 - field public static final int BLOCKED_REASON_NONE = 0; // 0x0 - field public static final int BLOCKED_REASON_RESTRICTED_MODE = 8; // 0x8 - field public static final int PROFILE_NETWORK_PREFERENCE_DEFAULT = 0; // 0x0 - field public static final int PROFILE_NETWORK_PREFERENCE_ENTERPRISE = 1; // 0x1 - } - - public static class ConnectivityManager.NetworkCallback { - method public void onBlockedStatusChanged(@NonNull android.net.Network, int); - } - - public class ConnectivitySettingsManager { - method public static void clearGlobalProxy(@NonNull android.content.Context); - method @NonNull public static java.util.Set getAppsAllowedOnRestrictedNetworks(@NonNull android.content.Context); - method @Nullable public static String getCaptivePortalHttpUrl(@NonNull android.content.Context); - method public static int getCaptivePortalMode(@NonNull android.content.Context, int); - method @NonNull public static java.time.Duration getConnectivityKeepPendingIntentDuration(@NonNull android.content.Context, @NonNull java.time.Duration); - method @NonNull public static android.util.Range getDnsResolverSampleRanges(@NonNull android.content.Context); - method @NonNull public static java.time.Duration getDnsResolverSampleValidityDuration(@NonNull android.content.Context, @NonNull java.time.Duration); - method public static int getDnsResolverSuccessThresholdPercent(@NonNull android.content.Context, int); - method @Nullable public static android.net.ProxyInfo getGlobalProxy(@NonNull android.content.Context); - method @NonNull public static java.time.Duration getMobileDataActivityTimeout(@NonNull android.content.Context, @NonNull java.time.Duration); - method public static boolean getMobileDataAlwaysOn(@NonNull android.content.Context, boolean); - method @NonNull public static java.util.Set getMobileDataPreferredUids(@NonNull android.content.Context); - method public static int getNetworkAvoidBadWifi(@NonNull android.content.Context); - method @Nullable public static String getNetworkMeteredMultipathPreference(@NonNull android.content.Context); - method public static int getNetworkSwitchNotificationMaximumDailyCount(@NonNull android.content.Context, int); - method @NonNull public static java.time.Duration getNetworkSwitchNotificationRateDuration(@NonNull android.content.Context, @NonNull java.time.Duration); - method @NonNull public static String getPrivateDnsDefaultMode(@NonNull android.content.Context); - method @Nullable public static String getPrivateDnsHostname(@NonNull android.content.Context); - method public static int getPrivateDnsMode(@NonNull android.content.Context); - method public static boolean getWifiAlwaysRequested(@NonNull android.content.Context, boolean); - method @NonNull public static java.time.Duration getWifiDataActivityTimeout(@NonNull android.content.Context, @NonNull java.time.Duration); - method public static void setAppsAllowedOnRestrictedNetworks(@NonNull android.content.Context, @NonNull java.util.Set); - method public static void setCaptivePortalHttpUrl(@NonNull android.content.Context, @Nullable String); - method public static void setCaptivePortalMode(@NonNull android.content.Context, int); - method public static void setConnectivityKeepPendingIntentDuration(@NonNull android.content.Context, @NonNull java.time.Duration); - method public static void setDnsResolverSampleRanges(@NonNull android.content.Context, @NonNull android.util.Range); - method public static void setDnsResolverSampleValidityDuration(@NonNull android.content.Context, @NonNull java.time.Duration); - method public static void setDnsResolverSuccessThresholdPercent(@NonNull android.content.Context, @IntRange(from=0, to=100) int); - method public static void setGlobalProxy(@NonNull android.content.Context, @NonNull android.net.ProxyInfo); - method public static void setMobileDataActivityTimeout(@NonNull android.content.Context, @NonNull java.time.Duration); - method public static void setMobileDataAlwaysOn(@NonNull android.content.Context, boolean); - method public static void setMobileDataPreferredUids(@NonNull android.content.Context, @NonNull java.util.Set); - method public static void setNetworkAvoidBadWifi(@NonNull android.content.Context, int); - method public static void setNetworkMeteredMultipathPreference(@NonNull android.content.Context, @NonNull String); - method public static void setNetworkSwitchNotificationMaximumDailyCount(@NonNull android.content.Context, @IntRange(from=0) int); - method public static void setNetworkSwitchNotificationRateDuration(@NonNull android.content.Context, @NonNull java.time.Duration); - method public static void setPrivateDnsDefaultMode(@NonNull android.content.Context, @NonNull int); - method public static void setPrivateDnsHostname(@NonNull android.content.Context, @Nullable String); - method public static void setPrivateDnsMode(@NonNull android.content.Context, int); - method public static void setWifiAlwaysRequested(@NonNull android.content.Context, boolean); - method public static void setWifiDataActivityTimeout(@NonNull android.content.Context, @NonNull java.time.Duration); - field public static final int CAPTIVE_PORTAL_MODE_AVOID = 2; // 0x2 - field public static final int CAPTIVE_PORTAL_MODE_IGNORE = 0; // 0x0 - field public static final int CAPTIVE_PORTAL_MODE_PROMPT = 1; // 0x1 - field public static final int NETWORK_AVOID_BAD_WIFI_AVOID = 2; // 0x2 - field public static final int NETWORK_AVOID_BAD_WIFI_IGNORE = 0; // 0x0 - field public static final int NETWORK_AVOID_BAD_WIFI_PROMPT = 1; // 0x1 - field public static final int PRIVATE_DNS_MODE_OFF = 1; // 0x1 - field public static final int PRIVATE_DNS_MODE_OPPORTUNISTIC = 2; // 0x2 - field public static final int PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = 3; // 0x3 - } - - public final class NetworkAgentConfig implements android.os.Parcelable { - method @Nullable public String getSubscriberId(); - method public boolean isBypassableVpn(); - } - - public static final class NetworkAgentConfig.Builder { - method @NonNull public android.net.NetworkAgentConfig.Builder setBypassableVpn(boolean); - method @NonNull public android.net.NetworkAgentConfig.Builder setSubscriberId(@Nullable String); - } - - public final class NetworkCapabilities implements android.os.Parcelable { - method @Nullable public java.util.Set> getUids(); - method public boolean hasForbiddenCapability(int); - field public static final long REDACT_ALL = -1L; // 0xffffffffffffffffL - field public static final long REDACT_FOR_ACCESS_FINE_LOCATION = 1L; // 0x1L - field public static final long REDACT_FOR_LOCAL_MAC_ADDRESS = 2L; // 0x2L - field public static final long REDACT_FOR_NETWORK_SETTINGS = 4L; // 0x4L - field public static final long REDACT_NONE = 0L; // 0x0L - field public static final int TRANSPORT_TEST = 7; // 0x7 - } - - public static final class NetworkCapabilities.Builder { - method @NonNull public android.net.NetworkCapabilities.Builder setUids(@Nullable java.util.Set>); - } - - public class NetworkRequest implements android.os.Parcelable { - method @NonNull public int[] getForbiddenCapabilities(); - method public boolean hasForbiddenCapability(int); - } - - public static class NetworkRequest.Builder { - method @NonNull public android.net.NetworkRequest.Builder addForbiddenCapability(int); - method @NonNull public android.net.NetworkRequest.Builder removeForbiddenCapability(int); - method @NonNull public android.net.NetworkRequest.Builder setUids(@Nullable java.util.Set>); - } - - public final class TestNetworkInterface implements android.os.Parcelable { - ctor public TestNetworkInterface(@NonNull android.os.ParcelFileDescriptor, @NonNull String); - method public int describeContents(); - method @NonNull public android.os.ParcelFileDescriptor getFileDescriptor(); - method @NonNull public String getInterfaceName(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator CREATOR; - } - - public class TestNetworkManager { - method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_TEST_NETWORKS) public android.net.TestNetworkInterface createTapInterface(); - method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_TEST_NETWORKS) public android.net.TestNetworkInterface createTunInterface(@NonNull java.util.Collection); - method @RequiresPermission(android.Manifest.permission.MANAGE_TEST_NETWORKS) public void setupTestNetwork(@NonNull String, @NonNull android.os.IBinder); - method @RequiresPermission(android.Manifest.permission.MANAGE_TEST_NETWORKS) public void teardownTestNetwork(@NonNull android.net.Network); - field public static final String TEST_TAP_PREFIX = "testtap"; - } - - public final class TestNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable { - ctor public TestNetworkSpecifier(@NonNull String); - method public int describeContents(); - method @Nullable public String getInterfaceName(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator CREATOR; - } - - public interface TransportInfo { - method public default long getApplicableRedactions(); - method @NonNull public default android.net.TransportInfo makeCopy(long); - } - - public final class VpnTransportInfo implements android.os.Parcelable android.net.TransportInfo { - ctor public VpnTransportInfo(int, @Nullable String); - method public int describeContents(); - method @Nullable public String getSessionId(); - method public int getType(); - method @NonNull public android.net.VpnTransportInfo makeCopy(long); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator CREATOR; - } - -} - diff --git a/packages/Connectivity/framework/api/module-lib-removed.txt b/packages/Connectivity/framework/api/module-lib-removed.txt deleted file mode 100644 index d802177e249b3..0000000000000 --- a/packages/Connectivity/framework/api/module-lib-removed.txt +++ /dev/null @@ -1 +0,0 @@ -// Signature format: 2.0 diff --git a/packages/Connectivity/framework/api/removed.txt b/packages/Connectivity/framework/api/removed.txt deleted file mode 100644 index 303a1e6173baf..0000000000000 --- a/packages/Connectivity/framework/api/removed.txt +++ /dev/null @@ -1,11 +0,0 @@ -// Signature format: 2.0 -package android.net { - - public class ConnectivityManager { - method @Deprecated public boolean requestRouteToHost(int, int); - method @Deprecated public int startUsingNetworkFeature(int, String); - method @Deprecated public int stopUsingNetworkFeature(int, String); - } - -} - diff --git a/packages/Connectivity/framework/api/system-current.txt b/packages/Connectivity/framework/api/system-current.txt deleted file mode 100644 index d1d51da151bf8..0000000000000 --- a/packages/Connectivity/framework/api/system-current.txt +++ /dev/null @@ -1,505 +0,0 @@ -// Signature format: 2.0 -package android.net { - - public class CaptivePortal implements android.os.Parcelable { - method @Deprecated public void logEvent(int, @NonNull String); - method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void reevaluateNetwork(); - method public void useNetwork(); - field public static final int APP_REQUEST_REEVALUATION_REQUIRED = 100; // 0x64 - field public static final int APP_RETURN_DISMISSED = 0; // 0x0 - field public static final int APP_RETURN_UNWANTED = 1; // 0x1 - field public static final int APP_RETURN_WANTED_AS_IS = 2; // 0x2 - } - - public final class CaptivePortalData implements android.os.Parcelable { - method public int describeContents(); - method public long getByteLimit(); - method public long getExpiryTimeMillis(); - method public long getRefreshTimeMillis(); - method @Nullable public android.net.Uri getUserPortalUrl(); - method public int getUserPortalUrlSource(); - method @Nullable public CharSequence getVenueFriendlyName(); - method @Nullable public android.net.Uri getVenueInfoUrl(); - method public int getVenueInfoUrlSource(); - method public boolean isCaptive(); - method public boolean isSessionExtendable(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field public static final int CAPTIVE_PORTAL_DATA_SOURCE_OTHER = 0; // 0x0 - field public static final int CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT = 1; // 0x1 - field @NonNull public static final android.os.Parcelable.Creator CREATOR; - } - - public static class CaptivePortalData.Builder { - ctor public CaptivePortalData.Builder(); - ctor public CaptivePortalData.Builder(@Nullable android.net.CaptivePortalData); - method @NonNull public android.net.CaptivePortalData build(); - method @NonNull public android.net.CaptivePortalData.Builder setBytesRemaining(long); - method @NonNull public android.net.CaptivePortalData.Builder setCaptive(boolean); - method @NonNull public android.net.CaptivePortalData.Builder setExpiryTime(long); - method @NonNull public android.net.CaptivePortalData.Builder setRefreshTime(long); - method @NonNull public android.net.CaptivePortalData.Builder setSessionExtendable(boolean); - method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri); - method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri, int); - method @NonNull public android.net.CaptivePortalData.Builder setVenueFriendlyName(@Nullable CharSequence); - method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri); - method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri, int); - } - - public class ConnectivityManager { - method @NonNull @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createNattKeepalive(@NonNull android.net.Network, @NonNull android.os.ParcelFileDescriptor, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback); - method @NonNull @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createSocketKeepalive(@NonNull android.net.Network, @NonNull java.net.Socket, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback); - method @Deprecated @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public String getCaptivePortalServerUrl(); - method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void getLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEntitlementResultListener); - method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public boolean isTetheringSupported(); - method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_FACTORY}) public int registerNetworkProvider(@NonNull android.net.NetworkProvider); - method public void registerQosCallback(@NonNull android.net.QosSocketInfo, @NonNull java.util.concurrent.Executor, @NonNull android.net.QosCallback); - method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEventCallback); - method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void requestNetwork(@NonNull android.net.NetworkRequest, int, int, @NonNull android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); - method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_AIRPLANE_MODE, android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void setAirplaneMode(boolean); - method @RequiresPermission(android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE) public void setOemNetworkPreference(@NonNull android.net.OemNetworkPreferences, @Nullable java.util.concurrent.Executor, @Nullable Runnable); - method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public boolean shouldAvoidBadWifi(); - method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(@NonNull android.net.Network, @NonNull android.os.Bundle); - method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback); - method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback, android.os.Handler); - method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void stopTethering(int); - method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_FACTORY}) public void unregisterNetworkProvider(@NonNull android.net.NetworkProvider); - method public void unregisterQosCallback(@NonNull android.net.QosCallback); - method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void unregisterTetheringEventCallback(@NonNull android.net.ConnectivityManager.OnTetheringEventCallback); - field public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC"; - field public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = "android.net.extra.CAPTIVE_PORTAL_USER_AGENT"; - field public static final int TETHERING_BLUETOOTH = 2; // 0x2 - field public static final int TETHERING_USB = 1; // 0x1 - field public static final int TETHERING_WIFI = 0; // 0x0 - field @Deprecated public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN = 13; // 0xd - field @Deprecated public static final int TETHER_ERROR_NO_ERROR = 0; // 0x0 - field @Deprecated public static final int TETHER_ERROR_PROVISION_FAILED = 11; // 0xb - field public static final int TYPE_NONE = -1; // 0xffffffff - field @Deprecated public static final int TYPE_PROXY = 16; // 0x10 - field @Deprecated public static final int TYPE_WIFI_P2P = 13; // 0xd - } - - @Deprecated public abstract static class ConnectivityManager.OnStartTetheringCallback { - ctor @Deprecated public ConnectivityManager.OnStartTetheringCallback(); - method @Deprecated public void onTetheringFailed(); - method @Deprecated public void onTetheringStarted(); - } - - @Deprecated public static interface ConnectivityManager.OnTetheringEntitlementResultListener { - method @Deprecated public void onTetheringEntitlementResult(int); - } - - @Deprecated public abstract static class ConnectivityManager.OnTetheringEventCallback { - ctor @Deprecated public ConnectivityManager.OnTetheringEventCallback(); - method @Deprecated public void onUpstreamChanged(@Nullable android.net.Network); - } - - public final class InvalidPacketException extends java.lang.Exception { - ctor public InvalidPacketException(int); - method public int getError(); - field public static final int ERROR_INVALID_IP_ADDRESS = -21; // 0xffffffeb - field public static final int ERROR_INVALID_LENGTH = -23; // 0xffffffe9 - field public static final int ERROR_INVALID_PORT = -22; // 0xffffffea - } - - public final class IpConfiguration implements android.os.Parcelable { - ctor public IpConfiguration(); - ctor public IpConfiguration(@NonNull android.net.IpConfiguration); - method public int describeContents(); - method @Nullable public android.net.ProxyInfo getHttpProxy(); - method @NonNull public android.net.IpConfiguration.IpAssignment getIpAssignment(); - method @NonNull public android.net.IpConfiguration.ProxySettings getProxySettings(); - method @Nullable public android.net.StaticIpConfiguration getStaticIpConfiguration(); - method public void setHttpProxy(@Nullable android.net.ProxyInfo); - method public void setIpAssignment(@NonNull android.net.IpConfiguration.IpAssignment); - method public void setProxySettings(@NonNull android.net.IpConfiguration.ProxySettings); - method public void setStaticIpConfiguration(@Nullable android.net.StaticIpConfiguration); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator CREATOR; - } - - public enum IpConfiguration.IpAssignment { - enum_constant public static final android.net.IpConfiguration.IpAssignment DHCP; - enum_constant public static final android.net.IpConfiguration.IpAssignment STATIC; - enum_constant public static final android.net.IpConfiguration.IpAssignment UNASSIGNED; - } - - public enum IpConfiguration.ProxySettings { - enum_constant public static final android.net.IpConfiguration.ProxySettings NONE; - enum_constant public static final android.net.IpConfiguration.ProxySettings PAC; - enum_constant public static final android.net.IpConfiguration.ProxySettings STATIC; - enum_constant public static final android.net.IpConfiguration.ProxySettings UNASSIGNED; - } - - public final class IpPrefix implements android.os.Parcelable { - ctor public IpPrefix(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int); - ctor public IpPrefix(@NonNull String); - } - - public class KeepalivePacketData { - ctor protected KeepalivePacketData(@NonNull java.net.InetAddress, @IntRange(from=0, to=65535) int, @NonNull java.net.InetAddress, @IntRange(from=0, to=65535) int, @NonNull byte[]) throws android.net.InvalidPacketException; - method @NonNull public java.net.InetAddress getDstAddress(); - method public int getDstPort(); - method @NonNull public byte[] getPacket(); - method @NonNull public java.net.InetAddress getSrcAddress(); - method public int getSrcPort(); - } - - public class LinkAddress implements android.os.Parcelable { - ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int, int, int); - ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int, int, int, long, long); - ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int); - ctor public LinkAddress(@NonNull String); - ctor public LinkAddress(@NonNull String, int, int); - method public long getDeprecationTime(); - method public long getExpirationTime(); - method public boolean isGlobalPreferred(); - method public boolean isIpv4(); - method public boolean isIpv6(); - method public boolean isSameAddressAs(@Nullable android.net.LinkAddress); - field public static final long LIFETIME_PERMANENT = 9223372036854775807L; // 0x7fffffffffffffffL - field public static final long LIFETIME_UNKNOWN = -1L; // 0xffffffffffffffffL - } - - public final class LinkProperties implements android.os.Parcelable { - ctor public LinkProperties(@Nullable android.net.LinkProperties); - ctor public LinkProperties(@Nullable android.net.LinkProperties, boolean); - method public boolean addDnsServer(@NonNull java.net.InetAddress); - method public boolean addLinkAddress(@NonNull android.net.LinkAddress); - method public boolean addPcscfServer(@NonNull java.net.InetAddress); - method @NonNull public java.util.List getAddresses(); - method @NonNull public java.util.List getAllInterfaceNames(); - method @NonNull public java.util.List getAllLinkAddresses(); - method @NonNull public java.util.List getAllRoutes(); - method @Nullable public android.net.Uri getCaptivePortalApiUrl(); - method @Nullable public android.net.CaptivePortalData getCaptivePortalData(); - method @NonNull public java.util.List getPcscfServers(); - method @Nullable public String getTcpBufferSizes(); - method @NonNull public java.util.List getValidatedPrivateDnsServers(); - method public boolean hasGlobalIpv6Address(); - method public boolean hasIpv4Address(); - method public boolean hasIpv4DefaultRoute(); - method public boolean hasIpv4DnsServer(); - method public boolean hasIpv6DefaultRoute(); - method public boolean hasIpv6DnsServer(); - method public boolean isIpv4Provisioned(); - method public boolean isIpv6Provisioned(); - method public boolean isProvisioned(); - method public boolean isReachable(@NonNull java.net.InetAddress); - method public boolean removeDnsServer(@NonNull java.net.InetAddress); - method public boolean removeLinkAddress(@NonNull android.net.LinkAddress); - method public boolean removeRoute(@NonNull android.net.RouteInfo); - method public void setCaptivePortalApiUrl(@Nullable android.net.Uri); - method public void setCaptivePortalData(@Nullable android.net.CaptivePortalData); - method public void setPcscfServers(@NonNull java.util.Collection); - method public void setPrivateDnsServerName(@Nullable String); - method public void setTcpBufferSizes(@Nullable String); - method public void setUsePrivateDns(boolean); - method public void setValidatedPrivateDnsServers(@NonNull java.util.Collection); - } - - public final class NattKeepalivePacketData extends android.net.KeepalivePacketData implements android.os.Parcelable { - ctor public NattKeepalivePacketData(@NonNull java.net.InetAddress, int, @NonNull java.net.InetAddress, int, @NonNull byte[]) throws android.net.InvalidPacketException; - method public int describeContents(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator CREATOR; - } - - public class Network implements android.os.Parcelable { - ctor public Network(@NonNull android.net.Network); - method public int getNetId(); - method @NonNull public android.net.Network getPrivateDnsBypassingCopy(); - } - - public abstract class NetworkAgent { - ctor public NetworkAgent(@NonNull android.content.Context, @NonNull android.os.Looper, @NonNull String, @NonNull android.net.NetworkCapabilities, @NonNull android.net.LinkProperties, int, @NonNull android.net.NetworkAgentConfig, @Nullable android.net.NetworkProvider); - ctor public NetworkAgent(@NonNull android.content.Context, @NonNull android.os.Looper, @NonNull String, @NonNull android.net.NetworkCapabilities, @NonNull android.net.LinkProperties, @NonNull android.net.NetworkScore, @NonNull android.net.NetworkAgentConfig, @Nullable android.net.NetworkProvider); - method @Nullable public android.net.Network getNetwork(); - method public void markConnected(); - method public void onAddKeepalivePacketFilter(int, @NonNull android.net.KeepalivePacketData); - method public void onAutomaticReconnectDisabled(); - method public void onBandwidthUpdateRequested(); - method public void onNetworkCreated(); - method public void onNetworkDestroyed(); - method public void onNetworkUnwanted(); - method public void onQosCallbackRegistered(int, @NonNull android.net.QosFilter); - method public void onQosCallbackUnregistered(int); - method public void onRemoveKeepalivePacketFilter(int); - method public void onSaveAcceptUnvalidated(boolean); - method public void onSignalStrengthThresholdsUpdated(@NonNull int[]); - method public void onStartSocketKeepalive(int, @NonNull java.time.Duration, @NonNull android.net.KeepalivePacketData); - method public void onStopSocketKeepalive(int); - method public void onValidationStatus(int, @Nullable android.net.Uri); - method @NonNull public android.net.Network register(); - method public final void sendLinkProperties(@NonNull android.net.LinkProperties); - method public final void sendNetworkCapabilities(@NonNull android.net.NetworkCapabilities); - method public final void sendNetworkScore(@NonNull android.net.NetworkScore); - method public final void sendNetworkScore(@IntRange(from=0, to=99) int); - method public final void sendQosCallbackError(int, int); - method public final void sendQosSessionAvailable(int, int, @NonNull android.net.QosSessionAttributes); - method public final void sendQosSessionLost(int, int, int); - method public final void sendSocketKeepaliveEvent(int, int); - method @Deprecated public void setLegacySubtype(int, @NonNull String); - method public void setLingerDuration(@NonNull java.time.Duration); - method public void setTeardownDelayMillis(@IntRange(from=0, to=0x1388) int); - method public final void setUnderlyingNetworks(@Nullable java.util.List); - method public void unregister(); - field public static final int VALIDATION_STATUS_NOT_VALID = 2; // 0x2 - field public static final int VALIDATION_STATUS_VALID = 1; // 0x1 - } - - public final class NetworkAgentConfig implements android.os.Parcelable { - method public int describeContents(); - method public int getLegacyType(); - method @NonNull public String getLegacyTypeName(); - method public boolean isExplicitlySelected(); - method public boolean isPartialConnectivityAcceptable(); - method public boolean isUnvalidatedConnectivityAcceptable(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator CREATOR; - } - - public static final class NetworkAgentConfig.Builder { - ctor public NetworkAgentConfig.Builder(); - method @NonNull public android.net.NetworkAgentConfig build(); - method @NonNull public android.net.NetworkAgentConfig.Builder setExplicitlySelected(boolean); - method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyExtraInfo(@NonNull String); - method @NonNull public android.net.NetworkAgentConfig.Builder setLegacySubType(int); - method @NonNull public android.net.NetworkAgentConfig.Builder setLegacySubTypeName(@NonNull String); - method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyType(int); - method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyTypeName(@NonNull String); - method @NonNull public android.net.NetworkAgentConfig.Builder setNat64DetectionEnabled(boolean); - method @NonNull public android.net.NetworkAgentConfig.Builder setPartialConnectivityAcceptable(boolean); - method @NonNull public android.net.NetworkAgentConfig.Builder setProvisioningNotificationEnabled(boolean); - method @NonNull public android.net.NetworkAgentConfig.Builder setUnvalidatedConnectivityAcceptable(boolean); - } - - public final class NetworkCapabilities implements android.os.Parcelable { - method @NonNull public int[] getAdministratorUids(); - method @Nullable public static String getCapabilityCarrierName(int); - method @Nullable public String getSsid(); - method @NonNull public java.util.Set getSubscriptionIds(); - method @NonNull public int[] getTransportTypes(); - method public boolean isPrivateDnsBroken(); - method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities); - field public static final int NET_CAPABILITY_BIP = 31; // 0x1f - field public static final int NET_CAPABILITY_NOT_VCN_MANAGED = 28; // 0x1c - field public static final int NET_CAPABILITY_OEM_PAID = 22; // 0x16 - field public static final int NET_CAPABILITY_OEM_PRIVATE = 26; // 0x1a - field public static final int NET_CAPABILITY_PARTIAL_CONNECTIVITY = 24; // 0x18 - field public static final int NET_CAPABILITY_VEHICLE_INTERNAL = 27; // 0x1b - field public static final int NET_CAPABILITY_VSIM = 30; // 0x1e - } - - public static final class NetworkCapabilities.Builder { - ctor public NetworkCapabilities.Builder(); - ctor public NetworkCapabilities.Builder(@NonNull android.net.NetworkCapabilities); - method @NonNull public android.net.NetworkCapabilities.Builder addCapability(int); - method @NonNull public android.net.NetworkCapabilities.Builder addTransportType(int); - method @NonNull public android.net.NetworkCapabilities build(); - method @NonNull public android.net.NetworkCapabilities.Builder removeCapability(int); - method @NonNull public android.net.NetworkCapabilities.Builder removeTransportType(int); - method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setAdministratorUids(@NonNull int[]); - method @NonNull public android.net.NetworkCapabilities.Builder setLinkDownstreamBandwidthKbps(int); - method @NonNull public android.net.NetworkCapabilities.Builder setLinkUpstreamBandwidthKbps(int); - method @NonNull public android.net.NetworkCapabilities.Builder setNetworkSpecifier(@Nullable android.net.NetworkSpecifier); - method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setOwnerUid(int); - method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setRequestorPackageName(@Nullable String); - method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setRequestorUid(int); - method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) public android.net.NetworkCapabilities.Builder setSignalStrength(int); - method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setSsid(@Nullable String); - method @NonNull public android.net.NetworkCapabilities.Builder setSubscriptionIds(@NonNull java.util.Set); - method @NonNull public android.net.NetworkCapabilities.Builder setTransportInfo(@Nullable android.net.TransportInfo); - method @NonNull public static android.net.NetworkCapabilities.Builder withoutDefaultCapabilities(); - } - - public class NetworkProvider { - ctor public NetworkProvider(@NonNull android.content.Context, @NonNull android.os.Looper, @NonNull String); - method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void declareNetworkRequestUnfulfillable(@NonNull android.net.NetworkRequest); - method public int getProviderId(); - method public void onNetworkRequestWithdrawn(@NonNull android.net.NetworkRequest); - method public void onNetworkRequested(@NonNull android.net.NetworkRequest, @IntRange(from=0, to=99) int, int); - method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void registerNetworkOffer(@NonNull android.net.NetworkScore, @NonNull android.net.NetworkCapabilities, @NonNull java.util.concurrent.Executor, @NonNull android.net.NetworkProvider.NetworkOfferCallback); - method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void unregisterNetworkOffer(@NonNull android.net.NetworkProvider.NetworkOfferCallback); - field public static final int ID_NONE = -1; // 0xffffffff - } - - public static interface NetworkProvider.NetworkOfferCallback { - method public void onNetworkNeeded(@NonNull android.net.NetworkRequest); - method public void onNetworkUnneeded(@NonNull android.net.NetworkRequest); - } - - public class NetworkReleasedException extends java.lang.Exception { - } - - public class NetworkRequest implements android.os.Parcelable { - method @Nullable public String getRequestorPackageName(); - method public int getRequestorUid(); - } - - public static class NetworkRequest.Builder { - method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) public android.net.NetworkRequest.Builder setSignalStrength(int); - method @NonNull public android.net.NetworkRequest.Builder setSubscriptionIds(@NonNull java.util.Set); - } - - public final class NetworkScore implements android.os.Parcelable { - method public int describeContents(); - method public int getKeepConnectedReason(); - method public int getLegacyInt(); - method public boolean isExiting(); - method public boolean isTransportPrimary(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator CREATOR; - field public static final int KEEP_CONNECTED_FOR_HANDOVER = 1; // 0x1 - field public static final int KEEP_CONNECTED_NONE = 0; // 0x0 - } - - public static final class NetworkScore.Builder { - ctor public NetworkScore.Builder(); - method @NonNull public android.net.NetworkScore build(); - method @NonNull public android.net.NetworkScore.Builder setExiting(boolean); - method @NonNull public android.net.NetworkScore.Builder setKeepConnectedReason(int); - method @NonNull public android.net.NetworkScore.Builder setLegacyInt(int); - method @NonNull public android.net.NetworkScore.Builder setTransportPrimary(boolean); - } - - public final class OemNetworkPreferences implements android.os.Parcelable { - method public int describeContents(); - method @NonNull public java.util.Map getNetworkPreferences(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator CREATOR; - field public static final int OEM_NETWORK_PREFERENCE_OEM_PAID = 1; // 0x1 - field public static final int OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK = 2; // 0x2 - field public static final int OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY = 3; // 0x3 - field public static final int OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY = 4; // 0x4 - field public static final int OEM_NETWORK_PREFERENCE_UNINITIALIZED = 0; // 0x0 - } - - public static final class OemNetworkPreferences.Builder { - ctor public OemNetworkPreferences.Builder(); - ctor public OemNetworkPreferences.Builder(@NonNull android.net.OemNetworkPreferences); - method @NonNull public android.net.OemNetworkPreferences.Builder addNetworkPreference(@NonNull String, int); - method @NonNull public android.net.OemNetworkPreferences build(); - method @NonNull public android.net.OemNetworkPreferences.Builder clearNetworkPreference(@NonNull String); - } - - public abstract class QosCallback { - ctor public QosCallback(); - method public void onError(@NonNull android.net.QosCallbackException); - method public void onQosSessionAvailable(@NonNull android.net.QosSession, @NonNull android.net.QosSessionAttributes); - method public void onQosSessionLost(@NonNull android.net.QosSession); - } - - public static class QosCallback.QosCallbackRegistrationException extends java.lang.RuntimeException { - } - - public final class QosCallbackException extends java.lang.Exception { - } - - public abstract class QosFilter { - method @NonNull public abstract android.net.Network getNetwork(); - method public abstract boolean matchesLocalAddress(@NonNull java.net.InetAddress, int, int); - method public abstract boolean matchesRemoteAddress(@NonNull java.net.InetAddress, int, int); - } - - public final class QosSession implements android.os.Parcelable { - ctor public QosSession(int, int); - method public int describeContents(); - method public int getSessionId(); - method public int getSessionType(); - method public long getUniqueId(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator CREATOR; - field public static final int TYPE_EPS_BEARER = 1; // 0x1 - field public static final int TYPE_NR_BEARER = 2; // 0x2 - } - - public interface QosSessionAttributes { - } - - public final class QosSocketInfo implements android.os.Parcelable { - ctor public QosSocketInfo(@NonNull android.net.Network, @NonNull java.net.Socket) throws java.io.IOException; - method public int describeContents(); - method @NonNull public java.net.InetSocketAddress getLocalSocketAddress(); - method @NonNull public android.net.Network getNetwork(); - method @Nullable public java.net.InetSocketAddress getRemoteSocketAddress(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator CREATOR; - } - - public final class RouteInfo implements android.os.Parcelable { - ctor public RouteInfo(@Nullable android.net.IpPrefix, @Nullable java.net.InetAddress, @Nullable String, int); - ctor public RouteInfo(@Nullable android.net.IpPrefix, @Nullable java.net.InetAddress, @Nullable String, int, int); - method public int getMtu(); - method public int getType(); - field public static final int RTN_THROW = 9; // 0x9 - field public static final int RTN_UNICAST = 1; // 0x1 - field public static final int RTN_UNREACHABLE = 7; // 0x7 - } - - public abstract class SocketKeepalive implements java.lang.AutoCloseable { - field public static final int ERROR_NO_SUCH_SLOT = -33; // 0xffffffdf - field public static final int SUCCESS = 0; // 0x0 - } - - public class SocketLocalAddressChangedException extends java.lang.Exception { - } - - public class SocketNotBoundException extends java.lang.Exception { - } - - public final class StaticIpConfiguration implements android.os.Parcelable { - ctor public StaticIpConfiguration(); - ctor public StaticIpConfiguration(@Nullable android.net.StaticIpConfiguration); - method public void addDnsServer(@NonNull java.net.InetAddress); - method public void clear(); - method public int describeContents(); - method @NonNull public java.util.List getDnsServers(); - method @Nullable public String getDomains(); - method @Nullable public java.net.InetAddress getGateway(); - method @Nullable public android.net.LinkAddress getIpAddress(); - method @NonNull public java.util.List getRoutes(@Nullable String); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator CREATOR; - } - - public static final class StaticIpConfiguration.Builder { - ctor public StaticIpConfiguration.Builder(); - method @NonNull public android.net.StaticIpConfiguration build(); - method @NonNull public android.net.StaticIpConfiguration.Builder setDnsServers(@NonNull Iterable); - method @NonNull public android.net.StaticIpConfiguration.Builder setDomains(@Nullable String); - method @NonNull public android.net.StaticIpConfiguration.Builder setGateway(@Nullable java.net.InetAddress); - method @NonNull public android.net.StaticIpConfiguration.Builder setIpAddress(@Nullable android.net.LinkAddress); - } - - public final class TcpKeepalivePacketData extends android.net.KeepalivePacketData implements android.os.Parcelable { - ctor public TcpKeepalivePacketData(@NonNull java.net.InetAddress, int, @NonNull java.net.InetAddress, int, @NonNull byte[], int, int, int, int, int, int) throws android.net.InvalidPacketException; - method public int describeContents(); - method public int getIpTos(); - method public int getIpTtl(); - method public int getTcpAck(); - method public int getTcpSeq(); - method public int getTcpWindow(); - method public int getTcpWindowScale(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator CREATOR; - } - -} - -package android.net.apf { - - public final class ApfCapabilities implements android.os.Parcelable { - ctor public ApfCapabilities(int, int, int); - method public int describeContents(); - method public static boolean getApfDrop8023Frames(); - method @NonNull public static int[] getApfEtherTypeBlackList(); - method public boolean hasDataAccess(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator CREATOR; - field public final int apfPacketFormat; - field public final int apfVersionSupported; - field public final int maximumApfProgramSize; - } - -} - diff --git a/packages/Connectivity/framework/api/system-lint-baseline.txt b/packages/Connectivity/framework/api/system-lint-baseline.txt deleted file mode 100644 index 9a97707763f11..0000000000000 --- a/packages/Connectivity/framework/api/system-lint-baseline.txt +++ /dev/null @@ -1 +0,0 @@ -// Baseline format: 1.0 diff --git a/packages/Connectivity/framework/api/system-removed.txt b/packages/Connectivity/framework/api/system-removed.txt deleted file mode 100644 index d802177e249b3..0000000000000 --- a/packages/Connectivity/framework/api/system-removed.txt +++ /dev/null @@ -1 +0,0 @@ -// Signature format: 2.0 diff --git a/packages/Connectivity/framework/jarjar-rules.txt b/packages/Connectivity/framework/jarjar-rules.txt deleted file mode 100644 index 2e5848cb100d3..0000000000000 --- a/packages/Connectivity/framework/jarjar-rules.txt +++ /dev/null @@ -1,2 +0,0 @@ -rule com.android.net.module.util.** android.net.connectivity.framework.util.@1 -rule android.net.NetworkFactory* android.net.connectivity.framework.NetworkFactory@1 diff --git a/packages/Connectivity/framework/jni/android_net_NetworkUtils.cpp b/packages/Connectivity/framework/jni/android_net_NetworkUtils.cpp deleted file mode 100644 index 7478b3e73d0f9..0000000000000 --- a/packages/Connectivity/framework/jni/android_net_NetworkUtils.cpp +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Copyright 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. - */ - -#define LOG_TAG "NetworkUtils" - -#include -#include -#include -#include -#include -#include - -#include // NETID_USE_LOCAL_NAMESERVERS -#include -#include - -#include "jni.h" - -#define NETUTILS_PKG_NAME "android/net/NetworkUtils" - -namespace android { - -constexpr int MAXPACKETSIZE = 8 * 1024; -// FrameworkListener limits the size of commands to 4096 bytes. -constexpr int MAXCMDSIZE = 4096; - -static volatile jclass class_Network = 0; -static volatile jmethodID method_fromNetworkHandle = 0; - -static inline jclass FindClassOrDie(JNIEnv* env, const char* class_name) { - jclass clazz = env->FindClass(class_name); - LOG_ALWAYS_FATAL_IF(clazz == NULL, "Unable to find class %s", class_name); - return clazz; -} - -template -static inline T MakeGlobalRefOrDie(JNIEnv* env, T in) { - jobject res = env->NewGlobalRef(in); - LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to create global reference."); - return static_cast(res); -} - -static void android_net_utils_attachDropAllBPFFilter(JNIEnv *env, jobject clazz, jobject javaFd) -{ - struct sock_filter filter_code[] = { - // Reject all. - BPF_STMT(BPF_RET | BPF_K, 0) - }; - struct sock_fprog filter = { - sizeof(filter_code) / sizeof(filter_code[0]), - filter_code, - }; - - int fd = AFileDescriptor_getFd(env, javaFd); - if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) != 0) { - jniThrowExceptionFmt(env, "java/net/SocketException", - "setsockopt(SO_ATTACH_FILTER): %s", strerror(errno)); - } -} - -static void android_net_utils_detachBPFFilter(JNIEnv *env, jobject clazz, jobject javaFd) -{ - int optval_ignored = 0; - int fd = AFileDescriptor_getFd(env, javaFd); - if (setsockopt(fd, SOL_SOCKET, SO_DETACH_FILTER, &optval_ignored, sizeof(optval_ignored)) != - 0) { - jniThrowExceptionFmt(env, "java/net/SocketException", - "setsockopt(SO_DETACH_FILTER): %s", strerror(errno)); - } -} - -static jboolean android_net_utils_bindProcessToNetworkHandle(JNIEnv *env, jobject thiz, - jlong netHandle) -{ - return (jboolean) !android_setprocnetwork(netHandle); -} - -static jlong android_net_utils_getBoundNetworkHandleForProcess(JNIEnv *env, jobject thiz) -{ - net_handle_t network; - if (android_getprocnetwork(&network) != 0) { - jniThrowExceptionFmt(env, "java/lang/IllegalStateException", - "android_getprocnetwork(): %s", strerror(errno)); - return NETWORK_UNSPECIFIED; - } - return (jlong) network; -} - -static jboolean android_net_utils_bindProcessToNetworkForHostResolution(JNIEnv *env, jobject thiz, - jint netId, jlong netHandle) -{ - return (jboolean) !android_setprocdns(netHandle); -} - -static jint android_net_utils_bindSocketToNetworkHandle(JNIEnv *env, jobject thiz, jobject javaFd, - jlong netHandle) { - return android_setsocknetwork(netHandle, AFileDescriptor_getFd(env, javaFd)); -} - -static bool checkLenAndCopy(JNIEnv* env, const jbyteArray& addr, int len, void* dst) -{ - if (env->GetArrayLength(addr) != len) { - return false; - } - env->GetByteArrayRegion(addr, 0, len, reinterpret_cast(dst)); - return true; -} - -static jobject android_net_utils_resNetworkQuery(JNIEnv *env, jobject thiz, jlong netHandle, - jstring dname, jint ns_class, jint ns_type, jint flags) { - const jsize javaCharsCount = env->GetStringLength(dname); - const jsize byteCountUTF8 = env->GetStringUTFLength(dname); - - // Only allow dname which could be simply formatted to UTF8. - // In native layer, res_mkquery would re-format the input char array to packet. - char queryname[byteCountUTF8 + 1]; - memset(queryname, 0, (byteCountUTF8 + 1) * sizeof(char)); - - env->GetStringUTFRegion(dname, 0, javaCharsCount, queryname); - int fd = android_res_nquery(netHandle, queryname, ns_class, ns_type, flags); - - if (fd < 0) { - jniThrowErrnoException(env, "resNetworkQuery", -fd); - return nullptr; - } - - return jniCreateFileDescriptor(env, fd); -} - -static jobject android_net_utils_resNetworkSend(JNIEnv *env, jobject thiz, jlong netHandle, - jbyteArray msg, jint msgLen, jint flags) { - uint8_t data[MAXCMDSIZE]; - - checkLenAndCopy(env, msg, msgLen, data); - int fd = android_res_nsend(netHandle, data, msgLen, flags); - - if (fd < 0) { - jniThrowErrnoException(env, "resNetworkSend", -fd); - return nullptr; - } - - return jniCreateFileDescriptor(env, fd); -} - -static jobject android_net_utils_resNetworkResult(JNIEnv *env, jobject thiz, jobject javaFd) { - int fd = AFileDescriptor_getFd(env, javaFd); - int rcode; - uint8_t buf[MAXPACKETSIZE] = {0}; - - int res = android_res_nresult(fd, &rcode, buf, MAXPACKETSIZE); - jniSetFileDescriptorOfFD(env, javaFd, -1); - if (res < 0) { - jniThrowErrnoException(env, "resNetworkResult", -res); - return nullptr; - } - - jbyteArray answer = env->NewByteArray(res); - if (answer == nullptr) { - jniThrowErrnoException(env, "resNetworkResult", ENOMEM); - return nullptr; - } else { - env->SetByteArrayRegion(answer, 0, res, reinterpret_cast(buf)); - } - - jclass class_DnsResponse = env->FindClass("android/net/DnsResolver$DnsResponse"); - jmethodID ctor = env->GetMethodID(class_DnsResponse, "", "([BI)V"); - - return env->NewObject(class_DnsResponse, ctor, answer, rcode); -} - -static void android_net_utils_resNetworkCancel(JNIEnv *env, jobject thiz, jobject javaFd) { - int fd = AFileDescriptor_getFd(env, javaFd); - android_res_cancel(fd); - jniSetFileDescriptorOfFD(env, javaFd, -1); -} - -static jobject android_net_utils_getDnsNetwork(JNIEnv *env, jobject thiz) { - net_handle_t dnsNetHandle = NETWORK_UNSPECIFIED; - if (int res = android_getprocdns(&dnsNetHandle) < 0) { - jniThrowErrnoException(env, "getDnsNetwork", -res); - return nullptr; - } - - if (method_fromNetworkHandle == 0) { - // This may be called multiple times concurrently but that is fine - class_Network = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/net/Network")); - method_fromNetworkHandle = env->GetStaticMethodID(class_Network, "fromNetworkHandle", - "(J)Landroid/net/Network;"); - } - return env->CallStaticObjectMethod(class_Network, method_fromNetworkHandle, - static_cast(dnsNetHandle)); -} - -static jobject android_net_utils_getTcpRepairWindow(JNIEnv *env, jobject thiz, jobject javaFd) { - if (javaFd == NULL) { - jniThrowNullPointerException(env, NULL); - return NULL; - } - - int fd = AFileDescriptor_getFd(env, javaFd); - struct tcp_repair_window trw = {}; - socklen_t size = sizeof(trw); - - // Obtain the parameters of the TCP repair window. - int rc = getsockopt(fd, IPPROTO_TCP, TCP_REPAIR_WINDOW, &trw, &size); - if (rc == -1) { - jniThrowErrnoException(env, "getsockopt : TCP_REPAIR_WINDOW", errno); - return NULL; - } - - struct tcp_info tcpinfo = {}; - socklen_t tcpinfo_size = sizeof(tcp_info); - - // Obtain the window scale from the tcp info structure. This contains a scale factor that - // should be applied to the window size. - rc = getsockopt(fd, IPPROTO_TCP, TCP_INFO, &tcpinfo, &tcpinfo_size); - if (rc == -1) { - jniThrowErrnoException(env, "getsockopt : TCP_INFO", errno); - return NULL; - } - - jclass class_TcpRepairWindow = env->FindClass("android/net/TcpRepairWindow"); - jmethodID ctor = env->GetMethodID(class_TcpRepairWindow, "", "(IIIIII)V"); - - return env->NewObject(class_TcpRepairWindow, ctor, trw.snd_wl1, trw.snd_wnd, trw.max_window, - trw.rcv_wnd, trw.rcv_wup, tcpinfo.tcpi_rcv_wscale); -} - -// ---------------------------------------------------------------------------- - -/* - * JNI registration. - */ -// clang-format off -static const JNINativeMethod gNetworkUtilMethods[] = { - /* name, signature, funcPtr */ - { "bindProcessToNetworkHandle", "(J)Z", (void*) android_net_utils_bindProcessToNetworkHandle }, - { "getBoundNetworkHandleForProcess", "()J", (void*) android_net_utils_getBoundNetworkHandleForProcess }, - { "bindProcessToNetworkForHostResolution", "(I)Z", (void*) android_net_utils_bindProcessToNetworkForHostResolution }, - { "bindSocketToNetworkHandle", "(Ljava/io/FileDescriptor;J)I", (void*) android_net_utils_bindSocketToNetworkHandle }, - { "attachDropAllBPFFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_attachDropAllBPFFilter }, - { "detachBPFFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_detachBPFFilter }, - { "getTcpRepairWindow", "(Ljava/io/FileDescriptor;)Landroid/net/TcpRepairWindow;", (void*) android_net_utils_getTcpRepairWindow }, - { "resNetworkSend", "(J[BII)Ljava/io/FileDescriptor;", (void*) android_net_utils_resNetworkSend }, - { "resNetworkQuery", "(JLjava/lang/String;III)Ljava/io/FileDescriptor;", (void*) android_net_utils_resNetworkQuery }, - { "resNetworkResult", "(Ljava/io/FileDescriptor;)Landroid/net/DnsResolver$DnsResponse;", (void*) android_net_utils_resNetworkResult }, - { "resNetworkCancel", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_resNetworkCancel }, - { "getDnsNetwork", "()Landroid/net/Network;", (void*) android_net_utils_getDnsNetwork }, -}; -// clang-format on - -int register_android_net_NetworkUtils(JNIEnv* env) -{ - return jniRegisterNativeMethods(env, NETUTILS_PKG_NAME, gNetworkUtilMethods, - NELEM(gNetworkUtilMethods)); -} - -}; // namespace android diff --git a/packages/Connectivity/framework/jni/onload.cpp b/packages/Connectivity/framework/jni/onload.cpp deleted file mode 100644 index 435f4343ed145..0000000000000 --- a/packages/Connectivity/framework/jni/onload.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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. - */ - -#include -#include - -namespace android { - -int register_android_net_NetworkUtils(JNIEnv* env); - -extern "C" jint JNI_OnLoad(JavaVM* vm, void*) { - JNIEnv *env; - if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) { - ALOGE("GetEnv failed"); - return JNI_ERR; - } - - if (register_android_net_NetworkUtils(env) < 0) { - return JNI_ERR; - } - - return JNI_VERSION_1_6; -} - -}; \ No newline at end of file diff --git a/packages/Connectivity/framework/lint-baseline.xml b/packages/Connectivity/framework/lint-baseline.xml deleted file mode 100644 index df37ae8514386..0000000000000 --- a/packages/Connectivity/framework/lint-baseline.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/packages/Connectivity/framework/src/android/net/CaptivePortal.java b/packages/Connectivity/framework/src/android/net/CaptivePortal.java deleted file mode 100644 index 4a7b6016427be..0000000000000 --- a/packages/Connectivity/framework/src/android/net/CaptivePortal.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed urnder the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.net; - -import android.annotation.NonNull; -import android.annotation.RequiresPermission; -import android.annotation.SystemApi; -import android.os.IBinder; -import android.os.Parcel; -import android.os.Parcelable; -import android.os.RemoteException; - -/** - * A class allowing apps handling the {@link ConnectivityManager#ACTION_CAPTIVE_PORTAL_SIGN_IN} - * activity to indicate to the system different outcomes of captive portal sign in. This class is - * passed as an extra named {@link ConnectivityManager#EXTRA_CAPTIVE_PORTAL} with the - * {@code ACTION_CAPTIVE_PORTAL_SIGN_IN} activity. - */ -public class CaptivePortal implements Parcelable { - /** - * Response code from the captive portal application, indicating that the portal was dismissed - * and the network should be re-validated. - * @see ICaptivePortal#appResponse(int) - * @see android.net.INetworkMonitor#notifyCaptivePortalAppFinished(int) - * @hide - */ - @SystemApi - public static final int APP_RETURN_DISMISSED = 0; - /** - * Response code from the captive portal application, indicating that the user did not login and - * does not want to use the captive portal network. - * @see ICaptivePortal#appResponse(int) - * @see android.net.INetworkMonitor#notifyCaptivePortalAppFinished(int) - * @hide - */ - @SystemApi - public static final int APP_RETURN_UNWANTED = 1; - /** - * Response code from the captive portal application, indicating that the user does not wish to - * login but wants to use the captive portal network as-is. - * @see ICaptivePortal#appResponse(int) - * @see android.net.INetworkMonitor#notifyCaptivePortalAppFinished(int) - * @hide - */ - @SystemApi - public static final int APP_RETURN_WANTED_AS_IS = 2; - /** Event offset of request codes from captive portal application. */ - private static final int APP_REQUEST_BASE = 100; - /** - * Request code from the captive portal application, indicating that the network condition may - * have changed and the network should be re-validated. - * @see ICaptivePortal#appRequest(int) - * @see android.net.INetworkMonitor#forceReevaluation(int) - * @hide - */ - @SystemApi - public static final int APP_REQUEST_REEVALUATION_REQUIRED = APP_REQUEST_BASE + 0; - - private final IBinder mBinder; - - /** @hide */ - public CaptivePortal(@NonNull IBinder binder) { - mBinder = binder; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel out, int flags) { - out.writeStrongBinder(mBinder); - } - - public static final @android.annotation.NonNull Parcelable.Creator CREATOR - = new Parcelable.Creator() { - @Override - public CaptivePortal createFromParcel(Parcel in) { - return new CaptivePortal(in.readStrongBinder()); - } - - @Override - public CaptivePortal[] newArray(int size) { - return new CaptivePortal[size]; - } - }; - - /** - * Indicate to the system that the captive portal has been - * dismissed. In response the framework will re-evaluate the network's - * connectivity and might take further action thereafter. - */ - public void reportCaptivePortalDismissed() { - try { - ICaptivePortal.Stub.asInterface(mBinder).appResponse(APP_RETURN_DISMISSED); - } catch (RemoteException e) { - } - } - - /** - * Indicate to the system that the user does not want to pursue signing in to the - * captive portal and the system should continue to prefer other networks - * without captive portals for use as the default active data network. The - * system will not retest the network for a captive portal so as to avoid - * disturbing the user with further sign in to network notifications. - */ - public void ignoreNetwork() { - try { - ICaptivePortal.Stub.asInterface(mBinder).appResponse(APP_RETURN_UNWANTED); - } catch (RemoteException e) { - } - } - - /** - * Indicate to the system the user wants to use this network as is, even though - * the captive portal is still in place. The system will treat the network - * as if it did not have a captive portal when selecting the network to use - * as the default active data network. This may result in this network - * becoming the default active data network, which could disrupt network - * connectivity for apps because the captive portal is still in place. - * @hide - */ - @SystemApi - public void useNetwork() { - try { - ICaptivePortal.Stub.asInterface(mBinder).appResponse(APP_RETURN_WANTED_AS_IS); - } catch (RemoteException e) { - } - } - - /** - * Request that the system reevaluates the captive portal status. - * @hide - */ - @SystemApi - @RequiresPermission(android.Manifest.permission.NETWORK_STACK) - public void reevaluateNetwork() { - try { - ICaptivePortal.Stub.asInterface(mBinder).appRequest(APP_REQUEST_REEVALUATION_REQUIRED); - } catch (RemoteException e) { - } - } - - /** - * Log a captive portal login event. - * @param eventId one of the CAPTIVE_PORTAL_LOGIN_* constants in metrics_constants.proto. - * @param packageName captive portal application package name. - * @hide - * @deprecated The event will not be logged in Android S and above. The - * caller is migrating to statsd. - */ - @Deprecated - @SystemApi - public void logEvent(int eventId, @NonNull String packageName) { - } -} diff --git a/packages/Connectivity/framework/src/android/net/CaptivePortalData.java b/packages/Connectivity/framework/src/android/net/CaptivePortalData.java deleted file mode 100644 index 53aa1b92edcad..0000000000000 --- a/packages/Connectivity/framework/src/android/net/CaptivePortalData.java +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SystemApi; -import android.os.Parcel; -import android.os.Parcelable; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.Objects; - -/** - * Metadata sent by captive portals, see https://www.ietf.org/id/draft-ietf-capport-api-03.txt. - * @hide - */ -@SystemApi -public final class CaptivePortalData implements Parcelable { - private final long mRefreshTimeMillis; - @Nullable - private final Uri mUserPortalUrl; - @Nullable - private final Uri mVenueInfoUrl; - private final boolean mIsSessionExtendable; - private final long mByteLimit; - private final long mExpiryTimeMillis; - private final boolean mCaptive; - private final String mVenueFriendlyName; - private final int mVenueInfoUrlSource; - private final int mUserPortalUrlSource; - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = {"CAPTIVE_PORTAL_DATA_SOURCE_"}, value = { - CAPTIVE_PORTAL_DATA_SOURCE_OTHER, - CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT}) - public @interface CaptivePortalDataSource {} - - /** - * Source of information: Other (default) - */ - public static final int CAPTIVE_PORTAL_DATA_SOURCE_OTHER = 0; - - /** - * Source of information: Wi-Fi Passpoint - */ - public static final int CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT = 1; - - private CaptivePortalData(long refreshTimeMillis, Uri userPortalUrl, Uri venueInfoUrl, - boolean isSessionExtendable, long byteLimit, long expiryTimeMillis, boolean captive, - CharSequence venueFriendlyName, int venueInfoUrlSource, int userPortalUrlSource) { - mRefreshTimeMillis = refreshTimeMillis; - mUserPortalUrl = userPortalUrl; - mVenueInfoUrl = venueInfoUrl; - mIsSessionExtendable = isSessionExtendable; - mByteLimit = byteLimit; - mExpiryTimeMillis = expiryTimeMillis; - mCaptive = captive; - mVenueFriendlyName = venueFriendlyName == null ? null : venueFriendlyName.toString(); - mVenueInfoUrlSource = venueInfoUrlSource; - mUserPortalUrlSource = userPortalUrlSource; - } - - private CaptivePortalData(Parcel p) { - this(p.readLong(), p.readParcelable(null), p.readParcelable(null), p.readBoolean(), - p.readLong(), p.readLong(), p.readBoolean(), p.readString(), p.readInt(), - p.readInt()); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeLong(mRefreshTimeMillis); - dest.writeParcelable(mUserPortalUrl, 0); - dest.writeParcelable(mVenueInfoUrl, 0); - dest.writeBoolean(mIsSessionExtendable); - dest.writeLong(mByteLimit); - dest.writeLong(mExpiryTimeMillis); - dest.writeBoolean(mCaptive); - dest.writeString(mVenueFriendlyName); - dest.writeInt(mVenueInfoUrlSource); - dest.writeInt(mUserPortalUrlSource); - } - - /** - * A builder to create new {@link CaptivePortalData}. - */ - public static class Builder { - private long mRefreshTime; - private Uri mUserPortalUrl; - private Uri mVenueInfoUrl; - private boolean mIsSessionExtendable; - private long mBytesRemaining = -1; - private long mExpiryTime = -1; - private boolean mCaptive; - private CharSequence mVenueFriendlyName; - private @CaptivePortalDataSource int mVenueInfoUrlSource = CAPTIVE_PORTAL_DATA_SOURCE_OTHER; - private @CaptivePortalDataSource int mUserPortalUrlSource = - CAPTIVE_PORTAL_DATA_SOURCE_OTHER; - - /** - * Create an empty builder. - */ - public Builder() {} - - /** - * Create a builder copying all data from existing {@link CaptivePortalData}. - */ - public Builder(@Nullable CaptivePortalData data) { - if (data == null) return; - setRefreshTime(data.mRefreshTimeMillis) - .setUserPortalUrl(data.mUserPortalUrl, data.mUserPortalUrlSource) - .setVenueInfoUrl(data.mVenueInfoUrl, data.mVenueInfoUrlSource) - .setSessionExtendable(data.mIsSessionExtendable) - .setBytesRemaining(data.mByteLimit) - .setExpiryTime(data.mExpiryTimeMillis) - .setCaptive(data.mCaptive) - .setVenueFriendlyName(data.mVenueFriendlyName); - } - - /** - * Set the time at which data was last refreshed, as per {@link System#currentTimeMillis()}. - */ - @NonNull - public Builder setRefreshTime(long refreshTime) { - mRefreshTime = refreshTime; - return this; - } - - /** - * Set the URL to be used for users to login to the portal, if captive. - */ - @NonNull - public Builder setUserPortalUrl(@Nullable Uri userPortalUrl) { - return setUserPortalUrl(userPortalUrl, CAPTIVE_PORTAL_DATA_SOURCE_OTHER); - } - - /** - * Set the URL to be used for users to login to the portal, if captive, and the source of - * the data, see {@link CaptivePortalDataSource} - */ - @NonNull - public Builder setUserPortalUrl(@Nullable Uri userPortalUrl, - @CaptivePortalDataSource int source) { - mUserPortalUrl = userPortalUrl; - mUserPortalUrlSource = source; - return this; - } - - /** - * Set the URL that can be used by users to view information about the network venue. - */ - @NonNull - public Builder setVenueInfoUrl(@Nullable Uri venueInfoUrl) { - return setVenueInfoUrl(venueInfoUrl, CAPTIVE_PORTAL_DATA_SOURCE_OTHER); - } - - /** - * Set the URL that can be used by users to view information about the network venue, and - * the source of the data, see {@link CaptivePortalDataSource} - */ - @NonNull - public Builder setVenueInfoUrl(@Nullable Uri venueInfoUrl, - @CaptivePortalDataSource int source) { - mVenueInfoUrl = venueInfoUrl; - mVenueInfoUrlSource = source; - return this; - } - - /** - * Set whether the portal supports extending a user session on the portal URL page. - */ - @NonNull - public Builder setSessionExtendable(boolean sessionExtendable) { - mIsSessionExtendable = sessionExtendable; - return this; - } - - /** - * Set the number of bytes remaining on the network before the portal closes. - */ - @NonNull - public Builder setBytesRemaining(long bytesRemaining) { - mBytesRemaining = bytesRemaining; - return this; - } - - /** - * Set the time at the session will expire, as per {@link System#currentTimeMillis()}. - */ - @NonNull - public Builder setExpiryTime(long expiryTime) { - mExpiryTime = expiryTime; - return this; - } - - /** - * Set whether the network is captive (portal closed). - */ - @NonNull - public Builder setCaptive(boolean captive) { - mCaptive = captive; - return this; - } - - /** - * Set the venue friendly name. - */ - @NonNull - public Builder setVenueFriendlyName(@Nullable CharSequence venueFriendlyName) { - mVenueFriendlyName = venueFriendlyName; - return this; - } - - /** - * Create a new {@link CaptivePortalData}. - */ - @NonNull - public CaptivePortalData build() { - return new CaptivePortalData(mRefreshTime, mUserPortalUrl, mVenueInfoUrl, - mIsSessionExtendable, mBytesRemaining, mExpiryTime, mCaptive, - mVenueFriendlyName, mVenueInfoUrlSource, - mUserPortalUrlSource); - } - } - - /** - * Get the time at which data was last refreshed, as per {@link System#currentTimeMillis()}. - */ - public long getRefreshTimeMillis() { - return mRefreshTimeMillis; - } - - /** - * Get the URL to be used for users to login to the portal, or extend their session if - * {@link #isSessionExtendable()} is true. - */ - @Nullable - public Uri getUserPortalUrl() { - return mUserPortalUrl; - } - - /** - * Get the URL that can be used by users to view information about the network venue. - */ - @Nullable - public Uri getVenueInfoUrl() { - return mVenueInfoUrl; - } - - /** - * Indicates whether the user portal URL can be used to extend sessions, when the user is logged - * in and the session has a time or byte limit. - */ - public boolean isSessionExtendable() { - return mIsSessionExtendable; - } - - /** - * Get the remaining bytes on the captive portal session, at the time {@link CaptivePortalData} - * was refreshed. This may be different from the limit currently enforced by the portal. - * @return The byte limit, or -1 if not set. - */ - public long getByteLimit() { - return mByteLimit; - } - - /** - * Get the time at the session will expire, as per {@link System#currentTimeMillis()}. - * @return The expiry time, or -1 if unset. - */ - public long getExpiryTimeMillis() { - return mExpiryTimeMillis; - } - - /** - * Get whether the network is captive (portal closed). - */ - public boolean isCaptive() { - return mCaptive; - } - - /** - * Get the information source of the Venue URL - * @return The source that the Venue URL was obtained from - */ - public @CaptivePortalDataSource int getVenueInfoUrlSource() { - return mVenueInfoUrlSource; - } - - /** - * Get the information source of the user portal URL - * @return The source that the user portal URL was obtained from - */ - public @CaptivePortalDataSource int getUserPortalUrlSource() { - return mUserPortalUrlSource; - } - - /** - * Get the venue friendly name - */ - @Nullable - public CharSequence getVenueFriendlyName() { - return mVenueFriendlyName; - } - - @NonNull - public static final Creator CREATOR = new Creator() { - @Override - public CaptivePortalData createFromParcel(Parcel source) { - return new CaptivePortalData(source); - } - - @Override - public CaptivePortalData[] newArray(int size) { - return new CaptivePortalData[size]; - } - }; - - @Override - public int hashCode() { - return Objects.hash(mRefreshTimeMillis, mUserPortalUrl, mVenueInfoUrl, - mIsSessionExtendable, mByteLimit, mExpiryTimeMillis, mCaptive, mVenueFriendlyName, - mVenueInfoUrlSource, mUserPortalUrlSource); - } - - @Override - public boolean equals(@Nullable Object obj) { - if (!(obj instanceof CaptivePortalData)) return false; - final CaptivePortalData other = (CaptivePortalData) obj; - return mRefreshTimeMillis == other.mRefreshTimeMillis - && Objects.equals(mUserPortalUrl, other.mUserPortalUrl) - && Objects.equals(mVenueInfoUrl, other.mVenueInfoUrl) - && mIsSessionExtendable == other.mIsSessionExtendable - && mByteLimit == other.mByteLimit - && mExpiryTimeMillis == other.mExpiryTimeMillis - && mCaptive == other.mCaptive - && Objects.equals(mVenueFriendlyName, other.mVenueFriendlyName) - && mVenueInfoUrlSource == other.mVenueInfoUrlSource - && mUserPortalUrlSource == other.mUserPortalUrlSource; - } - - @Override - public String toString() { - return "CaptivePortalData {" - + "refreshTime: " + mRefreshTimeMillis - + ", userPortalUrl: " + mUserPortalUrl - + ", venueInfoUrl: " + mVenueInfoUrl - + ", isSessionExtendable: " + mIsSessionExtendable - + ", byteLimit: " + mByteLimit - + ", expiryTime: " + mExpiryTimeMillis - + ", captive: " + mCaptive - + ", venueFriendlyName: " + mVenueFriendlyName - + ", venueInfoUrlSource: " + mVenueInfoUrlSource - + ", userPortalUrlSource: " + mUserPortalUrlSource - + "}"; - } -} diff --git a/packages/Connectivity/framework/src/android/net/ConnectionInfo.aidl b/packages/Connectivity/framework/src/android/net/ConnectionInfo.aidl deleted file mode 100644 index 07faf8bbbed84..0000000000000 --- a/packages/Connectivity/framework/src/android/net/ConnectionInfo.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* -** -** Copyright (C) 2018 The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -package android.net; - -parcelable ConnectionInfo; diff --git a/packages/Connectivity/framework/src/android/net/ConnectionInfo.java b/packages/Connectivity/framework/src/android/net/ConnectionInfo.java deleted file mode 100644 index 4514a8484d96d..0000000000000 --- a/packages/Connectivity/framework/src/android/net/ConnectionInfo.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.os.Parcel; -import android.os.Parcelable; - -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.UnknownHostException; - -/** - * Describe a network connection including local and remote address/port of a connection and the - * transport protocol. - * - * @hide - */ -public final class ConnectionInfo implements Parcelable { - public final int protocol; - public final InetSocketAddress local; - public final InetSocketAddress remote; - - @Override - public int describeContents() { - return 0; - } - - public ConnectionInfo(int protocol, InetSocketAddress local, InetSocketAddress remote) { - this.protocol = protocol; - this.local = local; - this.remote = remote; - } - - @Override - public void writeToParcel(Parcel out, int flags) { - out.writeInt(protocol); - out.writeByteArray(local.getAddress().getAddress()); - out.writeInt(local.getPort()); - out.writeByteArray(remote.getAddress().getAddress()); - out.writeInt(remote.getPort()); - } - - public static final @android.annotation.NonNull Creator CREATOR = new Creator() { - public ConnectionInfo createFromParcel(Parcel in) { - int protocol = in.readInt(); - InetAddress localAddress; - try { - localAddress = InetAddress.getByAddress(in.createByteArray()); - } catch (UnknownHostException e) { - throw new IllegalArgumentException("Invalid InetAddress"); - } - int localPort = in.readInt(); - InetAddress remoteAddress; - try { - remoteAddress = InetAddress.getByAddress(in.createByteArray()); - } catch (UnknownHostException e) { - throw new IllegalArgumentException("Invalid InetAddress"); - } - int remotePort = in.readInt(); - InetSocketAddress local = new InetSocketAddress(localAddress, localPort); - InetSocketAddress remote = new InetSocketAddress(remoteAddress, remotePort); - return new ConnectionInfo(protocol, local, remote); - } - - public ConnectionInfo[] newArray(int size) { - return new ConnectionInfo[size]; - } - }; -} diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityAnnotations.java b/packages/Connectivity/framework/src/android/net/ConnectivityAnnotations.java deleted file mode 100644 index eb1faa0aa25c3..0000000000000 --- a/packages/Connectivity/framework/src/android/net/ConnectivityAnnotations.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.IntDef; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Type annotations for constants used in the connectivity API surface. - * - * The annotations are maintained in a separate class so that it can be built as - * a separate library that other modules can build against, as Typedef should not - * be exposed as SystemApi. - * - * @hide - */ -public final class ConnectivityAnnotations { - private ConnectivityAnnotations() {} - - @Retention(RetentionPolicy.SOURCE) - @IntDef(flag = true, value = { - ConnectivityManager.MULTIPATH_PREFERENCE_HANDOVER, - ConnectivityManager.MULTIPATH_PREFERENCE_RELIABILITY, - ConnectivityManager.MULTIPATH_PREFERENCE_PERFORMANCE, - }) - public @interface MultipathPreference {} - - @Retention(RetentionPolicy.SOURCE) - @IntDef(flag = false, value = { - ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED, - ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED, - ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED, - }) - public @interface RestrictBackgroundStatus {} -} diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityDiagnosticsManager.java b/packages/Connectivity/framework/src/android/net/ConnectivityDiagnosticsManager.java deleted file mode 100644 index dcc8a5eacd138..0000000000000 --- a/packages/Connectivity/framework/src/android/net/ConnectivityDiagnosticsManager.java +++ /dev/null @@ -1,778 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.StringDef; -import android.content.Context; -import android.os.Binder; -import android.os.Parcel; -import android.os.Parcelable; -import android.os.PersistableBundle; -import android.os.RemoteException; - -import com.android.internal.annotations.VisibleForTesting; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Executor; - -/** - * Class that provides utilities for collecting network connectivity diagnostics information. - * Connectivity information is made available through triggerable diagnostics tools and by listening - * to System validations. Some diagnostics information may be permissions-restricted. - * - *

ConnectivityDiagnosticsManager is intended for use by applications offering network - * connectivity on a user device. These tools will provide several mechanisms for these applications - * to be alerted to network conditions as well as diagnose potential network issues themselves. - * - *

The primary responsibilities of this class are to: - * - *

    - *
  • Allow permissioned applications to register and unregister callbacks for network event - * notifications - *
  • Invoke callbacks for network event notifications, including: - *
      - *
    • Network validations - *
    • Data stalls - *
    • Connectivity reports from applications - *
    - *
- */ -public class ConnectivityDiagnosticsManager { - /** @hide */ - @VisibleForTesting - public static final Map - sCallbacks = new ConcurrentHashMap<>(); - - private final Context mContext; - private final IConnectivityManager mService; - - /** @hide */ - public ConnectivityDiagnosticsManager(Context context, IConnectivityManager service) { - mContext = Objects.requireNonNull(context, "missing context"); - mService = Objects.requireNonNull(service, "missing IConnectivityManager"); - } - - /** @hide */ - @VisibleForTesting - public static boolean persistableBundleEquals( - @Nullable PersistableBundle a, @Nullable PersistableBundle b) { - if (a == b) return true; - if (a == null || b == null) return false; - if (!Objects.equals(a.keySet(), b.keySet())) return false; - for (String key : a.keySet()) { - if (!Objects.equals(a.get(key), b.get(key))) return false; - } - return true; - } - - /** Class that includes connectivity information for a specific Network at a specific time. */ - public static final class ConnectivityReport implements Parcelable { - /** - * The overall status of the network is that it is invalid; it neither provides - * connectivity nor has been exempted from validation. - */ - public static final int NETWORK_VALIDATION_RESULT_INVALID = 0; - - /** - * The overall status of the network is that it is valid, this may be because it provides - * full Internet access (all probes succeeded), or because other properties of the network - * caused probes not to be run. - */ - // TODO: link to INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID - public static final int NETWORK_VALIDATION_RESULT_VALID = 1; - - /** - * The overall status of the network is that it provides partial connectivity; some - * probed services succeeded but others failed. - */ - // TODO: link to INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL; - public static final int NETWORK_VALIDATION_RESULT_PARTIALLY_VALID = 2; - - /** - * Due to the properties of the network, validation was not performed. - */ - public static final int NETWORK_VALIDATION_RESULT_SKIPPED = 3; - - /** @hide */ - @IntDef( - prefix = {"NETWORK_VALIDATION_RESULT_"}, - value = { - NETWORK_VALIDATION_RESULT_INVALID, - NETWORK_VALIDATION_RESULT_VALID, - NETWORK_VALIDATION_RESULT_PARTIALLY_VALID, - NETWORK_VALIDATION_RESULT_SKIPPED - }) - @Retention(RetentionPolicy.SOURCE) - public @interface NetworkValidationResult {} - - /** - * The overall validation result for the Network being reported on. - * - *

The possible values for this key are: - * {@link #NETWORK_VALIDATION_RESULT_INVALID}, - * {@link #NETWORK_VALIDATION_RESULT_VALID}, - * {@link #NETWORK_VALIDATION_RESULT_PARTIALLY_VALID}, - * {@link #NETWORK_VALIDATION_RESULT_SKIPPED}. - * - * @see android.net.NetworkCapabilities#NET_CAPABILITY_VALIDATED - */ - @NetworkValidationResult - public static final String KEY_NETWORK_VALIDATION_RESULT = "networkValidationResult"; - - /** DNS probe. */ - // TODO: link to INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS - public static final int NETWORK_PROBE_DNS = 0x04; - - /** HTTP probe. */ - // TODO: link to INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTP - public static final int NETWORK_PROBE_HTTP = 0x08; - - /** HTTPS probe. */ - // TODO: link to INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTPS; - public static final int NETWORK_PROBE_HTTPS = 0x10; - - /** Captive portal fallback probe. */ - // TODO: link to INetworkMonitor.NETWORK_VALIDATION_FALLBACK - public static final int NETWORK_PROBE_FALLBACK = 0x20; - - /** Private DNS (DNS over TLS) probd. */ - // TODO: link to INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS - public static final int NETWORK_PROBE_PRIVATE_DNS = 0x40; - - /** @hide */ - @IntDef( - prefix = {"NETWORK_PROBE_"}, - value = { - NETWORK_PROBE_DNS, - NETWORK_PROBE_HTTP, - NETWORK_PROBE_HTTPS, - NETWORK_PROBE_FALLBACK, - NETWORK_PROBE_PRIVATE_DNS - }) - @Retention(RetentionPolicy.SOURCE) - public @interface NetworkProbe {} - - /** - * A bitmask of network validation probes that succeeded. - * - *

The possible bits values reported by this key are: - * {@link #NETWORK_PROBE_DNS}, - * {@link #NETWORK_PROBE_HTTP}, - * {@link #NETWORK_PROBE_HTTPS}, - * {@link #NETWORK_PROBE_FALLBACK}, - * {@link #NETWORK_PROBE_PRIVATE_DNS}. - */ - @NetworkProbe - public static final String KEY_NETWORK_PROBES_SUCCEEDED_BITMASK = - "networkProbesSucceeded"; - - /** - * A bitmask of network validation probes that were attempted. - * - *

These probes may have failed or may be incomplete at the time of this report. - * - *

The possible bits values reported by this key are: - * {@link #NETWORK_PROBE_DNS}, - * {@link #NETWORK_PROBE_HTTP}, - * {@link #NETWORK_PROBE_HTTPS}, - * {@link #NETWORK_PROBE_FALLBACK}, - * {@link #NETWORK_PROBE_PRIVATE_DNS}. - */ - @NetworkProbe - public static final String KEY_NETWORK_PROBES_ATTEMPTED_BITMASK = - "networkProbesAttempted"; - - /** @hide */ - @StringDef(prefix = {"KEY_"}, value = { - KEY_NETWORK_VALIDATION_RESULT, KEY_NETWORK_PROBES_SUCCEEDED_BITMASK, - KEY_NETWORK_PROBES_ATTEMPTED_BITMASK}) - @Retention(RetentionPolicy.SOURCE) - public @interface ConnectivityReportBundleKeys {} - - /** The Network for which this ConnectivityReport applied */ - @NonNull private final Network mNetwork; - - /** - * The timestamp for the report. The timestamp is taken from {@link - * System#currentTimeMillis}. - */ - private final long mReportTimestamp; - - /** LinkProperties available on the Network at the reported timestamp */ - @NonNull private final LinkProperties mLinkProperties; - - /** NetworkCapabilities available on the Network at the reported timestamp */ - @NonNull private final NetworkCapabilities mNetworkCapabilities; - - /** PersistableBundle that may contain additional info about the report */ - @NonNull private final PersistableBundle mAdditionalInfo; - - /** - * Constructor for ConnectivityReport. - * - *

Apps should obtain instances through {@link - * ConnectivityDiagnosticsCallback#onConnectivityReportAvailable} instead of instantiating - * their own instances (unless for testing purposes). - * - * @param network The Network for which this ConnectivityReport applies - * @param reportTimestamp The timestamp for the report - * @param linkProperties The LinkProperties available on network at reportTimestamp - * @param networkCapabilities The NetworkCapabilities available on network at - * reportTimestamp - * @param additionalInfo A PersistableBundle that may contain additional info about the - * report - */ - public ConnectivityReport( - @NonNull Network network, - long reportTimestamp, - @NonNull LinkProperties linkProperties, - @NonNull NetworkCapabilities networkCapabilities, - @NonNull PersistableBundle additionalInfo) { - mNetwork = network; - mReportTimestamp = reportTimestamp; - mLinkProperties = new LinkProperties(linkProperties); - mNetworkCapabilities = new NetworkCapabilities(networkCapabilities); - mAdditionalInfo = additionalInfo; - } - - /** - * Returns the Network for this ConnectivityReport. - * - * @return The Network for which this ConnectivityReport applied - */ - @NonNull - public Network getNetwork() { - return mNetwork; - } - - /** - * Returns the epoch timestamp (milliseconds) for when this report was taken. - * - * @return The timestamp for the report. Taken from {@link System#currentTimeMillis}. - */ - public long getReportTimestamp() { - return mReportTimestamp; - } - - /** - * Returns the LinkProperties available when this report was taken. - * - * @return LinkProperties available on the Network at the reported timestamp - */ - @NonNull - public LinkProperties getLinkProperties() { - return new LinkProperties(mLinkProperties); - } - - /** - * Returns the NetworkCapabilities when this report was taken. - * - * @return NetworkCapabilities available on the Network at the reported timestamp - */ - @NonNull - public NetworkCapabilities getNetworkCapabilities() { - return new NetworkCapabilities(mNetworkCapabilities); - } - - /** - * Returns a PersistableBundle with additional info for this report. - * - * @return PersistableBundle that may contain additional info about the report - */ - @NonNull - public PersistableBundle getAdditionalInfo() { - return new PersistableBundle(mAdditionalInfo); - } - - @Override - public boolean equals(@Nullable Object o) { - if (this == o) return true; - if (!(o instanceof ConnectivityReport)) return false; - final ConnectivityReport that = (ConnectivityReport) o; - - // PersistableBundle is optimized to avoid unparcelling data unless fields are - // referenced. Because of this, use {@link ConnectivityDiagnosticsManager#equals} over - // {@link PersistableBundle#kindofEquals}. - return mReportTimestamp == that.mReportTimestamp - && mNetwork.equals(that.mNetwork) - && mLinkProperties.equals(that.mLinkProperties) - && mNetworkCapabilities.equals(that.mNetworkCapabilities) - && persistableBundleEquals(mAdditionalInfo, that.mAdditionalInfo); - } - - @Override - public int hashCode() { - return Objects.hash( - mNetwork, - mReportTimestamp, - mLinkProperties, - mNetworkCapabilities, - mAdditionalInfo); - } - - /** {@inheritDoc} */ - @Override - public int describeContents() { - return 0; - } - - /** {@inheritDoc} */ - @Override - public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeParcelable(mNetwork, flags); - dest.writeLong(mReportTimestamp); - dest.writeParcelable(mLinkProperties, flags); - dest.writeParcelable(mNetworkCapabilities, flags); - dest.writeParcelable(mAdditionalInfo, flags); - } - - /** Implement the Parcelable interface */ - public static final @NonNull Creator CREATOR = - new Creator() { - public ConnectivityReport createFromParcel(Parcel in) { - return new ConnectivityReport( - in.readParcelable(null), - in.readLong(), - in.readParcelable(null), - in.readParcelable(null), - in.readParcelable(null)); - } - - public ConnectivityReport[] newArray(int size) { - return new ConnectivityReport[size]; - } - }; - } - - /** Class that includes information for a suspected data stall on a specific Network */ - public static final class DataStallReport implements Parcelable { - /** - * Indicates that the Data Stall was detected using DNS events. - */ - public static final int DETECTION_METHOD_DNS_EVENTS = 1; - - /** - * Indicates that the Data Stall was detected using TCP metrics. - */ - public static final int DETECTION_METHOD_TCP_METRICS = 2; - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef( - prefix = {"DETECTION_METHOD_"}, - value = {DETECTION_METHOD_DNS_EVENTS, DETECTION_METHOD_TCP_METRICS}) - public @interface DetectionMethod {} - - /** - * This key represents the period in milliseconds over which other included TCP metrics - * were measured. - * - *

This key will be included if the data stall detection method is - * {@link #DETECTION_METHOD_TCP_METRICS}. - * - *

This value is an int. - */ - public static final String KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS = - "tcpMetricsCollectionPeriodMillis"; - - /** - * This key represents the fail rate of TCP packets when the suspected data stall was - * detected. - * - *

This key will be included if the data stall detection method is - * {@link #DETECTION_METHOD_TCP_METRICS}. - * - *

This value is an int percentage between 0 and 100. - */ - public static final String KEY_TCP_PACKET_FAIL_RATE = "tcpPacketFailRate"; - - /** - * This key represents the consecutive number of DNS timeouts that have occurred. - * - *

The consecutive count will be reset any time a DNS response is received. - * - *

This key will be included if the data stall detection method is - * {@link #DETECTION_METHOD_DNS_EVENTS}. - * - *

This value is an int. - */ - public static final String KEY_DNS_CONSECUTIVE_TIMEOUTS = "dnsConsecutiveTimeouts"; - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @StringDef(prefix = {"KEY_"}, value = { - KEY_TCP_PACKET_FAIL_RATE, - KEY_DNS_CONSECUTIVE_TIMEOUTS - }) - public @interface DataStallReportBundleKeys {} - - /** The Network for which this DataStallReport applied */ - @NonNull private final Network mNetwork; - - /** - * The timestamp for the report. The timestamp is taken from {@link - * System#currentTimeMillis}. - */ - private long mReportTimestamp; - - /** A bitmask of the detection methods used to identify the suspected data stall */ - @DetectionMethod private final int mDetectionMethod; - - /** LinkProperties available on the Network at the reported timestamp */ - @NonNull private final LinkProperties mLinkProperties; - - /** NetworkCapabilities available on the Network at the reported timestamp */ - @NonNull private final NetworkCapabilities mNetworkCapabilities; - - /** PersistableBundle that may contain additional information on the suspected data stall */ - @NonNull private final PersistableBundle mStallDetails; - - /** - * Constructor for DataStallReport. - * - *

Apps should obtain instances through {@link - * ConnectivityDiagnosticsCallback#onDataStallSuspected} instead of instantiating their own - * instances (unless for testing purposes). - * - * @param network The Network for which this DataStallReport applies - * @param reportTimestamp The timestamp for the report - * @param detectionMethod The detection method used to identify this data stall - * @param linkProperties The LinkProperties available on network at reportTimestamp - * @param networkCapabilities The NetworkCapabilities available on network at - * reportTimestamp - * @param stallDetails A PersistableBundle that may contain additional info about the report - */ - public DataStallReport( - @NonNull Network network, - long reportTimestamp, - @DetectionMethod int detectionMethod, - @NonNull LinkProperties linkProperties, - @NonNull NetworkCapabilities networkCapabilities, - @NonNull PersistableBundle stallDetails) { - mNetwork = network; - mReportTimestamp = reportTimestamp; - mDetectionMethod = detectionMethod; - mLinkProperties = new LinkProperties(linkProperties); - mNetworkCapabilities = new NetworkCapabilities(networkCapabilities); - mStallDetails = stallDetails; - } - - /** - * Returns the Network for this DataStallReport. - * - * @return The Network for which this DataStallReport applied - */ - @NonNull - public Network getNetwork() { - return mNetwork; - } - - /** - * Returns the epoch timestamp (milliseconds) for when this report was taken. - * - * @return The timestamp for the report. Taken from {@link System#currentTimeMillis}. - */ - public long getReportTimestamp() { - return mReportTimestamp; - } - - /** - * Returns the bitmask of detection methods used to identify this suspected data stall. - * - * @return The bitmask of detection methods used to identify the suspected data stall - */ - public int getDetectionMethod() { - return mDetectionMethod; - } - - /** - * Returns the LinkProperties available when this report was taken. - * - * @return LinkProperties available on the Network at the reported timestamp - */ - @NonNull - public LinkProperties getLinkProperties() { - return new LinkProperties(mLinkProperties); - } - - /** - * Returns the NetworkCapabilities when this report was taken. - * - * @return NetworkCapabilities available on the Network at the reported timestamp - */ - @NonNull - public NetworkCapabilities getNetworkCapabilities() { - return new NetworkCapabilities(mNetworkCapabilities); - } - - /** - * Returns a PersistableBundle with additional info for this report. - * - *

Gets a bundle with details about the suspected data stall including information - * specific to the monitoring method that detected the data stall. - * - * @return PersistableBundle that may contain additional information on the suspected data - * stall - */ - @NonNull - public PersistableBundle getStallDetails() { - return new PersistableBundle(mStallDetails); - } - - @Override - public boolean equals(@Nullable Object o) { - if (this == o) return true; - if (!(o instanceof DataStallReport)) return false; - final DataStallReport that = (DataStallReport) o; - - // PersistableBundle is optimized to avoid unparcelling data unless fields are - // referenced. Because of this, use {@link ConnectivityDiagnosticsManager#equals} over - // {@link PersistableBundle#kindofEquals}. - return mReportTimestamp == that.mReportTimestamp - && mDetectionMethod == that.mDetectionMethod - && mNetwork.equals(that.mNetwork) - && mLinkProperties.equals(that.mLinkProperties) - && mNetworkCapabilities.equals(that.mNetworkCapabilities) - && persistableBundleEquals(mStallDetails, that.mStallDetails); - } - - @Override - public int hashCode() { - return Objects.hash( - mNetwork, - mReportTimestamp, - mDetectionMethod, - mLinkProperties, - mNetworkCapabilities, - mStallDetails); - } - - /** {@inheritDoc} */ - @Override - public int describeContents() { - return 0; - } - - /** {@inheritDoc} */ - @Override - public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeParcelable(mNetwork, flags); - dest.writeLong(mReportTimestamp); - dest.writeInt(mDetectionMethod); - dest.writeParcelable(mLinkProperties, flags); - dest.writeParcelable(mNetworkCapabilities, flags); - dest.writeParcelable(mStallDetails, flags); - } - - /** Implement the Parcelable interface */ - public static final @NonNull Creator CREATOR = - new Creator() { - public DataStallReport createFromParcel(Parcel in) { - return new DataStallReport( - in.readParcelable(null), - in.readLong(), - in.readInt(), - in.readParcelable(null), - in.readParcelable(null), - in.readParcelable(null)); - } - - public DataStallReport[] newArray(int size) { - return new DataStallReport[size]; - } - }; - } - - /** @hide */ - @VisibleForTesting - public static class ConnectivityDiagnosticsBinder - extends IConnectivityDiagnosticsCallback.Stub { - @NonNull private final ConnectivityDiagnosticsCallback mCb; - @NonNull private final Executor mExecutor; - - /** @hide */ - @VisibleForTesting - public ConnectivityDiagnosticsBinder( - @NonNull ConnectivityDiagnosticsCallback cb, @NonNull Executor executor) { - this.mCb = cb; - this.mExecutor = executor; - } - - /** @hide */ - @VisibleForTesting - public void onConnectivityReportAvailable(@NonNull ConnectivityReport report) { - final long token = Binder.clearCallingIdentity(); - try { - mExecutor.execute(() -> { - mCb.onConnectivityReportAvailable(report); - }); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - /** @hide */ - @VisibleForTesting - public void onDataStallSuspected(@NonNull DataStallReport report) { - final long token = Binder.clearCallingIdentity(); - try { - mExecutor.execute(() -> { - mCb.onDataStallSuspected(report); - }); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - /** @hide */ - @VisibleForTesting - public void onNetworkConnectivityReported( - @NonNull Network network, boolean hasConnectivity) { - final long token = Binder.clearCallingIdentity(); - try { - mExecutor.execute(() -> { - mCb.onNetworkConnectivityReported(network, hasConnectivity); - }); - } finally { - Binder.restoreCallingIdentity(token); - } - } - } - - /** - * Abstract base class for Connectivity Diagnostics callbacks. Used for notifications about - * network connectivity events. Must be extended by applications wanting notifications. - */ - public abstract static class ConnectivityDiagnosticsCallback { - /** - * Called when the platform completes a data connectivity check. This will also be invoked - * immediately upon registration for each network matching the request with the latest - * report, if a report has already been generated for that network. - * - *

The Network specified in the ConnectivityReport may not be active any more when this - * method is invoked. - * - * @param report The ConnectivityReport containing information about a connectivity check - */ - public void onConnectivityReportAvailable(@NonNull ConnectivityReport report) {} - - /** - * Called when the platform suspects a data stall on some Network. - * - *

The Network specified in the DataStallReport may not be active any more when this - * method is invoked. - * - * @param report The DataStallReport containing information about the suspected data stall - */ - public void onDataStallSuspected(@NonNull DataStallReport report) {} - - /** - * Called when any app reports connectivity to the System. - * - * @param network The Network for which connectivity has been reported - * @param hasConnectivity The connectivity reported to the System - */ - public void onNetworkConnectivityReported( - @NonNull Network network, boolean hasConnectivity) {} - } - - /** - * Registers a ConnectivityDiagnosticsCallback with the System. - * - *

Only apps that offer network connectivity to the user should be registering callbacks. - * These are the only apps whose callbacks will be invoked by the system. Apps considered to - * meet these conditions include: - * - *

    - *
  • Carrier apps with active subscriptions - *
  • Active VPNs - *
  • WiFi Suggesters - *
- * - *

Callbacks registered by apps not meeting the above criteria will not be invoked. - * - *

If a registering app loses its relevant permissions, any callbacks it registered will - * silently stop receiving callbacks. Note that registering apps must also have location - * permissions to receive callbacks as some Networks may be location-bound (such as WiFi - * networks). - * - *

Each register() call MUST use a ConnectivityDiagnosticsCallback instance that is - * not currently registered. If a ConnectivityDiagnosticsCallback instance is registered with - * multiple NetworkRequests, an IllegalArgumentException will be thrown. - * - *

To avoid performance issues due to apps leaking callbacks, the system will limit the - * number of outstanding requests to 100 per app (identified by their UID), shared with - * callbacks in {@link ConnectivityManager}. Registering a callback with this method will count - * toward this limit. If this limit is exceeded, an exception will be thrown. To avoid hitting - * this issue and to conserve resources, make sure to unregister the callbacks with - * {@link #unregisterConnectivityDiagnosticsCallback}. - * - * @param request The NetworkRequest that will be used to match with Networks for which - * callbacks will be fired - * @param e The Executor to be used for running the callback method invocations - * @param callback The ConnectivityDiagnosticsCallback that the caller wants registered with the - * System - * @throws IllegalArgumentException if the same callback instance is registered with multiple - * NetworkRequests - * @throws RuntimeException if the app already has too many callbacks registered. - */ - public void registerConnectivityDiagnosticsCallback( - @NonNull NetworkRequest request, - @NonNull Executor e, - @NonNull ConnectivityDiagnosticsCallback callback) { - final ConnectivityDiagnosticsBinder binder = new ConnectivityDiagnosticsBinder(callback, e); - if (sCallbacks.putIfAbsent(callback, binder) != null) { - throw new IllegalArgumentException("Callback is currently registered"); - } - - try { - mService.registerConnectivityDiagnosticsCallback( - binder, request, mContext.getOpPackageName()); - } catch (RemoteException exception) { - exception.rethrowFromSystemServer(); - } - } - - /** - * Unregisters a ConnectivityDiagnosticsCallback with the System. - * - *

If the given callback is not currently registered with the System, this operation will be - * a no-op. - * - * @param callback The ConnectivityDiagnosticsCallback to be unregistered from the System. - */ - public void unregisterConnectivityDiagnosticsCallback( - @NonNull ConnectivityDiagnosticsCallback callback) { - // unconditionally removing from sCallbacks prevents race conditions here, since remove() is - // atomic. - final ConnectivityDiagnosticsBinder binder = sCallbacks.remove(callback); - if (binder == null) return; - - try { - mService.unregisterConnectivityDiagnosticsCallback(binder); - } catch (RemoteException exception) { - exception.rethrowFromSystemServer(); - } - } -} diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityFrameworkInitializer.java b/packages/Connectivity/framework/src/android/net/ConnectivityFrameworkInitializer.java deleted file mode 100644 index a2e218dcbb4bc..0000000000000 --- a/packages/Connectivity/framework/src/android/net/ConnectivityFrameworkInitializer.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.SystemApi; -import android.app.SystemServiceRegistry; -import android.content.Context; - -/** - * Class for performing registration for all core connectivity services. - * - * @hide - */ -@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) -public final class ConnectivityFrameworkInitializer { - private ConnectivityFrameworkInitializer() {} - - /** - * Called by {@link SystemServiceRegistry}'s static initializer and registers all core - * connectivity services to {@link Context}, so that {@link Context#getSystemService} can - * return them. - * - * @throws IllegalStateException if this is called anywhere besides - * {@link SystemServiceRegistry}. - */ - public static void registerServiceWrappers() { - // registerContextAwareService will throw if this is called outside of SystemServiceRegistry - // initialization. - SystemServiceRegistry.registerContextAwareService( - Context.CONNECTIVITY_SERVICE, - ConnectivityManager.class, - (context, serviceBinder) -> { - IConnectivityManager icm = IConnectivityManager.Stub.asInterface(serviceBinder); - return new ConnectivityManager(context, icm); - } - ); - - SystemServiceRegistry.registerContextAwareService( - Context.CONNECTIVITY_DIAGNOSTICS_SERVICE, - ConnectivityDiagnosticsManager.class, - (context) -> { - final ConnectivityManager cm = context.getSystemService( - ConnectivityManager.class); - return cm.createDiagnosticsManager(); - } - ); - - SystemServiceRegistry.registerContextAwareService( - Context.TEST_NETWORK_SERVICE, - TestNetworkManager.class, - context -> { - final ConnectivityManager cm = context.getSystemService( - ConnectivityManager.class); - return cm.startOrGetTestNetworkManager(); - } - ); - - SystemServiceRegistry.registerContextAwareService( - DnsResolverServiceManager.DNS_RESOLVER_SERVICE, - DnsResolverServiceManager.class, - (context, serviceBinder) -> new DnsResolverServiceManager(serviceBinder) - ); - } -} diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java deleted file mode 100644 index 93455bc800877..0000000000000 --- a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java +++ /dev/null @@ -1,5459 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.net; - -import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; -import static android.net.NetworkRequest.Type.BACKGROUND_REQUEST; -import static android.net.NetworkRequest.Type.LISTEN; -import static android.net.NetworkRequest.Type.LISTEN_FOR_BEST; -import static android.net.NetworkRequest.Type.REQUEST; -import static android.net.NetworkRequest.Type.TRACK_DEFAULT; -import static android.net.NetworkRequest.Type.TRACK_SYSTEM_DEFAULT; -import static android.net.QosCallback.QosCallbackRegistrationException; - -import android.annotation.CallbackExecutor; -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.RequiresPermission; -import android.annotation.SdkConstant; -import android.annotation.SdkConstant.SdkConstantType; -import android.annotation.SuppressLint; -import android.annotation.SystemApi; -import android.annotation.SystemService; -import android.app.PendingIntent; -import android.app.admin.DevicePolicyManager; -import android.compat.annotation.UnsupportedAppUsage; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.net.ConnectivityAnnotations.MultipathPreference; -import android.net.ConnectivityAnnotations.RestrictBackgroundStatus; -import android.net.ConnectivityDiagnosticsManager.DataStallReport.DetectionMethod; -import android.net.IpSecManager.UdpEncapsulationSocket; -import android.net.SocketKeepalive.Callback; -import android.net.TetheringManager.StartTetheringCallback; -import android.net.TetheringManager.TetheringEventCallback; -import android.net.TetheringManager.TetheringRequest; -import android.net.wifi.WifiNetworkSuggestion; -import android.os.Binder; -import android.os.Build; -import android.os.Build.VERSION_CODES; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.os.Looper; -import android.os.Message; -import android.os.Messenger; -import android.os.ParcelFileDescriptor; -import android.os.PersistableBundle; -import android.os.Process; -import android.os.RemoteException; -import android.os.ResultReceiver; -import android.os.ServiceSpecificException; -import android.os.UserHandle; -import android.provider.Settings; -import android.telephony.SubscriptionManager; -import android.telephony.TelephonyManager; -import android.util.ArrayMap; -import android.util.Log; -import android.util.Range; -import android.util.SparseIntArray; - -import com.android.internal.annotations.GuardedBy; - -import libcore.net.event.NetworkEventDispatcher; - -import java.io.IOException; -import java.io.UncheckedIOException; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.net.DatagramSocket; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.RejectedExecutionException; - -/** - * Class that answers queries about the state of network connectivity. It also - * notifies applications when network connectivity changes. - *

- * The primary responsibilities of this class are to: - *

    - *
  1. Monitor network connections (Wi-Fi, GPRS, UMTS, etc.)
  2. - *
  3. Send broadcast intents when network connectivity changes
  4. - *
  5. Attempt to "fail over" to another network when connectivity to a network - * is lost
  6. - *
  7. Provide an API that allows applications to query the coarse-grained or fine-grained - * state of the available networks
  8. - *
  9. Provide an API that allows applications to request and select networks for their data - * traffic
  10. - *
- */ -@SystemService(Context.CONNECTIVITY_SERVICE) -public class ConnectivityManager { - private static final String TAG = "ConnectivityManager"; - private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); - - /** - * A change in network connectivity has occurred. A default connection has either - * been established or lost. The NetworkInfo for the affected network is - * sent as an extra; it should be consulted to see what kind of - * connectivity event occurred. - *

- * Apps targeting Android 7.0 (API level 24) and higher do not receive this - * broadcast if they declare the broadcast receiver in their manifest. Apps - * will still receive broadcasts if they register their - * {@link android.content.BroadcastReceiver} with - * {@link android.content.Context#registerReceiver Context.registerReceiver()} - * and that context is still valid. - *

- * If this is a connection that was the result of failing over from a - * disconnected network, then the FAILOVER_CONNECTION boolean extra is - * set to true. - *

- * For a loss of connectivity, if the connectivity manager is attempting - * to connect (or has already connected) to another network, the - * NetworkInfo for the new network is also passed as an extra. This lets - * any receivers of the broadcast know that they should not necessarily - * tell the user that no data traffic will be possible. Instead, the - * receiver should expect another broadcast soon, indicating either that - * the failover attempt succeeded (and so there is still overall data - * connectivity), or that the failover attempt failed, meaning that all - * connectivity has been lost. - *

- * For a disconnect event, the boolean extra EXTRA_NO_CONNECTIVITY - * is set to {@code true} if there are no connected networks at all. - * - * @deprecated apps should use the more versatile {@link #requestNetwork}, - * {@link #registerNetworkCallback} or {@link #registerDefaultNetworkCallback} - * functions instead for faster and more detailed updates about the network - * changes they care about. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - @Deprecated - public static final String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE"; - - /** - * The device has connected to a network that has presented a captive - * portal, which is blocking Internet connectivity. The user was presented - * with a notification that network sign in is required, - * and the user invoked the notification's action indicating they - * desire to sign in to the network. Apps handling this activity should - * facilitate signing in to the network. This action includes a - * {@link Network} typed extra called {@link #EXTRA_NETWORK} that represents - * the network presenting the captive portal; all communication with the - * captive portal must be done using this {@code Network} object. - *

- * This activity includes a {@link CaptivePortal} extra named - * {@link #EXTRA_CAPTIVE_PORTAL} that can be used to indicate different - * outcomes of the captive portal sign in to the system: - *

    - *
  • When the app handling this action believes the user has signed in to - * the network and the captive portal has been dismissed, the app should - * call {@link CaptivePortal#reportCaptivePortalDismissed} so the system can - * reevaluate the network. If reevaluation finds the network no longer - * subject to a captive portal, the network may become the default active - * data network.
  • - *
  • When the app handling this action believes the user explicitly wants - * to ignore the captive portal and the network, the app should call - * {@link CaptivePortal#ignoreNetwork}.
  • - *
- */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_CAPTIVE_PORTAL_SIGN_IN = "android.net.conn.CAPTIVE_PORTAL"; - - /** - * The lookup key for a {@link NetworkInfo} object. Retrieve with - * {@link android.content.Intent#getParcelableExtra(String)}. - * - * @deprecated The {@link NetworkInfo} object is deprecated, as many of its properties - * can't accurately represent modern network characteristics. - * Please obtain information about networks from the {@link NetworkCapabilities} - * or {@link LinkProperties} objects instead. - */ - @Deprecated - public static final String EXTRA_NETWORK_INFO = "networkInfo"; - - /** - * Network type which triggered a {@link #CONNECTIVITY_ACTION} broadcast. - * - * @see android.content.Intent#getIntExtra(String, int) - * @deprecated The network type is not rich enough to represent the characteristics - * of modern networks. Please use {@link NetworkCapabilities} instead, - * in particular the transports. - */ - @Deprecated - public static final String EXTRA_NETWORK_TYPE = "networkType"; - - /** - * The lookup key for a boolean that indicates whether a connect event - * is for a network to which the connectivity manager was failing over - * following a disconnect on another network. - * Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}. - * - * @deprecated See {@link NetworkInfo}. - */ - @Deprecated - public static final String EXTRA_IS_FAILOVER = "isFailover"; - /** - * The lookup key for a {@link NetworkInfo} object. This is supplied when - * there is another network that it may be possible to connect to. Retrieve with - * {@link android.content.Intent#getParcelableExtra(String)}. - * - * @deprecated See {@link NetworkInfo}. - */ - @Deprecated - public static final String EXTRA_OTHER_NETWORK_INFO = "otherNetwork"; - /** - * The lookup key for a boolean that indicates whether there is a - * complete lack of connectivity, i.e., no network is available. - * Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}. - */ - public static final String EXTRA_NO_CONNECTIVITY = "noConnectivity"; - /** - * The lookup key for a string that indicates why an attempt to connect - * to a network failed. The string has no particular structure. It is - * intended to be used in notifications presented to users. Retrieve - * it with {@link android.content.Intent#getStringExtra(String)}. - */ - public static final String EXTRA_REASON = "reason"; - /** - * The lookup key for a string that provides optionally supplied - * extra information about the network state. The information - * may be passed up from the lower networking layers, and its - * meaning may be specific to a particular network type. Retrieve - * it with {@link android.content.Intent#getStringExtra(String)}. - * - * @deprecated See {@link NetworkInfo#getExtraInfo()}. - */ - @Deprecated - public static final String EXTRA_EXTRA_INFO = "extraInfo"; - /** - * The lookup key for an int that provides information about - * our connection to the internet at large. 0 indicates no connection, - * 100 indicates a great connection. Retrieve it with - * {@link android.content.Intent#getIntExtra(String, int)}. - * {@hide} - */ - public static final String EXTRA_INET_CONDITION = "inetCondition"; - /** - * The lookup key for a {@link CaptivePortal} object included with the - * {@link #ACTION_CAPTIVE_PORTAL_SIGN_IN} intent. The {@code CaptivePortal} - * object can be used to either indicate to the system that the captive - * portal has been dismissed or that the user does not want to pursue - * signing in to captive portal. Retrieve it with - * {@link android.content.Intent#getParcelableExtra(String)}. - */ - public static final String EXTRA_CAPTIVE_PORTAL = "android.net.extra.CAPTIVE_PORTAL"; - - /** - * Key for passing a URL to the captive portal login activity. - */ - public static final String EXTRA_CAPTIVE_PORTAL_URL = "android.net.extra.CAPTIVE_PORTAL_URL"; - - /** - * Key for passing a {@link android.net.captiveportal.CaptivePortalProbeSpec} to the captive - * portal login activity. - * {@hide} - */ - @SystemApi - public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = - "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC"; - - /** - * Key for passing a user agent string to the captive portal login activity. - * {@hide} - */ - @SystemApi - public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = - "android.net.extra.CAPTIVE_PORTAL_USER_AGENT"; - - /** - * Broadcast action to indicate the change of data activity status - * (idle or active) on a network in a recent period. - * The network becomes active when data transmission is started, or - * idle if there is no data transmission for a period of time. - * {@hide} - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_DATA_ACTIVITY_CHANGE = - "android.net.conn.DATA_ACTIVITY_CHANGE"; - /** - * The lookup key for an enum that indicates the network device type on which this data activity - * change happens. - * {@hide} - */ - public static final String EXTRA_DEVICE_TYPE = "deviceType"; - /** - * The lookup key for a boolean that indicates the device is active or not. {@code true} means - * it is actively sending or receiving data and {@code false} means it is idle. - * {@hide} - */ - public static final String EXTRA_IS_ACTIVE = "isActive"; - /** - * The lookup key for a long that contains the timestamp (nanos) of the radio state change. - * {@hide} - */ - public static final String EXTRA_REALTIME_NS = "tsNanos"; - - /** - * Broadcast Action: The setting for background data usage has changed - * values. Use {@link #getBackgroundDataSetting()} to get the current value. - *

- * If an application uses the network in the background, it should listen - * for this broadcast and stop using the background data if the value is - * {@code false}. - *

- * - * @deprecated As of {@link VERSION_CODES#ICE_CREAM_SANDWICH}, availability - * of background data depends on several combined factors, and - * this broadcast is no longer sent. Instead, when background - * data is unavailable, {@link #getActiveNetworkInfo()} will now - * appear disconnected. During first boot after a platform - * upgrade, this broadcast will be sent once if - * {@link #getBackgroundDataSetting()} was {@code false} before - * the upgrade. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - @Deprecated - public static final String ACTION_BACKGROUND_DATA_SETTING_CHANGED = - "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED"; - - /** - * Broadcast Action: The network connection may not be good - * uses {@code ConnectivityManager.EXTRA_INET_CONDITION} and - * {@code ConnectivityManager.EXTRA_NETWORK_INFO} to specify - * the network and it's condition. - * @hide - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - @UnsupportedAppUsage - public static final String INET_CONDITION_ACTION = - "android.net.conn.INET_CONDITION_ACTION"; - - /** - * Broadcast Action: A tetherable connection has come or gone. - * Uses {@code ConnectivityManager.EXTRA_AVAILABLE_TETHER}, - * {@code ConnectivityManager.EXTRA_ACTIVE_LOCAL_ONLY}, - * {@code ConnectivityManager.EXTRA_ACTIVE_TETHER}, and - * {@code ConnectivityManager.EXTRA_ERRORED_TETHER} to indicate - * the current state of tethering. Each include a list of - * interface names in that state (may be empty). - * @hide - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public static final String ACTION_TETHER_STATE_CHANGED = - TetheringManager.ACTION_TETHER_STATE_CHANGED; - - /** - * @hide - * gives a String[] listing all the interfaces configured for - * tethering and currently available for tethering. - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public static final String EXTRA_AVAILABLE_TETHER = TetheringManager.EXTRA_AVAILABLE_TETHER; - - /** - * @hide - * gives a String[] listing all the interfaces currently in local-only - * mode (ie, has DHCPv4+IPv6-ULA support and no packet forwarding) - */ - public static final String EXTRA_ACTIVE_LOCAL_ONLY = TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY; - - /** - * @hide - * gives a String[] listing all the interfaces currently tethered - * (ie, has DHCPv4 support and packets potentially forwarded/NATed) - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public static final String EXTRA_ACTIVE_TETHER = TetheringManager.EXTRA_ACTIVE_TETHER; - - /** - * @hide - * gives a String[] listing all the interfaces we tried to tether and - * failed. Use {@link #getLastTetherError} to find the error code - * for any interfaces listed here. - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public static final String EXTRA_ERRORED_TETHER = TetheringManager.EXTRA_ERRORED_TETHER; - - /** - * Broadcast Action: The captive portal tracker has finished its test. - * Sent only while running Setup Wizard, in lieu of showing a user - * notification. - * @hide - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_CAPTIVE_PORTAL_TEST_COMPLETED = - "android.net.conn.CAPTIVE_PORTAL_TEST_COMPLETED"; - /** - * The lookup key for a boolean that indicates whether a captive portal was detected. - * Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}. - * @hide - */ - public static final String EXTRA_IS_CAPTIVE_PORTAL = "captivePortal"; - - /** - * Action used to display a dialog that asks the user whether to connect to a network that is - * not validated. This intent is used to start the dialog in settings via startActivity. - * - * This action includes a {@link Network} typed extra which is called - * {@link ConnectivityManager#EXTRA_NETWORK} that represents the network which is unvalidated. - * - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - public static final String ACTION_PROMPT_UNVALIDATED = "android.net.action.PROMPT_UNVALIDATED"; - - /** - * Action used to display a dialog that asks the user whether to avoid a network that is no - * longer validated. This intent is used to start the dialog in settings via startActivity. - * - * This action includes a {@link Network} typed extra which is called - * {@link ConnectivityManager#EXTRA_NETWORK} that represents the network which is no longer - * validated. - * - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - public static final String ACTION_PROMPT_LOST_VALIDATION = - "android.net.action.PROMPT_LOST_VALIDATION"; - - /** - * Action used to display a dialog that asks the user whether to stay connected to a network - * that has not validated. This intent is used to start the dialog in settings via - * startActivity. - * - * This action includes a {@link Network} typed extra which is called - * {@link ConnectivityManager#EXTRA_NETWORK} that represents the network which has partial - * connectivity. - * - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - public static final String ACTION_PROMPT_PARTIAL_CONNECTIVITY = - "android.net.action.PROMPT_PARTIAL_CONNECTIVITY"; - - /** - * Clear DNS Cache Action: This is broadcast when networks have changed and old - * DNS entries should be cleared. - * @hide - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public static final String ACTION_CLEAR_DNS_CACHE = "android.net.action.CLEAR_DNS_CACHE"; - - /** - * Invalid tethering type. - * @see #startTethering(int, boolean, OnStartTetheringCallback) - * @hide - */ - public static final int TETHERING_INVALID = TetheringManager.TETHERING_INVALID; - - /** - * Wifi tethering type. - * @see #startTethering(int, boolean, OnStartTetheringCallback) - * @hide - */ - @SystemApi - public static final int TETHERING_WIFI = 0; - - /** - * USB tethering type. - * @see #startTethering(int, boolean, OnStartTetheringCallback) - * @hide - */ - @SystemApi - public static final int TETHERING_USB = 1; - - /** - * Bluetooth tethering type. - * @see #startTethering(int, boolean, OnStartTetheringCallback) - * @hide - */ - @SystemApi - public static final int TETHERING_BLUETOOTH = 2; - - /** - * Wifi P2p tethering type. - * Wifi P2p tethering is set through events automatically, and don't - * need to start from #startTethering(int, boolean, OnStartTetheringCallback). - * @hide - */ - public static final int TETHERING_WIFI_P2P = TetheringManager.TETHERING_WIFI_P2P; - - /** - * Extra used for communicating with the TetherService. Includes the type of tethering to - * enable if any. - * @hide - */ - public static final String EXTRA_ADD_TETHER_TYPE = TetheringConstants.EXTRA_ADD_TETHER_TYPE; - - /** - * Extra used for communicating with the TetherService. Includes the type of tethering for - * which to cancel provisioning. - * @hide - */ - public static final String EXTRA_REM_TETHER_TYPE = TetheringConstants.EXTRA_REM_TETHER_TYPE; - - /** - * Extra used for communicating with the TetherService. True to schedule a recheck of tether - * provisioning. - * @hide - */ - public static final String EXTRA_SET_ALARM = TetheringConstants.EXTRA_SET_ALARM; - - /** - * Tells the TetherService to run a provision check now. - * @hide - */ - public static final String EXTRA_RUN_PROVISION = TetheringConstants.EXTRA_RUN_PROVISION; - - /** - * Extra used for communicating with the TetherService. Contains the {@link ResultReceiver} - * which will receive provisioning results. Can be left empty. - * @hide - */ - public static final String EXTRA_PROVISION_CALLBACK = - TetheringConstants.EXTRA_PROVISION_CALLBACK; - - /** - * The absence of a connection type. - * @hide - */ - @SystemApi - public static final int TYPE_NONE = -1; - - /** - * A Mobile data connection. Devices may support more than one. - * - * @deprecated Applications should instead use {@link NetworkCapabilities#hasTransport} or - * {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request an - * appropriate network. {@see NetworkCapabilities} for supported transports. - */ - @Deprecated - public static final int TYPE_MOBILE = 0; - - /** - * A WIFI data connection. Devices may support more than one. - * - * @deprecated Applications should instead use {@link NetworkCapabilities#hasTransport} or - * {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request an - * appropriate network. {@see NetworkCapabilities} for supported transports. - */ - @Deprecated - public static final int TYPE_WIFI = 1; - - /** - * An MMS-specific Mobile data connection. This network type may use the - * same network interface as {@link #TYPE_MOBILE} or it may use a different - * one. This is used by applications needing to talk to the carrier's - * Multimedia Messaging Service servers. - * - * @deprecated Applications should instead use {@link NetworkCapabilities#hasCapability} or - * {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request a network that - * provides the {@link NetworkCapabilities#NET_CAPABILITY_MMS} capability. - */ - @Deprecated - public static final int TYPE_MOBILE_MMS = 2; - - /** - * A SUPL-specific Mobile data connection. This network type may use the - * same network interface as {@link #TYPE_MOBILE} or it may use a different - * one. This is used by applications needing to talk to the carrier's - * Secure User Plane Location servers for help locating the device. - * - * @deprecated Applications should instead use {@link NetworkCapabilities#hasCapability} or - * {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request a network that - * provides the {@link NetworkCapabilities#NET_CAPABILITY_SUPL} capability. - */ - @Deprecated - public static final int TYPE_MOBILE_SUPL = 3; - - /** - * A DUN-specific Mobile data connection. This network type may use the - * same network interface as {@link #TYPE_MOBILE} or it may use a different - * one. This is sometimes by the system when setting up an upstream connection - * for tethering so that the carrier is aware of DUN traffic. - * - * @deprecated Applications should instead use {@link NetworkCapabilities#hasCapability} or - * {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request a network that - * provides the {@link NetworkCapabilities#NET_CAPABILITY_DUN} capability. - */ - @Deprecated - public static final int TYPE_MOBILE_DUN = 4; - - /** - * A High Priority Mobile data connection. This network type uses the - * same network interface as {@link #TYPE_MOBILE} but the routing setup - * is different. - * - * @deprecated Applications should instead use {@link NetworkCapabilities#hasTransport} or - * {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request an - * appropriate network. {@see NetworkCapabilities} for supported transports. - */ - @Deprecated - public static final int TYPE_MOBILE_HIPRI = 5; - - /** - * A WiMAX data connection. - * - * @deprecated Applications should instead use {@link NetworkCapabilities#hasTransport} or - * {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request an - * appropriate network. {@see NetworkCapabilities} for supported transports. - */ - @Deprecated - public static final int TYPE_WIMAX = 6; - - /** - * A Bluetooth data connection. - * - * @deprecated Applications should instead use {@link NetworkCapabilities#hasTransport} or - * {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request an - * appropriate network. {@see NetworkCapabilities} for supported transports. - */ - @Deprecated - public static final int TYPE_BLUETOOTH = 7; - - /** - * Fake data connection. This should not be used on shipping devices. - * @deprecated This is not used any more. - */ - @Deprecated - public static final int TYPE_DUMMY = 8; - - /** - * An Ethernet data connection. - * - * @deprecated Applications should instead use {@link NetworkCapabilities#hasTransport} or - * {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request an - * appropriate network. {@see NetworkCapabilities} for supported transports. - */ - @Deprecated - public static final int TYPE_ETHERNET = 9; - - /** - * Over the air Administration. - * @deprecated Use {@link NetworkCapabilities} instead. - * {@hide} - */ - @Deprecated - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562) - public static final int TYPE_MOBILE_FOTA = 10; - - /** - * IP Multimedia Subsystem. - * @deprecated Use {@link NetworkCapabilities#NET_CAPABILITY_IMS} instead. - * {@hide} - */ - @Deprecated - @UnsupportedAppUsage - public static final int TYPE_MOBILE_IMS = 11; - - /** - * Carrier Branded Services. - * @deprecated Use {@link NetworkCapabilities#NET_CAPABILITY_CBS} instead. - * {@hide} - */ - @Deprecated - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562) - public static final int TYPE_MOBILE_CBS = 12; - - /** - * A Wi-Fi p2p connection. Only requesting processes will have access to - * the peers connected. - * @deprecated Use {@link NetworkCapabilities#NET_CAPABILITY_WIFI_P2P} instead. - * {@hide} - */ - @Deprecated - @SystemApi - public static final int TYPE_WIFI_P2P = 13; - - /** - * The network to use for initially attaching to the network - * @deprecated Use {@link NetworkCapabilities#NET_CAPABILITY_IA} instead. - * {@hide} - */ - @Deprecated - @UnsupportedAppUsage - public static final int TYPE_MOBILE_IA = 14; - - /** - * Emergency PDN connection for emergency services. This - * may include IMS and MMS in emergency situations. - * @deprecated Use {@link NetworkCapabilities#NET_CAPABILITY_EIMS} instead. - * {@hide} - */ - @Deprecated - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562) - public static final int TYPE_MOBILE_EMERGENCY = 15; - - /** - * The network that uses proxy to achieve connectivity. - * @deprecated Use {@link NetworkCapabilities} instead. - * {@hide} - */ - @Deprecated - @SystemApi - public static final int TYPE_PROXY = 16; - - /** - * A virtual network using one or more native bearers. - * It may or may not be providing security services. - * @deprecated Applications should use {@link NetworkCapabilities#TRANSPORT_VPN} instead. - */ - @Deprecated - public static final int TYPE_VPN = 17; - - /** - * A network that is exclusively meant to be used for testing - * - * @deprecated Use {@link NetworkCapabilities} instead. - * @hide - */ - @Deprecated - public static final int TYPE_TEST = 18; // TODO: Remove this once NetworkTypes are unused. - - /** - * @deprecated Use {@link NetworkCapabilities} instead. - * @hide - */ - @Deprecated - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = { "TYPE_" }, value = { - TYPE_NONE, - TYPE_MOBILE, - TYPE_WIFI, - TYPE_MOBILE_MMS, - TYPE_MOBILE_SUPL, - TYPE_MOBILE_DUN, - TYPE_MOBILE_HIPRI, - TYPE_WIMAX, - TYPE_BLUETOOTH, - TYPE_DUMMY, - TYPE_ETHERNET, - TYPE_MOBILE_FOTA, - TYPE_MOBILE_IMS, - TYPE_MOBILE_CBS, - TYPE_WIFI_P2P, - TYPE_MOBILE_IA, - TYPE_MOBILE_EMERGENCY, - TYPE_PROXY, - TYPE_VPN, - TYPE_TEST - }) - public @interface LegacyNetworkType {} - - // Deprecated constants for return values of startUsingNetworkFeature. They used to live - // in com.android.internal.telephony.PhoneConstants until they were made inaccessible. - private static final int DEPRECATED_PHONE_CONSTANT_APN_ALREADY_ACTIVE = 0; - private static final int DEPRECATED_PHONE_CONSTANT_APN_REQUEST_STARTED = 1; - private static final int DEPRECATED_PHONE_CONSTANT_APN_REQUEST_FAILED = 3; - - /** {@hide} */ - public static final int MAX_RADIO_TYPE = TYPE_TEST; - - /** {@hide} */ - public static final int MAX_NETWORK_TYPE = TYPE_TEST; - - private static final int MIN_NETWORK_TYPE = TYPE_MOBILE; - - /** - * If you want to set the default network preference,you can directly - * change the networkAttributes array in framework's config.xml. - * - * @deprecated Since we support so many more networks now, the single - * network default network preference can't really express - * the hierarchy. Instead, the default is defined by the - * networkAttributes in config.xml. You can determine - * the current value by calling {@link #getNetworkPreference()} - * from an App. - */ - @Deprecated - public static final int DEFAULT_NETWORK_PREFERENCE = TYPE_WIFI; - - /** - * @hide - */ - public static final int REQUEST_ID_UNSET = 0; - - /** - * Static unique request used as a tombstone for NetworkCallbacks that have been unregistered. - * This allows to distinguish when unregistering NetworkCallbacks those that were never - * registered from those that were already unregistered. - * @hide - */ - private static final NetworkRequest ALREADY_UNREGISTERED = - new NetworkRequest.Builder().clearCapabilities().build(); - - /** - * A NetID indicating no Network is selected. - * Keep in sync with bionic/libc/dns/include/resolv_netid.h - * @hide - */ - public static final int NETID_UNSET = 0; - - /** - * Flag to indicate that an app is not subject to any restrictions that could result in its - * network access blocked. - * - * @hide - */ - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public static final int BLOCKED_REASON_NONE = 0; - - /** - * Flag to indicate that an app is subject to Battery saver restrictions that would - * result in its network access being blocked. - * - * @hide - */ - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public static final int BLOCKED_REASON_BATTERY_SAVER = 1 << 0; - - /** - * Flag to indicate that an app is subject to Doze restrictions that would - * result in its network access being blocked. - * - * @hide - */ - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public static final int BLOCKED_REASON_DOZE = 1 << 1; - - /** - * Flag to indicate that an app is subject to App Standby restrictions that would - * result in its network access being blocked. - * - * @hide - */ - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public static final int BLOCKED_REASON_APP_STANDBY = 1 << 2; - - /** - * Flag to indicate that an app is subject to Restricted mode restrictions that would - * result in its network access being blocked. - * - * @hide - */ - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public static final int BLOCKED_REASON_RESTRICTED_MODE = 1 << 3; - - /** - * Flag to indicate that an app is blocked because it is subject to an always-on VPN but the VPN - * is not currently connected. - * - * @see DevicePolicyManager#setAlwaysOnVpnPackage(ComponentName, String, boolean) - * - * @hide - */ - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public static final int BLOCKED_REASON_LOCKDOWN_VPN = 1 << 4; - - /** - * Flag to indicate that an app is subject to Data saver restrictions that would - * result in its metered network access being blocked. - * - * @hide - */ - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public static final int BLOCKED_METERED_REASON_DATA_SAVER = 1 << 16; - - /** - * Flag to indicate that an app is subject to user restrictions that would - * result in its metered network access being blocked. - * - * @hide - */ - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public static final int BLOCKED_METERED_REASON_USER_RESTRICTED = 1 << 17; - - /** - * Flag to indicate that an app is subject to Device admin restrictions that would - * result in its metered network access being blocked. - * - * @hide - */ - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public static final int BLOCKED_METERED_REASON_ADMIN_DISABLED = 1 << 18; - - /** - * @hide - */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(flag = true, prefix = {"BLOCKED_"}, value = { - BLOCKED_REASON_NONE, - BLOCKED_REASON_BATTERY_SAVER, - BLOCKED_REASON_DOZE, - BLOCKED_REASON_APP_STANDBY, - BLOCKED_REASON_RESTRICTED_MODE, - BLOCKED_REASON_LOCKDOWN_VPN, - BLOCKED_METERED_REASON_DATA_SAVER, - BLOCKED_METERED_REASON_USER_RESTRICTED, - BLOCKED_METERED_REASON_ADMIN_DISABLED, - }) - public @interface BlockedReason {} - - /** - * Set of blocked reasons that are only applicable on metered networks. - * - * @hide - */ - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public static final int BLOCKED_METERED_REASON_MASK = 0xffff0000; - - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562) - private final IConnectivityManager mService; - - /** - * A kludge to facilitate static access where a Context pointer isn't available, like in the - * case of the static set/getProcessDefaultNetwork methods and from the Network class. - * TODO: Remove this after deprecating the static methods in favor of non-static methods or - * methods that take a Context argument. - */ - private static ConnectivityManager sInstance; - - private final Context mContext; - - private final TetheringManager mTetheringManager; - - /** - * Tests if a given integer represents a valid network type. - * @param networkType the type to be tested - * @return a boolean. {@code true} if the type is valid, else {@code false} - * @deprecated All APIs accepting a network type are deprecated. There should be no need to - * validate a network type. - */ - @Deprecated - public static boolean isNetworkTypeValid(int networkType) { - return MIN_NETWORK_TYPE <= networkType && networkType <= MAX_NETWORK_TYPE; - } - - /** - * Returns a non-localized string representing a given network type. - * ONLY used for debugging output. - * @param type the type needing naming - * @return a String for the given type, or a string version of the type ("87") - * if no name is known. - * @deprecated Types are deprecated. Use {@link NetworkCapabilities} instead. - * {@hide} - */ - @Deprecated - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public static String getNetworkTypeName(int type) { - switch (type) { - case TYPE_NONE: - return "NONE"; - case TYPE_MOBILE: - return "MOBILE"; - case TYPE_WIFI: - return "WIFI"; - case TYPE_MOBILE_MMS: - return "MOBILE_MMS"; - case TYPE_MOBILE_SUPL: - return "MOBILE_SUPL"; - case TYPE_MOBILE_DUN: - return "MOBILE_DUN"; - case TYPE_MOBILE_HIPRI: - return "MOBILE_HIPRI"; - case TYPE_WIMAX: - return "WIMAX"; - case TYPE_BLUETOOTH: - return "BLUETOOTH"; - case TYPE_DUMMY: - return "DUMMY"; - case TYPE_ETHERNET: - return "ETHERNET"; - case TYPE_MOBILE_FOTA: - return "MOBILE_FOTA"; - case TYPE_MOBILE_IMS: - return "MOBILE_IMS"; - case TYPE_MOBILE_CBS: - return "MOBILE_CBS"; - case TYPE_WIFI_P2P: - return "WIFI_P2P"; - case TYPE_MOBILE_IA: - return "MOBILE_IA"; - case TYPE_MOBILE_EMERGENCY: - return "MOBILE_EMERGENCY"; - case TYPE_PROXY: - return "PROXY"; - case TYPE_VPN: - return "VPN"; - default: - return Integer.toString(type); - } - } - - /** - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - public void systemReady() { - try { - mService.systemReady(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Checks if a given type uses the cellular data connection. - * This should be replaced in the future by a network property. - * @param networkType the type to check - * @return a boolean - {@code true} if uses cellular network, else {@code false} - * @deprecated Types are deprecated. Use {@link NetworkCapabilities} instead. - * {@hide} - */ - @Deprecated - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562) - public static boolean isNetworkTypeMobile(int networkType) { - switch (networkType) { - case TYPE_MOBILE: - case TYPE_MOBILE_MMS: - case TYPE_MOBILE_SUPL: - case TYPE_MOBILE_DUN: - case TYPE_MOBILE_HIPRI: - case TYPE_MOBILE_FOTA: - case TYPE_MOBILE_IMS: - case TYPE_MOBILE_CBS: - case TYPE_MOBILE_IA: - case TYPE_MOBILE_EMERGENCY: - return true; - default: - return false; - } - } - - /** - * Checks if the given network type is backed by a Wi-Fi radio. - * - * @deprecated Types are deprecated. Use {@link NetworkCapabilities} instead. - * @hide - */ - @Deprecated - public static boolean isNetworkTypeWifi(int networkType) { - switch (networkType) { - case TYPE_WIFI: - case TYPE_WIFI_P2P: - return true; - default: - return false; - } - } - - /** - * Preference for {@link #setNetworkPreferenceForUser(UserHandle, int, Executor, Runnable)}. - * Specify that the traffic for this user should by follow the default rules. - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - public static final int PROFILE_NETWORK_PREFERENCE_DEFAULT = 0; - - /** - * Preference for {@link #setNetworkPreferenceForUser(UserHandle, int, Executor, Runnable)}. - * Specify that the traffic for this user should by default go on a network with - * {@link NetworkCapabilities#NET_CAPABILITY_ENTERPRISE}, and on the system default network - * if no such network is available. - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - public static final int PROFILE_NETWORK_PREFERENCE_ENTERPRISE = 1; - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(value = { - PROFILE_NETWORK_PREFERENCE_DEFAULT, - PROFILE_NETWORK_PREFERENCE_ENTERPRISE - }) - public @interface ProfileNetworkPreference { - } - - /** - * Specifies the preferred network type. When the device has more - * than one type available the preferred network type will be used. - * - * @param preference the network type to prefer over all others. It is - * unspecified what happens to the old preferred network in the - * overall ordering. - * @deprecated Functionality has been removed as it no longer makes sense, - * with many more than two networks - we'd need an array to express - * preference. Instead we use dynamic network properties of - * the networks to describe their precedence. - */ - @Deprecated - public void setNetworkPreference(int preference) { - } - - /** - * Retrieves the current preferred network type. - * - * @return an integer representing the preferred network type - * - * @deprecated Functionality has been removed as it no longer makes sense, - * with many more than two networks - we'd need an array to express - * preference. Instead we use dynamic network properties of - * the networks to describe their precedence. - */ - @Deprecated - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - public int getNetworkPreference() { - return TYPE_NONE; - } - - /** - * Returns details about the currently active default data network. When - * connected, this network is the default route for outgoing connections. - * You should always check {@link NetworkInfo#isConnected()} before initiating - * network traffic. This may return {@code null} when there is no default - * network. - * Note that if the default network is a VPN, this method will return the - * NetworkInfo for one of its underlying networks instead, or null if the - * VPN agent did not specify any. Apps interested in learning about VPNs - * should use {@link #getNetworkInfo(android.net.Network)} instead. - * - * @return a {@link NetworkInfo} object for the current default network - * or {@code null} if no default network is currently active - * @deprecated See {@link NetworkInfo}. - */ - @Deprecated - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - @Nullable - public NetworkInfo getActiveNetworkInfo() { - try { - return mService.getActiveNetworkInfo(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Returns a {@link Network} object corresponding to the currently active - * default data network. In the event that the current active default data - * network disconnects, the returned {@code Network} object will no longer - * be usable. This will return {@code null} when there is no default - * network. - * - * @return a {@link Network} object for the current default network or - * {@code null} if no default network is currently active - */ - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - @Nullable - public Network getActiveNetwork() { - try { - return mService.getActiveNetwork(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Returns a {@link Network} object corresponding to the currently active - * default data network for a specific UID. In the event that the default data - * network disconnects, the returned {@code Network} object will no longer - * be usable. This will return {@code null} when there is no default - * network for the UID. - * - * @return a {@link Network} object for the current default network for the - * given UID or {@code null} if no default network is currently active - * - * @hide - */ - @RequiresPermission(android.Manifest.permission.NETWORK_STACK) - @Nullable - public Network getActiveNetworkForUid(int uid) { - return getActiveNetworkForUid(uid, false); - } - - /** {@hide} */ - public Network getActiveNetworkForUid(int uid, boolean ignoreBlocked) { - try { - return mService.getActiveNetworkForUid(uid, ignoreBlocked); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Adds or removes a requirement for given UID ranges to use the VPN. - * - * If set to {@code true}, informs the system that the UIDs in the specified ranges must not - * have any connectivity except if a VPN is connected and applies to the UIDs, or if the UIDs - * otherwise have permission to bypass the VPN (e.g., because they have the - * {@link android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS} permission, or when - * using a socket protected by a method such as {@link VpnService#protect(DatagramSocket)}. If - * set to {@code false}, a previously-added restriction is removed. - *

- * Each of the UID ranges specified by this method is added and removed as is, and no processing - * is performed on the ranges to de-duplicate, merge, split, or intersect them. In order to - * remove a previously-added range, the exact range must be removed as is. - *

- * The changes are applied asynchronously and may not have been applied by the time the method - * returns. Apps will be notified about any changes that apply to them via - * {@link NetworkCallback#onBlockedStatusChanged} callbacks called after the changes take - * effect. - *

- * This method should be called only by the VPN code. - * - * @param ranges the UID ranges to restrict - * @param requireVpn whether the specified UID ranges must use a VPN - * - * @hide - */ - @RequiresPermission(anyOf = { - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, - android.Manifest.permission.NETWORK_STACK, - android.Manifest.permission.NETWORK_SETTINGS}) - @SystemApi(client = MODULE_LIBRARIES) - public void setRequireVpnForUids(boolean requireVpn, - @NonNull Collection> ranges) { - Objects.requireNonNull(ranges); - // The Range class is not parcelable. Convert to UidRange, which is what is used internally. - // This method is not necessarily expected to be used outside the system server, so - // parceling may not be necessary, but it could be used out-of-process, e.g., by the network - // stack process, or by tests. - UidRange[] rangesArray = new UidRange[ranges.size()]; - int index = 0; - for (Range range : ranges) { - rangesArray[index++] = new UidRange(range.getLower(), range.getUpper()); - } - try { - mService.setRequireVpnForUids(requireVpn, rangesArray); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Informs ConnectivityService of whether the legacy lockdown VPN, as implemented by - * LockdownVpnTracker, is in use. This is deprecated for new devices starting from Android 12 - * but is still supported for backwards compatibility. - *

- * This type of VPN is assumed always to use the system default network, and must always declare - * exactly one underlying network, which is the network that was the default when the VPN - * connected. - *

- * Calling this method with {@code true} enables legacy behaviour, specifically: - *

    - *
  • Any VPN that applies to userId 0 behaves specially with respect to deprecated - * {@link #CONNECTIVITY_ACTION} broadcasts. Any such broadcasts will have the state in the - * {@link #EXTRA_NETWORK_INFO} replaced by state of the VPN network. Also, any time the VPN - * connects, a {@link #CONNECTIVITY_ACTION} broadcast will be sent for the network - * underlying the VPN.
  • - *
  • Deprecated APIs that return {@link NetworkInfo} objects will have their state - * similarly replaced by the VPN network state.
  • - *
  • Information on current network interfaces passed to NetworkStatsService will not - * include any VPN interfaces.
  • - *
- * - * @param enabled whether legacy lockdown VPN is enabled or disabled - * - * @hide - */ - @RequiresPermission(anyOf = { - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, - android.Manifest.permission.NETWORK_STACK, - android.Manifest.permission.NETWORK_SETTINGS}) - @SystemApi(client = MODULE_LIBRARIES) - public void setLegacyLockdownVpnEnabled(boolean enabled) { - try { - mService.setLegacyLockdownVpnEnabled(enabled); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Returns details about the currently active default data network - * for a given uid. This is for internal use only to avoid spying - * other apps. - * - * @return a {@link NetworkInfo} object for the current default network - * for the given uid or {@code null} if no default network is - * available for the specified uid. - * - * {@hide} - */ - @RequiresPermission(android.Manifest.permission.NETWORK_STACK) - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public NetworkInfo getActiveNetworkInfoForUid(int uid) { - return getActiveNetworkInfoForUid(uid, false); - } - - /** {@hide} */ - public NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked) { - try { - return mService.getActiveNetworkInfoForUid(uid, ignoreBlocked); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Returns connection status information about a particular - * network type. - * - * @param networkType integer specifying which networkType in - * which you're interested. - * @return a {@link NetworkInfo} object for the requested - * network type or {@code null} if the type is not - * supported by the device. If {@code networkType} is - * TYPE_VPN and a VPN is active for the calling app, - * then this method will try to return one of the - * underlying networks for the VPN or null if the - * VPN agent didn't specify any. - * - * @deprecated This method does not support multiple connected networks - * of the same type. Use {@link #getAllNetworks} and - * {@link #getNetworkInfo(android.net.Network)} instead. - */ - @Deprecated - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - @Nullable - public NetworkInfo getNetworkInfo(int networkType) { - try { - return mService.getNetworkInfo(networkType); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Returns connection status information about a particular - * Network. - * - * @param network {@link Network} specifying which network - * in which you're interested. - * @return a {@link NetworkInfo} object for the requested - * network or {@code null} if the {@code Network} - * is not valid. - * @deprecated See {@link NetworkInfo}. - */ - @Deprecated - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - @Nullable - public NetworkInfo getNetworkInfo(@Nullable Network network) { - return getNetworkInfoForUid(network, Process.myUid(), false); - } - - /** {@hide} */ - public NetworkInfo getNetworkInfoForUid(Network network, int uid, boolean ignoreBlocked) { - try { - return mService.getNetworkInfoForUid(network, uid, ignoreBlocked); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Returns connection status information about all network - * types supported by the device. - * - * @return an array of {@link NetworkInfo} objects. Check each - * {@link NetworkInfo#getType} for which type each applies. - * - * @deprecated This method does not support multiple connected networks - * of the same type. Use {@link #getAllNetworks} and - * {@link #getNetworkInfo(android.net.Network)} instead. - */ - @Deprecated - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - @NonNull - public NetworkInfo[] getAllNetworkInfo() { - try { - return mService.getAllNetworkInfo(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Return a list of {@link NetworkStateSnapshot}s, one for each network that is currently - * connected. - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - @RequiresPermission(anyOf = { - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, - android.Manifest.permission.NETWORK_STACK, - android.Manifest.permission.NETWORK_SETTINGS}) - @NonNull - public List getAllNetworkStateSnapshots() { - try { - return mService.getAllNetworkStateSnapshots(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Returns the {@link Network} object currently serving a given type, or - * null if the given type is not connected. - * - * @hide - * @deprecated This method does not support multiple connected networks - * of the same type. Use {@link #getAllNetworks} and - * {@link #getNetworkInfo(android.net.Network)} instead. - */ - @Deprecated - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - @UnsupportedAppUsage - public Network getNetworkForType(int networkType) { - try { - return mService.getNetworkForType(networkType); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Returns an array of all {@link Network} currently tracked by the - * framework. - * - * @deprecated This method does not provide any notification of network state changes, forcing - * apps to call it repeatedly. This is inefficient and prone to race conditions. - * Apps should use methods such as - * {@link #registerNetworkCallback(NetworkRequest, NetworkCallback)} instead. - * Apps that desire to obtain information about networks that do not apply to them - * can use {@link NetworkRequest.Builder#setIncludeOtherUidNetworks}. - * - * @return an array of {@link Network} objects. - */ - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - @NonNull - @Deprecated - public Network[] getAllNetworks() { - try { - return mService.getAllNetworks(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Returns an array of {@link NetworkCapabilities} objects, representing - * the Networks that applications run by the given user will use by default. - * @hide - */ - @UnsupportedAppUsage - public NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId) { - try { - return mService.getDefaultNetworkCapabilitiesForUser( - userId, mContext.getOpPackageName(), getAttributionTag()); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Returns the IP information for the current default network. - * - * @return a {@link LinkProperties} object describing the IP info - * for the current default network, or {@code null} if there - * is no current default network. - * - * {@hide} - * @deprecated please use {@link #getLinkProperties(Network)} on the return - * value of {@link #getActiveNetwork()} instead. In particular, - * this method will return non-null LinkProperties even if the - * app is blocked by policy from using this network. - */ - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 109783091) - public LinkProperties getActiveLinkProperties() { - try { - return mService.getActiveLinkProperties(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Returns the IP information for a given network type. - * - * @param networkType the network type of interest. - * @return a {@link LinkProperties} object describing the IP info - * for the given networkType, or {@code null} if there is - * no current default network. - * - * {@hide} - * @deprecated This method does not support multiple connected networks - * of the same type. Use {@link #getAllNetworks}, - * {@link #getNetworkInfo(android.net.Network)}, and - * {@link #getLinkProperties(android.net.Network)} instead. - */ - @Deprecated - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562) - public LinkProperties getLinkProperties(int networkType) { - try { - return mService.getLinkPropertiesForType(networkType); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Get the {@link LinkProperties} for the given {@link Network}. This - * will return {@code null} if the network is unknown. - * - * @param network The {@link Network} object identifying the network in question. - * @return The {@link LinkProperties} for the network, or {@code null}. - */ - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - @Nullable - public LinkProperties getLinkProperties(@Nullable Network network) { - try { - return mService.getLinkProperties(network); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Get the {@link NetworkCapabilities} for the given {@link Network}. This - * will return {@code null} if the network is unknown or if the |network| argument is null. - * - * This will remove any location sensitive data in {@link TransportInfo} embedded in - * {@link NetworkCapabilities#getTransportInfo()}. Some transport info instances like - * {@link android.net.wifi.WifiInfo} contain location sensitive information. Retrieving - * this location sensitive information (subject to app's location permissions) will be - * noted by system. To include any location sensitive data in {@link TransportInfo}, - * use a {@link NetworkCallback} with - * {@link NetworkCallback#FLAG_INCLUDE_LOCATION_INFO} flag. - * - * @param network The {@link Network} object identifying the network in question. - * @return The {@link NetworkCapabilities} for the network, or {@code null}. - */ - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - @Nullable - public NetworkCapabilities getNetworkCapabilities(@Nullable Network network) { - try { - return mService.getNetworkCapabilities( - network, mContext.getOpPackageName(), getAttributionTag()); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Gets a URL that can be used for resolving whether a captive portal is present. - * 1. This URL should respond with a 204 response to a GET request to indicate no captive - * portal is present. - * 2. This URL must be HTTP as redirect responses are used to find captive portal - * sign-in pages. Captive portals cannot respond to HTTPS requests with redirects. - * - * The system network validation may be using different strategies to detect captive portals, - * so this method does not necessarily return a URL used by the system. It only returns a URL - * that may be relevant for other components trying to detect captive portals. - * - * @hide - * @deprecated This API returns URL which is not guaranteed to be one of the URLs used by the - * system. - */ - @Deprecated - @SystemApi - @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) - public String getCaptivePortalServerUrl() { - try { - return mService.getCaptivePortalServerUrl(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Tells the underlying networking system that the caller wants to - * begin using the named feature. The interpretation of {@code feature} - * is completely up to each networking implementation. - * - *

This method requires the caller to hold either the - * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission - * or the ability to modify system settings as determined by - * {@link android.provider.Settings.System#canWrite}.

- * - * @param networkType specifies which network the request pertains to - * @param feature the name of the feature to be used - * @return an integer value representing the outcome of the request. - * The interpretation of this value is specific to each networking - * implementation+feature combination, except that the value {@code -1} - * always indicates failure. - * - * @deprecated Deprecated in favor of the cleaner - * {@link #requestNetwork(NetworkRequest, NetworkCallback)} API. - * In {@link VERSION_CODES#M}, and above, this method is unsupported and will - * throw {@code UnsupportedOperationException} if called. - * @removed - */ - @Deprecated - public int startUsingNetworkFeature(int networkType, String feature) { - checkLegacyRoutingApiAccess(); - NetworkCapabilities netCap = networkCapabilitiesForFeature(networkType, feature); - if (netCap == null) { - Log.d(TAG, "Can't satisfy startUsingNetworkFeature for " + networkType + ", " + - feature); - return DEPRECATED_PHONE_CONSTANT_APN_REQUEST_FAILED; - } - - NetworkRequest request = null; - synchronized (sLegacyRequests) { - LegacyRequest l = sLegacyRequests.get(netCap); - if (l != null) { - Log.d(TAG, "renewing startUsingNetworkFeature request " + l.networkRequest); - renewRequestLocked(l); - if (l.currentNetwork != null) { - return DEPRECATED_PHONE_CONSTANT_APN_ALREADY_ACTIVE; - } else { - return DEPRECATED_PHONE_CONSTANT_APN_REQUEST_STARTED; - } - } - - request = requestNetworkForFeatureLocked(netCap); - } - if (request != null) { - Log.d(TAG, "starting startUsingNetworkFeature for request " + request); - return DEPRECATED_PHONE_CONSTANT_APN_REQUEST_STARTED; - } else { - Log.d(TAG, " request Failed"); - return DEPRECATED_PHONE_CONSTANT_APN_REQUEST_FAILED; - } - } - - /** - * Tells the underlying networking system that the caller is finished - * using the named feature. The interpretation of {@code feature} - * is completely up to each networking implementation. - * - *

This method requires the caller to hold either the - * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission - * or the ability to modify system settings as determined by - * {@link android.provider.Settings.System#canWrite}.

- * - * @param networkType specifies which network the request pertains to - * @param feature the name of the feature that is no longer needed - * @return an integer value representing the outcome of the request. - * The interpretation of this value is specific to each networking - * implementation+feature combination, except that the value {@code -1} - * always indicates failure. - * - * @deprecated Deprecated in favor of the cleaner - * {@link #unregisterNetworkCallback(NetworkCallback)} API. - * In {@link VERSION_CODES#M}, and above, this method is unsupported and will - * throw {@code UnsupportedOperationException} if called. - * @removed - */ - @Deprecated - public int stopUsingNetworkFeature(int networkType, String feature) { - checkLegacyRoutingApiAccess(); - NetworkCapabilities netCap = networkCapabilitiesForFeature(networkType, feature); - if (netCap == null) { - Log.d(TAG, "Can't satisfy stopUsingNetworkFeature for " + networkType + ", " + - feature); - return -1; - } - - if (removeRequestForFeature(netCap)) { - Log.d(TAG, "stopUsingNetworkFeature for " + networkType + ", " + feature); - } - return 1; - } - - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - private NetworkCapabilities networkCapabilitiesForFeature(int networkType, String feature) { - if (networkType == TYPE_MOBILE) { - switch (feature) { - case "enableCBS": - return networkCapabilitiesForType(TYPE_MOBILE_CBS); - case "enableDUN": - case "enableDUNAlways": - return networkCapabilitiesForType(TYPE_MOBILE_DUN); - case "enableFOTA": - return networkCapabilitiesForType(TYPE_MOBILE_FOTA); - case "enableHIPRI": - return networkCapabilitiesForType(TYPE_MOBILE_HIPRI); - case "enableIMS": - return networkCapabilitiesForType(TYPE_MOBILE_IMS); - case "enableMMS": - return networkCapabilitiesForType(TYPE_MOBILE_MMS); - case "enableSUPL": - return networkCapabilitiesForType(TYPE_MOBILE_SUPL); - default: - return null; - } - } else if (networkType == TYPE_WIFI && "p2p".equals(feature)) { - return networkCapabilitiesForType(TYPE_WIFI_P2P); - } - return null; - } - - private int legacyTypeForNetworkCapabilities(NetworkCapabilities netCap) { - if (netCap == null) return TYPE_NONE; - if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)) { - return TYPE_MOBILE_CBS; - } - if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)) { - return TYPE_MOBILE_IMS; - } - if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOTA)) { - return TYPE_MOBILE_FOTA; - } - if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)) { - return TYPE_MOBILE_DUN; - } - if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) { - return TYPE_MOBILE_SUPL; - } - if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) { - return TYPE_MOBILE_MMS; - } - if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) { - return TYPE_MOBILE_HIPRI; - } - if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_WIFI_P2P)) { - return TYPE_WIFI_P2P; - } - return TYPE_NONE; - } - - private static class LegacyRequest { - NetworkCapabilities networkCapabilities; - NetworkRequest networkRequest; - int expireSequenceNumber; - Network currentNetwork; - int delay = -1; - - private void clearDnsBinding() { - if (currentNetwork != null) { - currentNetwork = null; - setProcessDefaultNetworkForHostResolution(null); - } - } - - NetworkCallback networkCallback = new NetworkCallback() { - @Override - public void onAvailable(Network network) { - currentNetwork = network; - Log.d(TAG, "startUsingNetworkFeature got Network:" + network); - setProcessDefaultNetworkForHostResolution(network); - } - @Override - public void onLost(Network network) { - if (network.equals(currentNetwork)) clearDnsBinding(); - Log.d(TAG, "startUsingNetworkFeature lost Network:" + network); - } - }; - } - - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - private static final HashMap sLegacyRequests = - new HashMap<>(); - - private NetworkRequest findRequestForFeature(NetworkCapabilities netCap) { - synchronized (sLegacyRequests) { - LegacyRequest l = sLegacyRequests.get(netCap); - if (l != null) return l.networkRequest; - } - return null; - } - - private void renewRequestLocked(LegacyRequest l) { - l.expireSequenceNumber++; - Log.d(TAG, "renewing request to seqNum " + l.expireSequenceNumber); - sendExpireMsgForFeature(l.networkCapabilities, l.expireSequenceNumber, l.delay); - } - - private void expireRequest(NetworkCapabilities netCap, int sequenceNum) { - int ourSeqNum = -1; - synchronized (sLegacyRequests) { - LegacyRequest l = sLegacyRequests.get(netCap); - if (l == null) return; - ourSeqNum = l.expireSequenceNumber; - if (l.expireSequenceNumber == sequenceNum) removeRequestForFeature(netCap); - } - Log.d(TAG, "expireRequest with " + ourSeqNum + ", " + sequenceNum); - } - - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - private NetworkRequest requestNetworkForFeatureLocked(NetworkCapabilities netCap) { - int delay = -1; - int type = legacyTypeForNetworkCapabilities(netCap); - try { - delay = mService.getRestoreDefaultNetworkDelay(type); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - LegacyRequest l = new LegacyRequest(); - l.networkCapabilities = netCap; - l.delay = delay; - l.expireSequenceNumber = 0; - l.networkRequest = sendRequestForNetwork( - netCap, l.networkCallback, 0, REQUEST, type, getDefaultHandler()); - if (l.networkRequest == null) return null; - sLegacyRequests.put(netCap, l); - sendExpireMsgForFeature(netCap, l.expireSequenceNumber, delay); - return l.networkRequest; - } - - private void sendExpireMsgForFeature(NetworkCapabilities netCap, int seqNum, int delay) { - if (delay >= 0) { - Log.d(TAG, "sending expire msg with seqNum " + seqNum + " and delay " + delay); - CallbackHandler handler = getDefaultHandler(); - Message msg = handler.obtainMessage(EXPIRE_LEGACY_REQUEST, seqNum, 0, netCap); - handler.sendMessageDelayed(msg, delay); - } - } - - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - private boolean removeRequestForFeature(NetworkCapabilities netCap) { - final LegacyRequest l; - synchronized (sLegacyRequests) { - l = sLegacyRequests.remove(netCap); - } - if (l == null) return false; - unregisterNetworkCallback(l.networkCallback); - l.clearDnsBinding(); - return true; - } - - private static final SparseIntArray sLegacyTypeToTransport = new SparseIntArray(); - static { - sLegacyTypeToTransport.put(TYPE_MOBILE, NetworkCapabilities.TRANSPORT_CELLULAR); - sLegacyTypeToTransport.put(TYPE_MOBILE_CBS, NetworkCapabilities.TRANSPORT_CELLULAR); - sLegacyTypeToTransport.put(TYPE_MOBILE_DUN, NetworkCapabilities.TRANSPORT_CELLULAR); - sLegacyTypeToTransport.put(TYPE_MOBILE_FOTA, NetworkCapabilities.TRANSPORT_CELLULAR); - sLegacyTypeToTransport.put(TYPE_MOBILE_HIPRI, NetworkCapabilities.TRANSPORT_CELLULAR); - sLegacyTypeToTransport.put(TYPE_MOBILE_IMS, NetworkCapabilities.TRANSPORT_CELLULAR); - sLegacyTypeToTransport.put(TYPE_MOBILE_MMS, NetworkCapabilities.TRANSPORT_CELLULAR); - sLegacyTypeToTransport.put(TYPE_MOBILE_SUPL, NetworkCapabilities.TRANSPORT_CELLULAR); - sLegacyTypeToTransport.put(TYPE_WIFI, NetworkCapabilities.TRANSPORT_WIFI); - sLegacyTypeToTransport.put(TYPE_WIFI_P2P, NetworkCapabilities.TRANSPORT_WIFI); - sLegacyTypeToTransport.put(TYPE_BLUETOOTH, NetworkCapabilities.TRANSPORT_BLUETOOTH); - sLegacyTypeToTransport.put(TYPE_ETHERNET, NetworkCapabilities.TRANSPORT_ETHERNET); - } - - private static final SparseIntArray sLegacyTypeToCapability = new SparseIntArray(); - static { - sLegacyTypeToCapability.put(TYPE_MOBILE_CBS, NetworkCapabilities.NET_CAPABILITY_CBS); - sLegacyTypeToCapability.put(TYPE_MOBILE_DUN, NetworkCapabilities.NET_CAPABILITY_DUN); - sLegacyTypeToCapability.put(TYPE_MOBILE_FOTA, NetworkCapabilities.NET_CAPABILITY_FOTA); - sLegacyTypeToCapability.put(TYPE_MOBILE_IMS, NetworkCapabilities.NET_CAPABILITY_IMS); - sLegacyTypeToCapability.put(TYPE_MOBILE_MMS, NetworkCapabilities.NET_CAPABILITY_MMS); - sLegacyTypeToCapability.put(TYPE_MOBILE_SUPL, NetworkCapabilities.NET_CAPABILITY_SUPL); - sLegacyTypeToCapability.put(TYPE_WIFI_P2P, NetworkCapabilities.NET_CAPABILITY_WIFI_P2P); - } - - /** - * Given a legacy type (TYPE_WIFI, ...) returns a NetworkCapabilities - * instance suitable for registering a request or callback. Throws an - * IllegalArgumentException if no mapping from the legacy type to - * NetworkCapabilities is known. - * - * @deprecated Types are deprecated. Use {@link NetworkCallback} or {@link NetworkRequest} - * to find the network instead. - * @hide - */ - public static NetworkCapabilities networkCapabilitiesForType(int type) { - final NetworkCapabilities nc = new NetworkCapabilities(); - - // Map from type to transports. - final int NOT_FOUND = -1; - final int transport = sLegacyTypeToTransport.get(type, NOT_FOUND); - if (transport == NOT_FOUND) { - throw new IllegalArgumentException("unknown legacy type: " + type); - } - nc.addTransportType(transport); - - // Map from type to capabilities. - nc.addCapability(sLegacyTypeToCapability.get( - type, NetworkCapabilities.NET_CAPABILITY_INTERNET)); - nc.maybeMarkCapabilitiesRestricted(); - return nc; - } - - /** @hide */ - public static class PacketKeepaliveCallback { - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public PacketKeepaliveCallback() { - } - /** The requested keepalive was successfully started. */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public void onStarted() {} - /** The keepalive was successfully stopped. */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public void onStopped() {} - /** An error occurred. */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public void onError(int error) {} - } - - /** - * Allows applications to request that the system periodically send specific packets on their - * behalf, using hardware offload to save battery power. - * - * To request that the system send keepalives, call one of the methods that return a - * {@link ConnectivityManager.PacketKeepalive} object, such as {@link #startNattKeepalive}, - * passing in a non-null callback. If the callback is successfully started, the callback's - * {@code onStarted} method will be called. If an error occurs, {@code onError} will be called, - * specifying one of the {@code ERROR_*} constants in this class. - * - * To stop an existing keepalive, call {@link PacketKeepalive#stop}. The system will call - * {@link PacketKeepaliveCallback#onStopped} if the operation was successful or - * {@link PacketKeepaliveCallback#onError} if an error occurred. - * - * @deprecated Use {@link SocketKeepalive} instead. - * - * @hide - */ - public class PacketKeepalive { - - private static final String TAG = "PacketKeepalive"; - - /** @hide */ - public static final int SUCCESS = 0; - - /** @hide */ - public static final int NO_KEEPALIVE = -1; - - /** @hide */ - public static final int BINDER_DIED = -10; - - /** The specified {@code Network} is not connected. */ - public static final int ERROR_INVALID_NETWORK = -20; - /** The specified IP addresses are invalid. For example, the specified source IP address is - * not configured on the specified {@code Network}. */ - public static final int ERROR_INVALID_IP_ADDRESS = -21; - /** The requested port is invalid. */ - public static final int ERROR_INVALID_PORT = -22; - /** The packet length is invalid (e.g., too long). */ - public static final int ERROR_INVALID_LENGTH = -23; - /** The packet transmission interval is invalid (e.g., too short). */ - public static final int ERROR_INVALID_INTERVAL = -24; - - /** The hardware does not support this request. */ - public static final int ERROR_HARDWARE_UNSUPPORTED = -30; - /** The hardware returned an error. */ - public static final int ERROR_HARDWARE_ERROR = -31; - - /** The NAT-T destination port for IPsec */ - public static final int NATT_PORT = 4500; - - /** The minimum interval in seconds between keepalive packet transmissions */ - public static final int MIN_INTERVAL = 10; - - private final Network mNetwork; - private final ISocketKeepaliveCallback mCallback; - private final ExecutorService mExecutor; - - private volatile Integer mSlot; - - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public void stop() { - try { - mExecutor.execute(() -> { - try { - if (mSlot != null) { - mService.stopKeepalive(mNetwork, mSlot); - } - } catch (RemoteException e) { - Log.e(TAG, "Error stopping packet keepalive: ", e); - throw e.rethrowFromSystemServer(); - } - }); - } catch (RejectedExecutionException e) { - // The internal executor has already stopped due to previous event. - } - } - - private PacketKeepalive(Network network, PacketKeepaliveCallback callback) { - Objects.requireNonNull(network, "network cannot be null"); - Objects.requireNonNull(callback, "callback cannot be null"); - mNetwork = network; - mExecutor = Executors.newSingleThreadExecutor(); - mCallback = new ISocketKeepaliveCallback.Stub() { - @Override - public void onStarted(int slot) { - final long token = Binder.clearCallingIdentity(); - try { - mExecutor.execute(() -> { - mSlot = slot; - callback.onStarted(); - }); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public void onStopped() { - final long token = Binder.clearCallingIdentity(); - try { - mExecutor.execute(() -> { - mSlot = null; - callback.onStopped(); - }); - } finally { - Binder.restoreCallingIdentity(token); - } - mExecutor.shutdown(); - } - - @Override - public void onError(int error) { - final long token = Binder.clearCallingIdentity(); - try { - mExecutor.execute(() -> { - mSlot = null; - callback.onError(error); - }); - } finally { - Binder.restoreCallingIdentity(token); - } - mExecutor.shutdown(); - } - - @Override - public void onDataReceived() { - // PacketKeepalive is only used for Nat-T keepalive and as such does not invoke - // this callback when data is received. - } - }; - } - } - - /** - * Starts an IPsec NAT-T keepalive packet with the specified parameters. - * - * @deprecated Use {@link #createSocketKeepalive} instead. - * - * @hide - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public PacketKeepalive startNattKeepalive( - Network network, int intervalSeconds, PacketKeepaliveCallback callback, - InetAddress srcAddr, int srcPort, InetAddress dstAddr) { - final PacketKeepalive k = new PacketKeepalive(network, callback); - try { - mService.startNattKeepalive(network, intervalSeconds, k.mCallback, - srcAddr.getHostAddress(), srcPort, dstAddr.getHostAddress()); - } catch (RemoteException e) { - Log.e(TAG, "Error starting packet keepalive: ", e); - throw e.rethrowFromSystemServer(); - } - return k; - } - - // Construct an invalid fd. - private ParcelFileDescriptor createInvalidFd() { - final int invalidFd = -1; - return ParcelFileDescriptor.adoptFd(invalidFd); - } - - /** - * Request that keepalives be started on a IPsec NAT-T socket. - * - * @param network The {@link Network} the socket is on. - * @param socket The socket that needs to be kept alive. - * @param source The source address of the {@link UdpEncapsulationSocket}. - * @param destination The destination address of the {@link UdpEncapsulationSocket}. - * @param executor The executor on which callback will be invoked. The provided {@link Executor} - * must run callback sequentially, otherwise the order of callbacks cannot be - * guaranteed. - * @param callback A {@link SocketKeepalive.Callback}. Used for notifications about keepalive - * changes. Must be extended by applications that use this API. - * - * @return A {@link SocketKeepalive} object that can be used to control the keepalive on the - * given socket. - **/ - public @NonNull SocketKeepalive createSocketKeepalive(@NonNull Network network, - @NonNull UdpEncapsulationSocket socket, - @NonNull InetAddress source, - @NonNull InetAddress destination, - @NonNull @CallbackExecutor Executor executor, - @NonNull Callback callback) { - ParcelFileDescriptor dup; - try { - // Dup is needed here as the pfd inside the socket is owned by the IpSecService, - // which cannot be obtained by the app process. - dup = ParcelFileDescriptor.dup(socket.getFileDescriptor()); - } catch (IOException ignored) { - // Construct an invalid fd, so that if the user later calls start(), it will fail with - // ERROR_INVALID_SOCKET. - dup = createInvalidFd(); - } - return new NattSocketKeepalive(mService, network, dup, socket.getResourceId(), source, - destination, executor, callback); - } - - /** - * Request that keepalives be started on a IPsec NAT-T socket file descriptor. Directly called - * by system apps which don't use IpSecService to create {@link UdpEncapsulationSocket}. - * - * @param network The {@link Network} the socket is on. - * @param pfd The {@link ParcelFileDescriptor} that needs to be kept alive. The provided - * {@link ParcelFileDescriptor} must be bound to a port and the keepalives will be sent - * from that port. - * @param source The source address of the {@link UdpEncapsulationSocket}. - * @param destination The destination address of the {@link UdpEncapsulationSocket}. The - * keepalive packets will always be sent to port 4500 of the given {@code destination}. - * @param executor The executor on which callback will be invoked. The provided {@link Executor} - * must run callback sequentially, otherwise the order of callbacks cannot be - * guaranteed. - * @param callback A {@link SocketKeepalive.Callback}. Used for notifications about keepalive - * changes. Must be extended by applications that use this API. - * - * @return A {@link SocketKeepalive} object that can be used to control the keepalive on the - * given socket. - * @hide - */ - @SystemApi - @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) - public @NonNull SocketKeepalive createNattKeepalive(@NonNull Network network, - @NonNull ParcelFileDescriptor pfd, - @NonNull InetAddress source, - @NonNull InetAddress destination, - @NonNull @CallbackExecutor Executor executor, - @NonNull Callback callback) { - ParcelFileDescriptor dup; - try { - // TODO: Consider remove unnecessary dup. - dup = pfd.dup(); - } catch (IOException ignored) { - // Construct an invalid fd, so that if the user later calls start(), it will fail with - // ERROR_INVALID_SOCKET. - dup = createInvalidFd(); - } - return new NattSocketKeepalive(mService, network, dup, - -1 /* Unused */, source, destination, executor, callback); - } - - /** - * Request that keepalives be started on a TCP socket. - * The socket must be established. - * - * @param network The {@link Network} the socket is on. - * @param socket The socket that needs to be kept alive. - * @param executor The executor on which callback will be invoked. This implementation assumes - * the provided {@link Executor} runs the callbacks in sequence with no - * concurrency. Failing this, no guarantee of correctness can be made. It is - * the responsibility of the caller to ensure the executor provides this - * guarantee. A simple way of creating such an executor is with the standard - * tool {@code Executors.newSingleThreadExecutor}. - * @param callback A {@link SocketKeepalive.Callback}. Used for notifications about keepalive - * changes. Must be extended by applications that use this API. - * - * @return A {@link SocketKeepalive} object that can be used to control the keepalive on the - * given socket. - * @hide - */ - @SystemApi - @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) - public @NonNull SocketKeepalive createSocketKeepalive(@NonNull Network network, - @NonNull Socket socket, - @NonNull Executor executor, - @NonNull Callback callback) { - ParcelFileDescriptor dup; - try { - dup = ParcelFileDescriptor.fromSocket(socket); - } catch (UncheckedIOException ignored) { - // Construct an invalid fd, so that if the user later calls start(), it will fail with - // ERROR_INVALID_SOCKET. - dup = createInvalidFd(); - } - return new TcpSocketKeepalive(mService, network, dup, executor, callback); - } - - /** - * Ensure that a network route exists to deliver traffic to the specified - * host via the specified network interface. An attempt to add a route that - * already exists is ignored, but treated as successful. - * - *

This method requires the caller to hold either the - * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission - * or the ability to modify system settings as determined by - * {@link android.provider.Settings.System#canWrite}.

- * - * @param networkType the type of the network over which traffic to the specified - * host is to be routed - * @param hostAddress the IP address of the host to which the route is desired - * @return {@code true} on success, {@code false} on failure - * - * @deprecated Deprecated in favor of the - * {@link #requestNetwork(NetworkRequest, NetworkCallback)}, - * {@link #bindProcessToNetwork} and {@link Network#getSocketFactory} API. - * In {@link VERSION_CODES#M}, and above, this method is unsupported and will - * throw {@code UnsupportedOperationException} if called. - * @removed - */ - @Deprecated - public boolean requestRouteToHost(int networkType, int hostAddress) { - return requestRouteToHostAddress(networkType, NetworkUtils.intToInetAddress(hostAddress)); - } - - /** - * Ensure that a network route exists to deliver traffic to the specified - * host via the specified network interface. An attempt to add a route that - * already exists is ignored, but treated as successful. - * - *

This method requires the caller to hold either the - * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission - * or the ability to modify system settings as determined by - * {@link android.provider.Settings.System#canWrite}.

- * - * @param networkType the type of the network over which traffic to the specified - * host is to be routed - * @param hostAddress the IP address of the host to which the route is desired - * @return {@code true} on success, {@code false} on failure - * @hide - * @deprecated Deprecated in favor of the {@link #requestNetwork} and - * {@link #bindProcessToNetwork} API. - */ - @Deprecated - @UnsupportedAppUsage - @SystemApi(client = MODULE_LIBRARIES) - public boolean requestRouteToHostAddress(int networkType, InetAddress hostAddress) { - checkLegacyRoutingApiAccess(); - try { - return mService.requestRouteToHostAddress(networkType, hostAddress.getAddress(), - mContext.getOpPackageName(), getAttributionTag()); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * @return the context's attribution tag - */ - // TODO: Remove method and replace with direct call once R code is pushed to AOSP - private @Nullable String getAttributionTag() { - return mContext.getAttributionTag(); - } - - /** - * Returns the value of the setting for background data usage. If false, - * applications should not use the network if the application is not in the - * foreground. Developers should respect this setting, and check the value - * of this before performing any background data operations. - *

- * All applications that have background services that use the network - * should listen to {@link #ACTION_BACKGROUND_DATA_SETTING_CHANGED}. - *

- * @deprecated As of {@link VERSION_CODES#ICE_CREAM_SANDWICH}, availability of - * background data depends on several combined factors, and this method will - * always return {@code true}. Instead, when background data is unavailable, - * {@link #getActiveNetworkInfo()} will now appear disconnected. - * - * @return Whether background data usage is allowed. - */ - @Deprecated - public boolean getBackgroundDataSetting() { - // assume that background data is allowed; final authority is - // NetworkInfo which may be blocked. - return true; - } - - /** - * Sets the value of the setting for background data usage. - * - * @param allowBackgroundData Whether an application should use data while - * it is in the background. - * - * @attr ref android.Manifest.permission#CHANGE_BACKGROUND_DATA_SETTING - * @see #getBackgroundDataSetting() - * @hide - */ - @Deprecated - @UnsupportedAppUsage - public void setBackgroundDataSetting(boolean allowBackgroundData) { - // ignored - } - - /** - * @hide - * @deprecated Talk to TelephonyManager directly - */ - @Deprecated - @UnsupportedAppUsage - public boolean getMobileDataEnabled() { - TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); - if (tm != null) { - int subId = SubscriptionManager.getDefaultDataSubscriptionId(); - Log.d("ConnectivityManager", "getMobileDataEnabled()+ subId=" + subId); - boolean retVal = tm.createForSubscriptionId(subId).isDataEnabled(); - Log.d("ConnectivityManager", "getMobileDataEnabled()- subId=" + subId - + " retVal=" + retVal); - return retVal; - } - Log.d("ConnectivityManager", "getMobileDataEnabled()- remote exception retVal=false"); - return false; - } - - /** - * Callback for use with {@link ConnectivityManager#addDefaultNetworkActiveListener} - * to find out when the system default network has gone in to a high power state. - */ - public interface OnNetworkActiveListener { - /** - * Called on the main thread of the process to report that the current data network - * has become active, and it is now a good time to perform any pending network - * operations. Note that this listener only tells you when the network becomes - * active; if at any other time you want to know whether it is active (and thus okay - * to initiate network traffic), you can retrieve its instantaneous state with - * {@link ConnectivityManager#isDefaultNetworkActive}. - */ - void onNetworkActive(); - } - - private final ArrayMap - mNetworkActivityListeners = new ArrayMap<>(); - - /** - * Start listening to reports when the system's default data network is active, meaning it is - * a good time to perform network traffic. Use {@link #isDefaultNetworkActive()} - * to determine the current state of the system's default network after registering the - * listener. - *

- * If the process default network has been set with - * {@link ConnectivityManager#bindProcessToNetwork} this function will not - * reflect the process's default, but the system default. - * - * @param l The listener to be told when the network is active. - */ - public void addDefaultNetworkActiveListener(final OnNetworkActiveListener l) { - INetworkActivityListener rl = new INetworkActivityListener.Stub() { - @Override - public void onNetworkActive() throws RemoteException { - l.onNetworkActive(); - } - }; - - try { - mService.registerNetworkActivityListener(rl); - mNetworkActivityListeners.put(l, rl); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Remove network active listener previously registered with - * {@link #addDefaultNetworkActiveListener}. - * - * @param l Previously registered listener. - */ - public void removeDefaultNetworkActiveListener(@NonNull OnNetworkActiveListener l) { - INetworkActivityListener rl = mNetworkActivityListeners.get(l); - if (rl == null) { - throw new IllegalArgumentException("Listener was not registered."); - } - try { - mService.registerNetworkActivityListener(rl); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Return whether the data network is currently active. An active network means that - * it is currently in a high power state for performing data transmission. On some - * types of networks, it may be expensive to move and stay in such a state, so it is - * more power efficient to batch network traffic together when the radio is already in - * this state. This method tells you whether right now is currently a good time to - * initiate network traffic, as the network is already active. - */ - public boolean isDefaultNetworkActive() { - try { - return mService.isDefaultNetworkActive(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * {@hide} - */ - public ConnectivityManager(Context context, IConnectivityManager service) { - mContext = Objects.requireNonNull(context, "missing context"); - mService = Objects.requireNonNull(service, "missing IConnectivityManager"); - mTetheringManager = (TetheringManager) mContext.getSystemService(Context.TETHERING_SERVICE); - sInstance = this; - } - - /** {@hide} */ - @UnsupportedAppUsage - public static ConnectivityManager from(Context context) { - return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - } - - /** @hide */ - public NetworkRequest getDefaultRequest() { - try { - // This is not racy as the default request is final in ConnectivityService. - return mService.getDefaultRequest(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Check if the package is a allowed to write settings. This also accounts that such an access - * happened. - * - * @return {@code true} iff the package is allowed to write settings. - */ - // TODO: Remove method and replace with direct call once R code is pushed to AOSP - private static boolean checkAndNoteWriteSettingsOperation(@NonNull Context context, int uid, - @NonNull String callingPackage, @Nullable String callingAttributionTag, - boolean throwException) { - return Settings.checkAndNoteWriteSettingsOperation(context, uid, callingPackage, - callingAttributionTag, throwException); - } - - /** - * @deprecated - use getSystemService. This is a kludge to support static access in certain - * situations where a Context pointer is unavailable. - * @hide - */ - @Deprecated - static ConnectivityManager getInstanceOrNull() { - return sInstance; - } - - /** - * @deprecated - use getSystemService. This is a kludge to support static access in certain - * situations where a Context pointer is unavailable. - * @hide - */ - @Deprecated - @UnsupportedAppUsage - private static ConnectivityManager getInstance() { - if (getInstanceOrNull() == null) { - throw new IllegalStateException("No ConnectivityManager yet constructed"); - } - return getInstanceOrNull(); - } - - /** - * Get the set of tetherable, available interfaces. This list is limited by - * device configuration and current interface existence. - * - * @return an array of 0 or more Strings of tetherable interface names. - * - * @deprecated Use {@link TetheringEventCallback#onTetherableInterfacesChanged(List)} instead. - * {@hide} - */ - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - @UnsupportedAppUsage - @Deprecated - public String[] getTetherableIfaces() { - return mTetheringManager.getTetherableIfaces(); - } - - /** - * Get the set of tethered interfaces. - * - * @return an array of 0 or more String of currently tethered interface names. - * - * @deprecated Use {@link TetheringEventCallback#onTetherableInterfacesChanged(List)} instead. - * {@hide} - */ - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - @UnsupportedAppUsage - @Deprecated - public String[] getTetheredIfaces() { - return mTetheringManager.getTetheredIfaces(); - } - - /** - * Get the set of interface names which attempted to tether but - * failed. Re-attempting to tether may cause them to reset to the Tethered - * state. Alternatively, causing the interface to be destroyed and recreated - * may cause them to reset to the available state. - * {@link ConnectivityManager#getLastTetherError} can be used to get more - * information on the cause of the errors. - * - * @return an array of 0 or more String indicating the interface names - * which failed to tether. - * - * @deprecated Use {@link TetheringEventCallback#onError(String, int)} instead. - * {@hide} - */ - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - @UnsupportedAppUsage - @Deprecated - public String[] getTetheringErroredIfaces() { - return mTetheringManager.getTetheringErroredIfaces(); - } - - /** - * Get the set of tethered dhcp ranges. - * - * @deprecated This method is not supported. - * TODO: remove this function when all of clients are removed. - * {@hide} - */ - @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) - @Deprecated - public String[] getTetheredDhcpRanges() { - throw new UnsupportedOperationException("getTetheredDhcpRanges is not supported"); - } - - /** - * Attempt to tether the named interface. This will setup a dhcp server - * on the interface, forward and NAT IP packets and forward DNS requests - * to the best active upstream network interface. Note that if no upstream - * IP network interface is available, dhcp will still run and traffic will be - * allowed between the tethered devices and this device, though upstream net - * access will of course fail until an upstream network interface becomes - * active. - * - *

This method requires the caller to hold either the - * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission - * or the ability to modify system settings as determined by - * {@link android.provider.Settings.System#canWrite}.

- * - *

WARNING: New clients should not use this function. The only usages should be in PanService - * and WifiStateMachine which need direct access. All other clients should use - * {@link #startTethering} and {@link #stopTethering} which encapsulate proper provisioning - * logic.

- * - * @param iface the interface name to tether. - * @return error a {@code TETHER_ERROR} value indicating success or failure type - * @deprecated Use {@link TetheringManager#startTethering} instead - * - * {@hide} - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - @Deprecated - public int tether(String iface) { - return mTetheringManager.tether(iface); - } - - /** - * Stop tethering the named interface. - * - *

This method requires the caller to hold either the - * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission - * or the ability to modify system settings as determined by - * {@link android.provider.Settings.System#canWrite}.

- * - *

WARNING: New clients should not use this function. The only usages should be in PanService - * and WifiStateMachine which need direct access. All other clients should use - * {@link #startTethering} and {@link #stopTethering} which encapsulate proper provisioning - * logic.

- * - * @param iface the interface name to untether. - * @return error a {@code TETHER_ERROR} value indicating success or failure type - * - * {@hide} - */ - @UnsupportedAppUsage - @Deprecated - public int untether(String iface) { - return mTetheringManager.untether(iface); - } - - /** - * Check if the device allows for tethering. It may be disabled via - * {@code ro.tether.denied} system property, Settings.TETHER_SUPPORTED or - * due to device configuration. - * - *

If this app does not have permission to use this API, it will always - * return false rather than throw an exception.

- * - *

If the device has a hotspot provisioning app, the caller is required to hold the - * {@link android.Manifest.permission.TETHER_PRIVILEGED} permission.

- * - *

Otherwise, this method requires the caller to hold the ability to modify system - * settings as determined by {@link android.provider.Settings.System#canWrite}.

- * - * @return a boolean - {@code true} indicating Tethering is supported. - * - * @deprecated Use {@link TetheringEventCallback#onTetheringSupported(boolean)} instead. - * {@hide} - */ - @SystemApi - @RequiresPermission(anyOf = {android.Manifest.permission.TETHER_PRIVILEGED, - android.Manifest.permission.WRITE_SETTINGS}) - public boolean isTetheringSupported() { - return mTetheringManager.isTetheringSupported(); - } - - /** - * Callback for use with {@link #startTethering} to find out whether tethering succeeded. - * - * @deprecated Use {@link TetheringManager.StartTetheringCallback} instead. - * @hide - */ - @SystemApi - @Deprecated - public static abstract class OnStartTetheringCallback { - /** - * Called when tethering has been successfully started. - */ - public void onTetheringStarted() {} - - /** - * Called when starting tethering failed. - */ - public void onTetheringFailed() {} - } - - /** - * Convenient overload for - * {@link #startTethering(int, boolean, OnStartTetheringCallback, Handler)} which passes a null - * handler to run on the current thread's {@link Looper}. - * - * @deprecated Use {@link TetheringManager#startTethering} instead. - * @hide - */ - @SystemApi - @Deprecated - @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) - public void startTethering(int type, boolean showProvisioningUi, - final OnStartTetheringCallback callback) { - startTethering(type, showProvisioningUi, callback, null); - } - - /** - * Runs tether provisioning for the given type if needed and then starts tethering if - * the check succeeds. If no carrier provisioning is required for tethering, tethering is - * enabled immediately. If provisioning fails, tethering will not be enabled. It also - * schedules tether provisioning re-checks if appropriate. - * - * @param type The type of tethering to start. Must be one of - * {@link ConnectivityManager.TETHERING_WIFI}, - * {@link ConnectivityManager.TETHERING_USB}, or - * {@link ConnectivityManager.TETHERING_BLUETOOTH}. - * @param showProvisioningUi a boolean indicating to show the provisioning app UI if there - * is one. This should be true the first time this function is called and also any time - * the user can see this UI. It gives users information from their carrier about the - * check failing and how they can sign up for tethering if possible. - * @param callback an {@link OnStartTetheringCallback} which will be called to notify the caller - * of the result of trying to tether. - * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. - * - * @deprecated Use {@link TetheringManager#startTethering} instead. - * @hide - */ - @SystemApi - @Deprecated - @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) - public void startTethering(int type, boolean showProvisioningUi, - final OnStartTetheringCallback callback, Handler handler) { - Objects.requireNonNull(callback, "OnStartTetheringCallback cannot be null."); - - final Executor executor = new Executor() { - @Override - public void execute(Runnable command) { - if (handler == null) { - command.run(); - } else { - handler.post(command); - } - } - }; - - final StartTetheringCallback tetheringCallback = new StartTetheringCallback() { - @Override - public void onTetheringStarted() { - callback.onTetheringStarted(); - } - - @Override - public void onTetheringFailed(final int error) { - callback.onTetheringFailed(); - } - }; - - final TetheringRequest request = new TetheringRequest.Builder(type) - .setShouldShowEntitlementUi(showProvisioningUi).build(); - - mTetheringManager.startTethering(request, executor, tetheringCallback); - } - - /** - * Stops tethering for the given type. Also cancels any provisioning rechecks for that type if - * applicable. - * - * @param type The type of tethering to stop. Must be one of - * {@link ConnectivityManager.TETHERING_WIFI}, - * {@link ConnectivityManager.TETHERING_USB}, or - * {@link ConnectivityManager.TETHERING_BLUETOOTH}. - * - * @deprecated Use {@link TetheringManager#stopTethering} instead. - * @hide - */ - @SystemApi - @Deprecated - @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) - public void stopTethering(int type) { - mTetheringManager.stopTethering(type); - } - - /** - * Callback for use with {@link registerTetheringEventCallback} to find out tethering - * upstream status. - * - * @deprecated Use {@link TetheringManager#OnTetheringEventCallback} instead. - * @hide - */ - @SystemApi - @Deprecated - public abstract static class OnTetheringEventCallback { - - /** - * Called when tethering upstream changed. This can be called multiple times and can be - * called any time. - * - * @param network the {@link Network} of tethering upstream. Null means tethering doesn't - * have any upstream. - */ - public void onUpstreamChanged(@Nullable Network network) {} - } - - @GuardedBy("mTetheringEventCallbacks") - private final ArrayMap - mTetheringEventCallbacks = new ArrayMap<>(); - - /** - * Start listening to tethering change events. Any new added callback will receive the last - * tethering status right away. If callback is registered when tethering has no upstream or - * disabled, {@link OnTetheringEventCallback#onUpstreamChanged} will immediately be called - * with a null argument. The same callback object cannot be registered twice. - * - * @param executor the executor on which callback will be invoked. - * @param callback the callback to be called when tethering has change events. - * - * @deprecated Use {@link TetheringManager#registerTetheringEventCallback} instead. - * @hide - */ - @SystemApi - @Deprecated - @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) - public void registerTetheringEventCallback( - @NonNull @CallbackExecutor Executor executor, - @NonNull final OnTetheringEventCallback callback) { - Objects.requireNonNull(callback, "OnTetheringEventCallback cannot be null."); - - final TetheringEventCallback tetherCallback = - new TetheringEventCallback() { - @Override - public void onUpstreamChanged(@Nullable Network network) { - callback.onUpstreamChanged(network); - } - }; - - synchronized (mTetheringEventCallbacks) { - mTetheringEventCallbacks.put(callback, tetherCallback); - mTetheringManager.registerTetheringEventCallback(executor, tetherCallback); - } - } - - /** - * Remove tethering event callback previously registered with - * {@link #registerTetheringEventCallback}. - * - * @param callback previously registered callback. - * - * @deprecated Use {@link TetheringManager#unregisterTetheringEventCallback} instead. - * @hide - */ - @SystemApi - @Deprecated - @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) - public void unregisterTetheringEventCallback( - @NonNull final OnTetheringEventCallback callback) { - Objects.requireNonNull(callback, "The callback must be non-null"); - synchronized (mTetheringEventCallbacks) { - final TetheringEventCallback tetherCallback = - mTetheringEventCallbacks.remove(callback); - mTetheringManager.unregisterTetheringEventCallback(tetherCallback); - } - } - - - /** - * Get the list of regular expressions that define any tetherable - * USB network interfaces. If USB tethering is not supported by the - * device, this list should be empty. - * - * @return an array of 0 or more regular expression Strings defining - * what interfaces are considered tetherable usb interfaces. - * - * @deprecated Use {@link TetheringEventCallback#onTetherableInterfaceRegexpsChanged} instead. - * {@hide} - */ - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - @UnsupportedAppUsage - @Deprecated - public String[] getTetherableUsbRegexs() { - return mTetheringManager.getTetherableUsbRegexs(); - } - - /** - * Get the list of regular expressions that define any tetherable - * Wifi network interfaces. If Wifi tethering is not supported by the - * device, this list should be empty. - * - * @return an array of 0 or more regular expression Strings defining - * what interfaces are considered tetherable wifi interfaces. - * - * @deprecated Use {@link TetheringEventCallback#onTetherableInterfaceRegexpsChanged} instead. - * {@hide} - */ - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - @UnsupportedAppUsage - @Deprecated - public String[] getTetherableWifiRegexs() { - return mTetheringManager.getTetherableWifiRegexs(); - } - - /** - * Get the list of regular expressions that define any tetherable - * Bluetooth network interfaces. If Bluetooth tethering is not supported by the - * device, this list should be empty. - * - * @return an array of 0 or more regular expression Strings defining - * what interfaces are considered tetherable bluetooth interfaces. - * - * @deprecated Use {@link TetheringEventCallback#onTetherableInterfaceRegexpsChanged( - *TetheringManager.TetheringInterfaceRegexps)} instead. - * {@hide} - */ - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - @UnsupportedAppUsage - @Deprecated - public String[] getTetherableBluetoothRegexs() { - return mTetheringManager.getTetherableBluetoothRegexs(); - } - - /** - * Attempt to both alter the mode of USB and Tethering of USB. A - * utility method to deal with some of the complexity of USB - will - * attempt to switch to Rndis and subsequently tether the resulting - * interface on {@code true} or turn off tethering and switch off - * Rndis on {@code false}. - * - *

This method requires the caller to hold either the - * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission - * or the ability to modify system settings as determined by - * {@link android.provider.Settings.System#canWrite}.

- * - * @param enable a boolean - {@code true} to enable tethering - * @return error a {@code TETHER_ERROR} value indicating success or failure type - * @deprecated Use {@link TetheringManager#startTethering} instead - * - * {@hide} - */ - @UnsupportedAppUsage - @Deprecated - public int setUsbTethering(boolean enable) { - return mTetheringManager.setUsbTethering(enable); - } - - /** - * @deprecated Use {@link TetheringManager#TETHER_ERROR_NO_ERROR}. - * {@hide} - */ - @SystemApi - @Deprecated - public static final int TETHER_ERROR_NO_ERROR = 0; - /** - * @deprecated Use {@link TetheringManager#TETHER_ERROR_UNKNOWN_IFACE}. - * {@hide} - */ - @Deprecated - public static final int TETHER_ERROR_UNKNOWN_IFACE = - TetheringManager.TETHER_ERROR_UNKNOWN_IFACE; - /** - * @deprecated Use {@link TetheringManager#TETHER_ERROR_SERVICE_UNAVAIL}. - * {@hide} - */ - @Deprecated - public static final int TETHER_ERROR_SERVICE_UNAVAIL = - TetheringManager.TETHER_ERROR_SERVICE_UNAVAIL; - /** - * @deprecated Use {@link TetheringManager#TETHER_ERROR_UNSUPPORTED}. - * {@hide} - */ - @Deprecated - public static final int TETHER_ERROR_UNSUPPORTED = TetheringManager.TETHER_ERROR_UNSUPPORTED; - /** - * @deprecated Use {@link TetheringManager#TETHER_ERROR_UNAVAIL_IFACE}. - * {@hide} - */ - @Deprecated - public static final int TETHER_ERROR_UNAVAIL_IFACE = - TetheringManager.TETHER_ERROR_UNAVAIL_IFACE; - /** - * @deprecated Use {@link TetheringManager#TETHER_ERROR_INTERNAL_ERROR}. - * {@hide} - */ - @Deprecated - public static final int TETHER_ERROR_MASTER_ERROR = - TetheringManager.TETHER_ERROR_INTERNAL_ERROR; - /** - * @deprecated Use {@link TetheringManager#TETHER_ERROR_TETHER_IFACE_ERROR}. - * {@hide} - */ - @Deprecated - public static final int TETHER_ERROR_TETHER_IFACE_ERROR = - TetheringManager.TETHER_ERROR_TETHER_IFACE_ERROR; - /** - * @deprecated Use {@link TetheringManager#TETHER_ERROR_UNTETHER_IFACE_ERROR}. - * {@hide} - */ - @Deprecated - public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = - TetheringManager.TETHER_ERROR_UNTETHER_IFACE_ERROR; - /** - * @deprecated Use {@link TetheringManager#TETHER_ERROR_ENABLE_FORWARDING_ERROR}. - * {@hide} - */ - @Deprecated - public static final int TETHER_ERROR_ENABLE_NAT_ERROR = - TetheringManager.TETHER_ERROR_ENABLE_FORWARDING_ERROR; - /** - * @deprecated Use {@link TetheringManager#TETHER_ERROR_DISABLE_FORWARDING_ERROR}. - * {@hide} - */ - @Deprecated - public static final int TETHER_ERROR_DISABLE_NAT_ERROR = - TetheringManager.TETHER_ERROR_DISABLE_FORWARDING_ERROR; - /** - * @deprecated Use {@link TetheringManager#TETHER_ERROR_IFACE_CFG_ERROR}. - * {@hide} - */ - @Deprecated - public static final int TETHER_ERROR_IFACE_CFG_ERROR = - TetheringManager.TETHER_ERROR_IFACE_CFG_ERROR; - /** - * @deprecated Use {@link TetheringManager#TETHER_ERROR_PROVISIONING_FAILED}. - * {@hide} - */ - @SystemApi - @Deprecated - public static final int TETHER_ERROR_PROVISION_FAILED = 11; - /** - * @deprecated Use {@link TetheringManager#TETHER_ERROR_DHCPSERVER_ERROR}. - * {@hide} - */ - @Deprecated - public static final int TETHER_ERROR_DHCPSERVER_ERROR = - TetheringManager.TETHER_ERROR_DHCPSERVER_ERROR; - /** - * @deprecated Use {@link TetheringManager#TETHER_ERROR_ENTITLEMENT_UNKNOWN}. - * {@hide} - */ - @SystemApi - @Deprecated - public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN = 13; - - /** - * Get a more detailed error code after a Tethering or Untethering - * request asynchronously failed. - * - * @param iface The name of the interface of interest - * @return error The error code of the last error tethering or untethering the named - * interface - * - * @deprecated Use {@link TetheringEventCallback#onError(String, int)} instead. - * {@hide} - */ - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - @Deprecated - public int getLastTetherError(String iface) { - int error = mTetheringManager.getLastTetherError(iface); - if (error == TetheringManager.TETHER_ERROR_UNKNOWN_TYPE) { - // TETHER_ERROR_UNKNOWN_TYPE was introduced with TetheringManager and has never been - // returned by ConnectivityManager. Convert it to the legacy TETHER_ERROR_UNKNOWN_IFACE - // instead. - error = TetheringManager.TETHER_ERROR_UNKNOWN_IFACE; - } - return error; - } - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(value = { - TETHER_ERROR_NO_ERROR, - TETHER_ERROR_PROVISION_FAILED, - TETHER_ERROR_ENTITLEMENT_UNKONWN, - }) - public @interface EntitlementResultCode { - } - - /** - * Callback for use with {@link #getLatestTetheringEntitlementResult} to find out whether - * entitlement succeeded. - * - * @deprecated Use {@link TetheringManager#OnTetheringEntitlementResultListener} instead. - * @hide - */ - @SystemApi - @Deprecated - public interface OnTetheringEntitlementResultListener { - /** - * Called to notify entitlement result. - * - * @param resultCode an int value of entitlement result. It may be one of - * {@link #TETHER_ERROR_NO_ERROR}, - * {@link #TETHER_ERROR_PROVISION_FAILED}, or - * {@link #TETHER_ERROR_ENTITLEMENT_UNKONWN}. - */ - void onTetheringEntitlementResult(@EntitlementResultCode int resultCode); - } - - /** - * Get the last value of the entitlement check on this downstream. If the cached value is - * {@link #TETHER_ERROR_NO_ERROR} or showEntitlementUi argument is false, it just return the - * cached value. Otherwise, a UI-based entitlement check would be performed. It is not - * guaranteed that the UI-based entitlement check will complete in any specific time period - * and may in fact never complete. Any successful entitlement check the platform performs for - * any reason will update the cached value. - * - * @param type the downstream type of tethering. Must be one of - * {@link #TETHERING_WIFI}, - * {@link #TETHERING_USB}, or - * {@link #TETHERING_BLUETOOTH}. - * @param showEntitlementUi a boolean indicating whether to run UI-based entitlement check. - * @param executor the executor on which callback will be invoked. - * @param listener an {@link OnTetheringEntitlementResultListener} which will be called to - * notify the caller of the result of entitlement check. The listener may be called zero - * or one time. - * @deprecated Use {@link TetheringManager#requestLatestTetheringEntitlementResult} instead. - * {@hide} - */ - @SystemApi - @Deprecated - @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) - public void getLatestTetheringEntitlementResult(int type, boolean showEntitlementUi, - @NonNull @CallbackExecutor Executor executor, - @NonNull final OnTetheringEntitlementResultListener listener) { - Objects.requireNonNull(listener, "TetheringEntitlementResultListener cannot be null."); - ResultReceiver wrappedListener = new ResultReceiver(null) { - @Override - protected void onReceiveResult(int resultCode, Bundle resultData) { - final long token = Binder.clearCallingIdentity(); - try { - executor.execute(() -> { - listener.onTetheringEntitlementResult(resultCode); - }); - } finally { - Binder.restoreCallingIdentity(token); - } - } - }; - - mTetheringManager.requestLatestTetheringEntitlementResult(type, wrappedListener, - showEntitlementUi); - } - - /** - * Report network connectivity status. This is currently used only - * to alter status bar UI. - *

This method requires the caller to hold the permission - * {@link android.Manifest.permission#STATUS_BAR}. - * - * @param networkType The type of network you want to report on - * @param percentage The quality of the connection 0 is bad, 100 is good - * @deprecated Types are deprecated. Use {@link #reportNetworkConnectivity} instead. - * {@hide} - */ - public void reportInetCondition(int networkType, int percentage) { - printStackTrace(); - try { - mService.reportInetCondition(networkType, percentage); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Report a problem network to the framework. This provides a hint to the system - * that there might be connectivity problems on this network and may cause - * the framework to re-evaluate network connectivity and/or switch to another - * network. - * - * @param network The {@link Network} the application was attempting to use - * or {@code null} to indicate the current default network. - * @deprecated Use {@link #reportNetworkConnectivity} which allows reporting both - * working and non-working connectivity. - */ - @Deprecated - public void reportBadNetwork(@Nullable Network network) { - printStackTrace(); - try { - // One of these will be ignored because it matches system's current state. - // The other will trigger the necessary reevaluation. - mService.reportNetworkConnectivity(network, true); - mService.reportNetworkConnectivity(network, false); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Report to the framework whether a network has working connectivity. - * This provides a hint to the system that a particular network is providing - * working connectivity or not. In response the framework may re-evaluate - * the network's connectivity and might take further action thereafter. - * - * @param network The {@link Network} the application was attempting to use - * or {@code null} to indicate the current default network. - * @param hasConnectivity {@code true} if the application was able to successfully access the - * Internet using {@code network} or {@code false} if not. - */ - public void reportNetworkConnectivity(@Nullable Network network, boolean hasConnectivity) { - printStackTrace(); - try { - mService.reportNetworkConnectivity(network, hasConnectivity); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Set a network-independent global HTTP proxy. - * - * This sets an HTTP proxy that applies to all networks and overrides any network-specific - * proxy. If set, HTTP libraries that are proxy-aware will use this global proxy when - * accessing any network, regardless of what the settings for that network are. - * - * Note that HTTP proxies are by nature typically network-dependent, and setting a global - * proxy is likely to break networking on multiple networks. This method is only meant - * for device policy clients looking to do general internal filtering or similar use cases. - * - * {@see #getGlobalProxy} - * {@see LinkProperties#getHttpProxy} - * - * @param p A {@link ProxyInfo} object defining the new global HTTP proxy. Calling this - * method with a {@code null} value will clear the global HTTP proxy. - * @hide - */ - // Used by Device Policy Manager to set the global proxy. - @SystemApi(client = MODULE_LIBRARIES) - @RequiresPermission(android.Manifest.permission.NETWORK_STACK) - public void setGlobalProxy(@Nullable final ProxyInfo p) { - try { - mService.setGlobalProxy(p); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Retrieve any network-independent global HTTP proxy. - * - * @return {@link ProxyInfo} for the current global HTTP proxy or {@code null} - * if no global HTTP proxy is set. - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - @Nullable - public ProxyInfo getGlobalProxy() { - try { - return mService.getGlobalProxy(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Retrieve the global HTTP proxy, or if no global HTTP proxy is set, a - * network-specific HTTP proxy. If {@code network} is null, the - * network-specific proxy returned is the proxy of the default active - * network. - * - * @return {@link ProxyInfo} for the current global HTTP proxy, or if no - * global HTTP proxy is set, {@code ProxyInfo} for {@code network}, - * or when {@code network} is {@code null}, - * the {@code ProxyInfo} for the default active network. Returns - * {@code null} when no proxy applies or the caller doesn't have - * permission to use {@code network}. - * @hide - */ - public ProxyInfo getProxyForNetwork(Network network) { - try { - return mService.getProxyForNetwork(network); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Get the current default HTTP proxy settings. If a global proxy is set it will be returned, - * otherwise if this process is bound to a {@link Network} using - * {@link #bindProcessToNetwork} then that {@code Network}'s proxy is returned, otherwise - * the default network's proxy is returned. - * - * @return the {@link ProxyInfo} for the current HTTP proxy, or {@code null} if no - * HTTP proxy is active. - */ - @Nullable - public ProxyInfo getDefaultProxy() { - return getProxyForNetwork(getBoundNetworkForProcess()); - } - - /** - * Returns true if the hardware supports the given network type - * else it returns false. This doesn't indicate we have coverage - * or are authorized onto a network, just whether or not the - * hardware supports it. For example a GSM phone without a SIM - * should still return {@code true} for mobile data, but a wifi only - * tablet would return {@code false}. - * - * @param networkType The network type we'd like to check - * @return {@code true} if supported, else {@code false} - * @deprecated Types are deprecated. Use {@link NetworkCapabilities} instead. - * @hide - */ - @Deprecated - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562) - public boolean isNetworkSupported(int networkType) { - try { - return mService.isNetworkSupported(networkType); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Returns if the currently active data network is metered. A network is - * classified as metered when the user is sensitive to heavy data usage on - * that connection due to monetary costs, data limitations or - * battery/performance issues. You should check this before doing large - * data transfers, and warn the user or delay the operation until another - * network is available. - * - * @return {@code true} if large transfers should be avoided, otherwise - * {@code false}. - */ - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - public boolean isActiveNetworkMetered() { - try { - return mService.isActiveNetworkMetered(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Set sign in error notification to visible or invisible - * - * @hide - * @deprecated Doesn't properly deal with multiple connected networks of the same type. - */ - @Deprecated - public void setProvisioningNotificationVisible(boolean visible, int networkType, - String action) { - try { - mService.setProvisioningNotificationVisible(visible, networkType, action); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Set the value for enabling/disabling airplane mode - * - * @param enable whether to enable airplane mode or not - * - * @hide - */ - @RequiresPermission(anyOf = { - android.Manifest.permission.NETWORK_AIRPLANE_MODE, - android.Manifest.permission.NETWORK_SETTINGS, - android.Manifest.permission.NETWORK_SETUP_WIZARD, - android.Manifest.permission.NETWORK_STACK}) - @SystemApi - public void setAirplaneMode(boolean enable) { - try { - mService.setAirplaneMode(enable); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Registers the specified {@link NetworkProvider}. - * Each listener must only be registered once. The listener can be unregistered with - * {@link #unregisterNetworkProvider}. - * - * @param provider the provider to register - * @return the ID of the provider. This ID must be used by the provider when registering - * {@link android.net.NetworkAgent}s. - * @hide - */ - @SystemApi - @RequiresPermission(anyOf = { - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, - android.Manifest.permission.NETWORK_FACTORY}) - public int registerNetworkProvider(@NonNull NetworkProvider provider) { - if (provider.getProviderId() != NetworkProvider.ID_NONE) { - throw new IllegalStateException("NetworkProviders can only be registered once"); - } - - try { - int providerId = mService.registerNetworkProvider(provider.getMessenger(), - provider.getName()); - provider.setProviderId(providerId); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - return provider.getProviderId(); - } - - /** - * Unregisters the specified NetworkProvider. - * - * @param provider the provider to unregister - * @hide - */ - @SystemApi - @RequiresPermission(anyOf = { - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, - android.Manifest.permission.NETWORK_FACTORY}) - public void unregisterNetworkProvider(@NonNull NetworkProvider provider) { - try { - mService.unregisterNetworkProvider(provider.getMessenger()); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - provider.setProviderId(NetworkProvider.ID_NONE); - } - - /** - * Register or update a network offer with ConnectivityService. - * - * ConnectivityService keeps track of offers made by the various providers and matches - * them to networking requests made by apps or the system. A callback identifies an offer - * uniquely, and later calls with the same callback update the offer. The provider supplies a - * score and the capabilities of the network it might be able to bring up ; these act as - * filters used by ConnectivityService to only send those requests that can be fulfilled by the - * provider. - * - * The provider is under no obligation to be able to bring up the network it offers at any - * given time. Instead, this mechanism is meant to limit requests received by providers - * to those they actually have a chance to fulfill, as providers don't have a way to compare - * the quality of the network satisfying a given request to their own offer. - * - * An offer can be updated by calling this again with the same callback object. This is - * similar to calling unofferNetwork and offerNetwork again, but will only update the - * provider with the changes caused by the changes in the offer. - * - * @param provider The provider making this offer. - * @param score The prospective score of the network. - * @param caps The prospective capabilities of the network. - * @param callback The callback to call when this offer is needed or unneeded. - * @hide exposed via the NetworkProvider class. - */ - @RequiresPermission(anyOf = { - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, - android.Manifest.permission.NETWORK_FACTORY}) - public void offerNetwork(@NonNull final int providerId, - @NonNull final NetworkScore score, @NonNull final NetworkCapabilities caps, - @NonNull final INetworkOfferCallback callback) { - try { - mService.offerNetwork(providerId, - Objects.requireNonNull(score, "null score"), - Objects.requireNonNull(caps, "null caps"), - Objects.requireNonNull(callback, "null callback")); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Withdraw a network offer made with {@link #offerNetwork}. - * - * @param callback The callback passed at registration time. This must be the same object - * that was passed to {@link #offerNetwork} - * @hide exposed via the NetworkProvider class. - */ - public void unofferNetwork(@NonNull final INetworkOfferCallback callback) { - try { - mService.unofferNetwork(Objects.requireNonNull(callback)); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - /** @hide exposed via the NetworkProvider class. */ - @RequiresPermission(anyOf = { - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, - android.Manifest.permission.NETWORK_FACTORY}) - public void declareNetworkRequestUnfulfillable(@NonNull NetworkRequest request) { - try { - mService.declareNetworkRequestUnfulfillable(request); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * @hide - * Register a NetworkAgent with ConnectivityService. - * @return Network corresponding to NetworkAgent. - */ - @RequiresPermission(anyOf = { - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, - android.Manifest.permission.NETWORK_FACTORY}) - public Network registerNetworkAgent(INetworkAgent na, NetworkInfo ni, LinkProperties lp, - NetworkCapabilities nc, @NonNull NetworkScore score, NetworkAgentConfig config, - int providerId) { - try { - return mService.registerNetworkAgent(na, ni, lp, nc, score, config, providerId); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Base class for {@code NetworkRequest} callbacks. Used for notifications about network - * changes. Should be extended by applications wanting notifications. - * - * A {@code NetworkCallback} is registered by calling - * {@link #requestNetwork(NetworkRequest, NetworkCallback)}, - * {@link #registerNetworkCallback(NetworkRequest, NetworkCallback)}, - * or {@link #registerDefaultNetworkCallback(NetworkCallback)}. A {@code NetworkCallback} is - * unregistered by calling {@link #unregisterNetworkCallback(NetworkCallback)}. - * A {@code NetworkCallback} should be registered at most once at any time. - * A {@code NetworkCallback} that has been unregistered can be registered again. - */ - public static class NetworkCallback { - /** - * No flags associated with this callback. - * @hide - */ - public static final int FLAG_NONE = 0; - /** - * Use this flag to include any location sensitive data in {@link NetworkCapabilities} sent - * via {@link #onCapabilitiesChanged(Network, NetworkCapabilities)}. - *

- * These include: - *

  • Some transport info instances (retrieved via - * {@link NetworkCapabilities#getTransportInfo()}) like {@link android.net.wifi.WifiInfo} - * contain location sensitive information. - *
  • OwnerUid (retrieved via {@link NetworkCapabilities#getOwnerUid()} is location - * sensitive for wifi suggestor apps (i.e using {@link WifiNetworkSuggestion}).
  • - *

    - *

    - * Note: - *

  • Retrieving this location sensitive information (subject to app's location - * permissions) will be noted by system.
  • - *
  • Without this flag any {@link NetworkCapabilities} provided via the callback does - * not include location sensitive info. - *

    - */ - // Note: Some existing fields which are location sensitive may still be included without - // this flag if the app targets SDK < S (to maintain backwards compatibility). - public static final int FLAG_INCLUDE_LOCATION_INFO = 1 << 0; - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(flag = true, prefix = "FLAG_", value = { - FLAG_NONE, - FLAG_INCLUDE_LOCATION_INFO - }) - public @interface Flag { } - - /** - * All the valid flags for error checking. - */ - private static final int VALID_FLAGS = FLAG_INCLUDE_LOCATION_INFO; - - public NetworkCallback() { - this(FLAG_NONE); - } - - public NetworkCallback(@Flag int flags) { - if ((flags & VALID_FLAGS) != flags) { - throw new IllegalArgumentException("Invalid flags"); - } - mFlags = flags; - } - - /** - * Called when the framework connects to a new network to evaluate whether it satisfies this - * request. If evaluation succeeds, this callback may be followed by an {@link #onAvailable} - * callback. There is no guarantee that this new network will satisfy any requests, or that - * the network will stay connected for longer than the time necessary to evaluate it. - *

    - * Most applications should not act on this callback, and should instead use - * {@link #onAvailable}. This callback is intended for use by applications that can assist - * the framework in properly evaluating the network — for example, an application that - * can automatically log in to a captive portal without user intervention. - * - * @param network The {@link Network} of the network that is being evaluated. - * - * @hide - */ - public void onPreCheck(@NonNull Network network) {} - - /** - * Called when the framework connects and has declared a new network ready for use. - * This callback may be called more than once if the {@link Network} that is - * satisfying the request changes. - * - * @param network The {@link Network} of the satisfying network. - * @param networkCapabilities The {@link NetworkCapabilities} of the satisfying network. - * @param linkProperties The {@link LinkProperties} of the satisfying network. - * @param blocked Whether access to the {@link Network} is blocked due to system policy. - * @hide - */ - public final void onAvailable(@NonNull Network network, - @NonNull NetworkCapabilities networkCapabilities, - @NonNull LinkProperties linkProperties, @BlockedReason int blocked) { - // Internally only this method is called when a new network is available, and - // it calls the callback in the same way and order that older versions used - // to call so as not to change the behavior. - onAvailable(network, networkCapabilities, linkProperties, blocked != 0); - onBlockedStatusChanged(network, blocked); - } - - /** - * Legacy variant of onAvailable that takes a boolean blocked reason. - * - * This method has never been public API, but it's not final, so there may be apps that - * implemented it and rely on it being called. Do our best not to break them. - * Note: such apps will also get a second call to onBlockedStatusChanged immediately after - * this method is called. There does not seem to be a way to avoid this. - * TODO: add a compat check to move apps off this method, and eventually stop calling it. - * - * @hide - */ - public void onAvailable(@NonNull Network network, - @NonNull NetworkCapabilities networkCapabilities, - @NonNull LinkProperties linkProperties, boolean blocked) { - onAvailable(network); - if (!networkCapabilities.hasCapability( - NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)) { - onNetworkSuspended(network); - } - onCapabilitiesChanged(network, networkCapabilities); - onLinkPropertiesChanged(network, linkProperties); - // No call to onBlockedStatusChanged here. That is done by the caller. - } - - /** - * Called when the framework connects and has declared a new network ready for use. - * - *

    For callbacks registered with {@link #registerNetworkCallback}, multiple networks may - * be available at the same time, and onAvailable will be called for each of these as they - * appear. - * - *

    For callbacks registered with {@link #requestNetwork} and - * {@link #registerDefaultNetworkCallback}, this means the network passed as an argument - * is the new best network for this request and is now tracked by this callback ; this - * callback will no longer receive method calls about other networks that may have been - * passed to this method previously. The previously-best network may have disconnected, or - * it may still be around and the newly-best network may simply be better. - * - *

    Starting with {@link android.os.Build.VERSION_CODES#O}, this will always immediately - * be followed by a call to {@link #onCapabilitiesChanged(Network, NetworkCapabilities)} - * then by a call to {@link #onLinkPropertiesChanged(Network, LinkProperties)}, and a call - * to {@link #onBlockedStatusChanged(Network, boolean)}. - * - *

    Do NOT call {@link #getNetworkCapabilities(Network)} or - * {@link #getLinkProperties(Network)} or other synchronous ConnectivityManager methods in - * this callback as this is prone to race conditions (there is no guarantee the objects - * returned by these methods will be current). Instead, wait for a call to - * {@link #onCapabilitiesChanged(Network, NetworkCapabilities)} and - * {@link #onLinkPropertiesChanged(Network, LinkProperties)} whose arguments are guaranteed - * to be well-ordered with respect to other callbacks. - * - * @param network The {@link Network} of the satisfying network. - */ - public void onAvailable(@NonNull Network network) {} - - /** - * Called when the network is about to be lost, typically because there are no outstanding - * requests left for it. This may be paired with a {@link NetworkCallback#onAvailable} call - * with the new replacement network for graceful handover. This method is not guaranteed - * to be called before {@link NetworkCallback#onLost} is called, for example in case a - * network is suddenly disconnected. - * - *

    Do NOT call {@link #getNetworkCapabilities(Network)} or - * {@link #getLinkProperties(Network)} or other synchronous ConnectivityManager methods in - * this callback as this is prone to race conditions ; calling these methods while in a - * callback may return an outdated or even a null object. - * - * @param network The {@link Network} that is about to be lost. - * @param maxMsToLive The time in milliseconds the system intends to keep the network - * connected for graceful handover; note that the network may still - * suffer a hard loss at any time. - */ - public void onLosing(@NonNull Network network, int maxMsToLive) {} - - /** - * Called when a network disconnects or otherwise no longer satisfies this request or - * callback. - * - *

    If the callback was registered with requestNetwork() or - * registerDefaultNetworkCallback(), it will only be invoked against the last network - * returned by onAvailable() when that network is lost and no other network satisfies - * the criteria of the request. - * - *

    If the callback was registered with registerNetworkCallback() it will be called for - * each network which no longer satisfies the criteria of the callback. - * - *

    Do NOT call {@link #getNetworkCapabilities(Network)} or - * {@link #getLinkProperties(Network)} or other synchronous ConnectivityManager methods in - * this callback as this is prone to race conditions ; calling these methods while in a - * callback may return an outdated or even a null object. - * - * @param network The {@link Network} lost. - */ - public void onLost(@NonNull Network network) {} - - /** - * Called if no network is found within the timeout time specified in - * {@link #requestNetwork(NetworkRequest, NetworkCallback, int)} call or if the - * requested network request cannot be fulfilled (whether or not a timeout was - * specified). When this callback is invoked the associated - * {@link NetworkRequest} will have already been removed and released, as if - * {@link #unregisterNetworkCallback(NetworkCallback)} had been called. - */ - public void onUnavailable() {} - - /** - * Called when the network corresponding to this request changes capabilities but still - * satisfies the requested criteria. - * - *

    Starting with {@link android.os.Build.VERSION_CODES#O} this method is guaranteed - * to be called immediately after {@link #onAvailable}. - * - *

    Do NOT call {@link #getLinkProperties(Network)} or other synchronous - * ConnectivityManager methods in this callback as this is prone to race conditions : - * calling these methods while in a callback may return an outdated or even a null object. - * - * @param network The {@link Network} whose capabilities have changed. - * @param networkCapabilities The new {@link NetworkCapabilities} for this - * network. - */ - public void onCapabilitiesChanged(@NonNull Network network, - @NonNull NetworkCapabilities networkCapabilities) {} - - /** - * Called when the network corresponding to this request changes {@link LinkProperties}. - * - *

    Starting with {@link android.os.Build.VERSION_CODES#O} this method is guaranteed - * to be called immediately after {@link #onAvailable}. - * - *

    Do NOT call {@link #getNetworkCapabilities(Network)} or other synchronous - * ConnectivityManager methods in this callback as this is prone to race conditions : - * calling these methods while in a callback may return an outdated or even a null object. - * - * @param network The {@link Network} whose link properties have changed. - * @param linkProperties The new {@link LinkProperties} for this network. - */ - public void onLinkPropertiesChanged(@NonNull Network network, - @NonNull LinkProperties linkProperties) {} - - /** - * Called when the network the framework connected to for this request suspends data - * transmission temporarily. - * - *

    This generally means that while the TCP connections are still live temporarily - * network data fails to transfer. To give a specific example, this is used on cellular - * networks to mask temporary outages when driving through a tunnel, etc. In general this - * means read operations on sockets on this network will block once the buffers are - * drained, and write operations will block once the buffers are full. - * - *

    Do NOT call {@link #getNetworkCapabilities(Network)} or - * {@link #getLinkProperties(Network)} or other synchronous ConnectivityManager methods in - * this callback as this is prone to race conditions (there is no guarantee the objects - * returned by these methods will be current). - * - * @hide - */ - public void onNetworkSuspended(@NonNull Network network) {} - - /** - * Called when the network the framework connected to for this request - * returns from a {@link NetworkInfo.State#SUSPENDED} state. This should always be - * preceded by a matching {@link NetworkCallback#onNetworkSuspended} call. - - *

    Do NOT call {@link #getNetworkCapabilities(Network)} or - * {@link #getLinkProperties(Network)} or other synchronous ConnectivityManager methods in - * this callback as this is prone to race conditions : calling these methods while in a - * callback may return an outdated or even a null object. - * - * @hide - */ - public void onNetworkResumed(@NonNull Network network) {} - - /** - * Called when access to the specified network is blocked or unblocked. - * - *

    Do NOT call {@link #getNetworkCapabilities(Network)} or - * {@link #getLinkProperties(Network)} or other synchronous ConnectivityManager methods in - * this callback as this is prone to race conditions : calling these methods while in a - * callback may return an outdated or even a null object. - * - * @param network The {@link Network} whose blocked status has changed. - * @param blocked The blocked status of this {@link Network}. - */ - public void onBlockedStatusChanged(@NonNull Network network, boolean blocked) {} - - /** - * Called when access to the specified network is blocked or unblocked, or the reason for - * access being blocked changes. - * - * If a NetworkCallback object implements this method, - * {@link #onBlockedStatusChanged(Network, boolean)} will not be called. - * - *

    Do NOT call {@link #getNetworkCapabilities(Network)} or - * {@link #getLinkProperties(Network)} or other synchronous ConnectivityManager methods in - * this callback as this is prone to race conditions : calling these methods while in a - * callback may return an outdated or even a null object. - * - * @param network The {@link Network} whose blocked status has changed. - * @param blocked The blocked status of this {@link Network}. - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - public void onBlockedStatusChanged(@NonNull Network network, @BlockedReason int blocked) { - onBlockedStatusChanged(network, blocked != 0); - } - - private NetworkRequest networkRequest; - private final int mFlags; - } - - /** - * Constant error codes used by ConnectivityService to communicate about failures and errors - * across a Binder boundary. - * @hide - */ - public interface Errors { - int TOO_MANY_REQUESTS = 1; - } - - /** @hide */ - public static class TooManyRequestsException extends RuntimeException {} - - private static RuntimeException convertServiceException(ServiceSpecificException e) { - switch (e.errorCode) { - case Errors.TOO_MANY_REQUESTS: - return new TooManyRequestsException(); - default: - Log.w(TAG, "Unknown service error code " + e.errorCode); - return new RuntimeException(e); - } - } - - /** @hide */ - public static final int CALLBACK_PRECHECK = 1; - /** @hide */ - public static final int CALLBACK_AVAILABLE = 2; - /** @hide arg1 = TTL */ - public static final int CALLBACK_LOSING = 3; - /** @hide */ - public static final int CALLBACK_LOST = 4; - /** @hide */ - public static final int CALLBACK_UNAVAIL = 5; - /** @hide */ - public static final int CALLBACK_CAP_CHANGED = 6; - /** @hide */ - public static final int CALLBACK_IP_CHANGED = 7; - /** @hide obj = NetworkCapabilities, arg1 = seq number */ - private static final int EXPIRE_LEGACY_REQUEST = 8; - /** @hide */ - public static final int CALLBACK_SUSPENDED = 9; - /** @hide */ - public static final int CALLBACK_RESUMED = 10; - /** @hide */ - public static final int CALLBACK_BLK_CHANGED = 11; - - /** @hide */ - public static String getCallbackName(int whichCallback) { - switch (whichCallback) { - case CALLBACK_PRECHECK: return "CALLBACK_PRECHECK"; - case CALLBACK_AVAILABLE: return "CALLBACK_AVAILABLE"; - case CALLBACK_LOSING: return "CALLBACK_LOSING"; - case CALLBACK_LOST: return "CALLBACK_LOST"; - case CALLBACK_UNAVAIL: return "CALLBACK_UNAVAIL"; - case CALLBACK_CAP_CHANGED: return "CALLBACK_CAP_CHANGED"; - case CALLBACK_IP_CHANGED: return "CALLBACK_IP_CHANGED"; - case EXPIRE_LEGACY_REQUEST: return "EXPIRE_LEGACY_REQUEST"; - case CALLBACK_SUSPENDED: return "CALLBACK_SUSPENDED"; - case CALLBACK_RESUMED: return "CALLBACK_RESUMED"; - case CALLBACK_BLK_CHANGED: return "CALLBACK_BLK_CHANGED"; - default: - return Integer.toString(whichCallback); - } - } - - private class CallbackHandler extends Handler { - private static final String TAG = "ConnectivityManager.CallbackHandler"; - private static final boolean DBG = false; - - CallbackHandler(Looper looper) { - super(looper); - } - - CallbackHandler(Handler handler) { - this(Objects.requireNonNull(handler, "Handler cannot be null.").getLooper()); - } - - @Override - public void handleMessage(Message message) { - if (message.what == EXPIRE_LEGACY_REQUEST) { - expireRequest((NetworkCapabilities) message.obj, message.arg1); - return; - } - - final NetworkRequest request = getObject(message, NetworkRequest.class); - final Network network = getObject(message, Network.class); - final NetworkCallback callback; - synchronized (sCallbacks) { - callback = sCallbacks.get(request); - if (callback == null) { - Log.w(TAG, - "callback not found for " + getCallbackName(message.what) + " message"); - return; - } - if (message.what == CALLBACK_UNAVAIL) { - sCallbacks.remove(request); - callback.networkRequest = ALREADY_UNREGISTERED; - } - } - if (DBG) { - Log.d(TAG, getCallbackName(message.what) + " for network " + network); - } - - switch (message.what) { - case CALLBACK_PRECHECK: { - callback.onPreCheck(network); - break; - } - case CALLBACK_AVAILABLE: { - NetworkCapabilities cap = getObject(message, NetworkCapabilities.class); - LinkProperties lp = getObject(message, LinkProperties.class); - callback.onAvailable(network, cap, lp, message.arg1); - break; - } - case CALLBACK_LOSING: { - callback.onLosing(network, message.arg1); - break; - } - case CALLBACK_LOST: { - callback.onLost(network); - break; - } - case CALLBACK_UNAVAIL: { - callback.onUnavailable(); - break; - } - case CALLBACK_CAP_CHANGED: { - NetworkCapabilities cap = getObject(message, NetworkCapabilities.class); - callback.onCapabilitiesChanged(network, cap); - break; - } - case CALLBACK_IP_CHANGED: { - LinkProperties lp = getObject(message, LinkProperties.class); - callback.onLinkPropertiesChanged(network, lp); - break; - } - case CALLBACK_SUSPENDED: { - callback.onNetworkSuspended(network); - break; - } - case CALLBACK_RESUMED: { - callback.onNetworkResumed(network); - break; - } - case CALLBACK_BLK_CHANGED: { - callback.onBlockedStatusChanged(network, message.arg1); - } - } - } - - private T getObject(Message msg, Class c) { - return (T) msg.getData().getParcelable(c.getSimpleName()); - } - } - - private CallbackHandler getDefaultHandler() { - synchronized (sCallbacks) { - if (sCallbackHandler == null) { - sCallbackHandler = new CallbackHandler(ConnectivityThread.getInstanceLooper()); - } - return sCallbackHandler; - } - } - - private static final HashMap sCallbacks = new HashMap<>(); - private static CallbackHandler sCallbackHandler; - - private NetworkRequest sendRequestForNetwork(int asUid, NetworkCapabilities need, - NetworkCallback callback, int timeoutMs, NetworkRequest.Type reqType, int legacyType, - CallbackHandler handler) { - printStackTrace(); - checkCallbackNotNull(callback); - if (reqType != TRACK_DEFAULT && reqType != TRACK_SYSTEM_DEFAULT && need == null) { - throw new IllegalArgumentException("null NetworkCapabilities"); - } - final NetworkRequest request; - final String callingPackageName = mContext.getOpPackageName(); - try { - synchronized(sCallbacks) { - if (callback.networkRequest != null - && callback.networkRequest != ALREADY_UNREGISTERED) { - // TODO: throw exception instead and enforce 1:1 mapping of callbacks - // and requests (http://b/20701525). - Log.e(TAG, "NetworkCallback was already registered"); - } - Messenger messenger = new Messenger(handler); - Binder binder = new Binder(); - final int callbackFlags = callback.mFlags; - if (reqType == LISTEN) { - request = mService.listenForNetwork( - need, messenger, binder, callbackFlags, callingPackageName, - getAttributionTag()); - } else { - request = mService.requestNetwork( - asUid, need, reqType.ordinal(), messenger, timeoutMs, binder, - legacyType, callbackFlags, callingPackageName, getAttributionTag()); - } - if (request != null) { - sCallbacks.put(request, callback); - } - callback.networkRequest = request; - } - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } catch (ServiceSpecificException e) { - throw convertServiceException(e); - } - return request; - } - - private NetworkRequest sendRequestForNetwork(NetworkCapabilities need, NetworkCallback callback, - int timeoutMs, NetworkRequest.Type reqType, int legacyType, CallbackHandler handler) { - return sendRequestForNetwork(Process.INVALID_UID, need, callback, timeoutMs, reqType, - legacyType, handler); - } - - /** - * Helper function to request a network with a particular legacy type. - * - * This API is only for use in internal system code that requests networks with legacy type and - * relies on CONNECTIVITY_ACTION broadcasts instead of NetworkCallbacks. New caller should use - * {@link #requestNetwork(NetworkRequest, NetworkCallback, Handler)} instead. - * - * @param request {@link NetworkRequest} describing this request. - * @param timeoutMs The time in milliseconds to attempt looking for a suitable network - * before {@link NetworkCallback#onUnavailable()} is called. The timeout must - * be a positive value (i.e. >0). - * @param legacyType to specify the network type(#TYPE_*). - * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. - * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note - * the callback must not be shared - it uniquely specifies this request. - * - * @hide - */ - @SystemApi - @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) - public void requestNetwork(@NonNull NetworkRequest request, - int timeoutMs, int legacyType, @NonNull Handler handler, - @NonNull NetworkCallback networkCallback) { - if (legacyType == TYPE_NONE) { - throw new IllegalArgumentException("TYPE_NONE is meaningless legacy type"); - } - CallbackHandler cbHandler = new CallbackHandler(handler); - NetworkCapabilities nc = request.networkCapabilities; - sendRequestForNetwork(nc, networkCallback, timeoutMs, REQUEST, legacyType, cbHandler); - } - - /** - * Request a network to satisfy a set of {@link NetworkCapabilities}. - * - *

    This method will attempt to find the best network that matches the passed - * {@link NetworkRequest}, and to bring up one that does if none currently satisfies the - * criteria. The platform will evaluate which network is the best at its own discretion. - * Throughput, latency, cost per byte, policy, user preference and other considerations - * may be factored in the decision of what is considered the best network. - * - *

    As long as this request is outstanding, the platform will try to maintain the best network - * matching this request, while always attempting to match the request to a better network if - * possible. If a better match is found, the platform will switch this request to the now-best - * network and inform the app of the newly best network by invoking - * {@link NetworkCallback#onAvailable(Network)} on the provided callback. Note that the platform - * will not try to maintain any other network than the best one currently matching the request: - * a network not matching any network request may be disconnected at any time. - * - *

    For example, an application could use this method to obtain a connected cellular network - * even if the device currently has a data connection over Ethernet. This may cause the cellular - * radio to consume additional power. Or, an application could inform the system that it wants - * a network supporting sending MMSes and have the system let it know about the currently best - * MMS-supporting network through the provided {@link NetworkCallback}. - * - *

    The status of the request can be followed by listening to the various callbacks described - * in {@link NetworkCallback}. The {@link Network} object passed to the callback methods can be - * used to direct traffic to the network (although accessing some networks may be subject to - * holding specific permissions). Callers will learn about the specific characteristics of the - * network through - * {@link NetworkCallback#onCapabilitiesChanged(Network, NetworkCapabilities)} and - * {@link NetworkCallback#onLinkPropertiesChanged(Network, LinkProperties)}. The methods of the - * provided {@link NetworkCallback} will only be invoked due to changes in the best network - * matching the request at any given time; therefore when a better network matching the request - * becomes available, the {@link NetworkCallback#onAvailable(Network)} method is called - * with the new network after which no further updates are given about the previously-best - * network, unless it becomes the best again at some later time. All callbacks are invoked - * in order on the same thread, which by default is a thread created by the framework running - * in the app. - * {@see #requestNetwork(NetworkRequest, NetworkCallback, Handler)} to change where the - * callbacks are invoked. - * - *

    This{@link NetworkRequest} will live until released via - * {@link #unregisterNetworkCallback(NetworkCallback)} or the calling application exits, at - * which point the system may let go of the network at any time. - * - *

    A version of this method which takes a timeout is - * {@link #requestNetwork(NetworkRequest, NetworkCallback, int)}, that an app can use to only - * wait for a limited amount of time for the network to become unavailable. - * - *

    It is presently unsupported to request a network with mutable - * {@link NetworkCapabilities} such as - * {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} or - * {@link NetworkCapabilities#NET_CAPABILITY_CAPTIVE_PORTAL} - * as these {@code NetworkCapabilities} represent states that a particular - * network may never attain, and whether a network will attain these states - * is unknown prior to bringing up the network so the framework does not - * know how to go about satisfying a request with these capabilities. - * - *

    This method requires the caller to hold either the - * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission - * or the ability to modify system settings as determined by - * {@link android.provider.Settings.System#canWrite}.

    - * - *

    To avoid performance issues due to apps leaking callbacks, the system will limit the - * number of outstanding requests to 100 per app (identified by their UID), shared with - * all variants of this method, of {@link #registerNetworkCallback} as well as - * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}. - * Requesting a network with this method will count toward this limit. If this limit is - * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources, - * make sure to unregister the callbacks with - * {@link #unregisterNetworkCallback(NetworkCallback)}. - * - * @param request {@link NetworkRequest} describing this request. - * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note - * the callback must not be shared - it uniquely specifies this request. - * The callback is invoked on the default internal Handler. - * @throws IllegalArgumentException if {@code request} contains invalid network capabilities. - * @throws SecurityException if missing the appropriate permissions. - * @throws RuntimeException if the app already has too many callbacks registered. - */ - public void requestNetwork(@NonNull NetworkRequest request, - @NonNull NetworkCallback networkCallback) { - requestNetwork(request, networkCallback, getDefaultHandler()); - } - - /** - * Request a network to satisfy a set of {@link NetworkCapabilities}. - * - * This method behaves identically to {@link #requestNetwork(NetworkRequest, NetworkCallback)} - * but runs all the callbacks on the passed Handler. - * - *

    This method has the same permission requirements as - * {@link #requestNetwork(NetworkRequest, NetworkCallback)}, is subject to the same limitations, - * and throws the same exceptions in the same conditions. - * - * @param request {@link NetworkRequest} describing this request. - * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note - * the callback must not be shared - it uniquely specifies this request. - * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. - */ - public void requestNetwork(@NonNull NetworkRequest request, - @NonNull NetworkCallback networkCallback, @NonNull Handler handler) { - CallbackHandler cbHandler = new CallbackHandler(handler); - NetworkCapabilities nc = request.networkCapabilities; - sendRequestForNetwork(nc, networkCallback, 0, REQUEST, TYPE_NONE, cbHandler); - } - - /** - * Request a network to satisfy a set of {@link NetworkCapabilities}, limited - * by a timeout. - * - * This function behaves identically to the non-timed-out version - * {@link #requestNetwork(NetworkRequest, NetworkCallback)}, but if a suitable network - * is not found within the given time (in milliseconds) the - * {@link NetworkCallback#onUnavailable()} callback is called. The request can still be - * released normally by calling {@link #unregisterNetworkCallback(NetworkCallback)} but does - * not have to be released if timed-out (it is automatically released). Unregistering a - * request that timed out is not an error. - * - *

    Do not use this method to poll for the existence of specific networks (e.g. with a small - * timeout) - {@link #registerNetworkCallback(NetworkRequest, NetworkCallback)} is provided - * for that purpose. Calling this method will attempt to bring up the requested network. - * - *

    This method has the same permission requirements as - * {@link #requestNetwork(NetworkRequest, NetworkCallback)}, is subject to the same limitations, - * and throws the same exceptions in the same conditions. - * - * @param request {@link NetworkRequest} describing this request. - * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note - * the callback must not be shared - it uniquely specifies this request. - * @param timeoutMs The time in milliseconds to attempt looking for a suitable network - * before {@link NetworkCallback#onUnavailable()} is called. The timeout must - * be a positive value (i.e. >0). - */ - public void requestNetwork(@NonNull NetworkRequest request, - @NonNull NetworkCallback networkCallback, int timeoutMs) { - checkTimeout(timeoutMs); - NetworkCapabilities nc = request.networkCapabilities; - sendRequestForNetwork(nc, networkCallback, timeoutMs, REQUEST, TYPE_NONE, - getDefaultHandler()); - } - - /** - * Request a network to satisfy a set of {@link NetworkCapabilities}, limited - * by a timeout. - * - * This method behaves identically to - * {@link #requestNetwork(NetworkRequest, NetworkCallback, int)} but runs all the callbacks - * on the passed Handler. - * - *

    This method has the same permission requirements as - * {@link #requestNetwork(NetworkRequest, NetworkCallback)}, is subject to the same limitations, - * and throws the same exceptions in the same conditions. - * - * @param request {@link NetworkRequest} describing this request. - * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note - * the callback must not be shared - it uniquely specifies this request. - * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. - * @param timeoutMs The time in milliseconds to attempt looking for a suitable network - * before {@link NetworkCallback#onUnavailable} is called. - */ - public void requestNetwork(@NonNull NetworkRequest request, - @NonNull NetworkCallback networkCallback, @NonNull Handler handler, int timeoutMs) { - checkTimeout(timeoutMs); - CallbackHandler cbHandler = new CallbackHandler(handler); - NetworkCapabilities nc = request.networkCapabilities; - sendRequestForNetwork(nc, networkCallback, timeoutMs, REQUEST, TYPE_NONE, cbHandler); - } - - /** - * The lookup key for a {@link Network} object included with the intent after - * successfully finding a network for the applications request. Retrieve it with - * {@link android.content.Intent#getParcelableExtra(String)}. - *

    - * Note that if you intend to invoke {@link Network#openConnection(java.net.URL)} - * then you must get a ConnectivityManager instance before doing so. - */ - public static final String EXTRA_NETWORK = "android.net.extra.NETWORK"; - - /** - * The lookup key for a {@link NetworkRequest} object included with the intent after - * successfully finding a network for the applications request. Retrieve it with - * {@link android.content.Intent#getParcelableExtra(String)}. - */ - public static final String EXTRA_NETWORK_REQUEST = "android.net.extra.NETWORK_REQUEST"; - - - /** - * Request a network to satisfy a set of {@link NetworkCapabilities}. - * - * This function behaves identically to the version that takes a NetworkCallback, but instead - * of {@link NetworkCallback} a {@link PendingIntent} is used. This means - * the request may outlive the calling application and get called back when a suitable - * network is found. - *

    - * The operation is an Intent broadcast that goes to a broadcast receiver that - * you registered with {@link Context#registerReceiver} or through the - * <receiver> tag in an AndroidManifest.xml file - *

    - * The operation Intent is delivered with two extras, a {@link Network} typed - * extra called {@link #EXTRA_NETWORK} and a {@link NetworkRequest} - * typed extra called {@link #EXTRA_NETWORK_REQUEST} containing - * the original requests parameters. It is important to create a new, - * {@link NetworkCallback} based request before completing the processing of the - * Intent to reserve the network or it will be released shortly after the Intent - * is processed. - *

    - * If there is already a request for this Intent registered (with the equality of - * two Intents defined by {@link Intent#filterEquals}), then it will be removed and - * replaced by this one, effectively releasing the previous {@link NetworkRequest}. - *

    - * The request may be released normally by calling - * {@link #releaseNetworkRequest(android.app.PendingIntent)}. - *

    It is presently unsupported to request a network with either - * {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} or - * {@link NetworkCapabilities#NET_CAPABILITY_CAPTIVE_PORTAL} - * as these {@code NetworkCapabilities} represent states that a particular - * network may never attain, and whether a network will attain these states - * is unknown prior to bringing up the network so the framework does not - * know how to go about satisfying a request with these capabilities. - * - *

    To avoid performance issues due to apps leaking callbacks, the system will limit the - * number of outstanding requests to 100 per app (identified by their UID), shared with - * all variants of this method, of {@link #registerNetworkCallback} as well as - * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}. - * Requesting a network with this method will count toward this limit. If this limit is - * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources, - * make sure to unregister the callbacks with {@link #unregisterNetworkCallback(PendingIntent)} - * or {@link #releaseNetworkRequest(PendingIntent)}. - * - *

    This method requires the caller to hold either the - * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission - * or the ability to modify system settings as determined by - * {@link android.provider.Settings.System#canWrite}.

    - * - * @param request {@link NetworkRequest} describing this request. - * @param operation Action to perform when the network is available (corresponds - * to the {@link NetworkCallback#onAvailable} call. Typically - * comes from {@link PendingIntent#getBroadcast}. Cannot be null. - * @throws IllegalArgumentException if {@code request} contains invalid network capabilities. - * @throws SecurityException if missing the appropriate permissions. - * @throws RuntimeException if the app already has too many callbacks registered. - */ - public void requestNetwork(@NonNull NetworkRequest request, - @NonNull PendingIntent operation) { - printStackTrace(); - checkPendingIntentNotNull(operation); - try { - mService.pendingRequestForNetwork( - request.networkCapabilities, operation, mContext.getOpPackageName(), - getAttributionTag()); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } catch (ServiceSpecificException e) { - throw convertServiceException(e); - } - } - - /** - * Removes a request made via {@link #requestNetwork(NetworkRequest, android.app.PendingIntent)} - *

    - * This method has the same behavior as - * {@link #unregisterNetworkCallback(android.app.PendingIntent)} with respect to - * releasing network resources and disconnecting. - * - * @param operation A PendingIntent equal (as defined by {@link Intent#filterEquals}) to the - * PendingIntent passed to - * {@link #requestNetwork(NetworkRequest, android.app.PendingIntent)} with the - * corresponding NetworkRequest you'd like to remove. Cannot be null. - */ - public void releaseNetworkRequest(@NonNull PendingIntent operation) { - printStackTrace(); - checkPendingIntentNotNull(operation); - try { - mService.releasePendingNetworkRequest(operation); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - private static void checkPendingIntentNotNull(PendingIntent intent) { - Objects.requireNonNull(intent, "PendingIntent cannot be null."); - } - - private static void checkCallbackNotNull(NetworkCallback callback) { - Objects.requireNonNull(callback, "null NetworkCallback"); - } - - private static void checkTimeout(int timeoutMs) { - if (timeoutMs <= 0) { - throw new IllegalArgumentException("timeoutMs must be strictly positive."); - } - } - - /** - * Registers to receive notifications about all networks which satisfy the given - * {@link NetworkRequest}. The callbacks will continue to be called until - * either the application exits or {@link #unregisterNetworkCallback(NetworkCallback)} is - * called. - * - *

    To avoid performance issues due to apps leaking callbacks, the system will limit the - * number of outstanding requests to 100 per app (identified by their UID), shared with - * all variants of this method, of {@link #requestNetwork} as well as - * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}. - * Requesting a network with this method will count toward this limit. If this limit is - * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources, - * make sure to unregister the callbacks with - * {@link #unregisterNetworkCallback(NetworkCallback)}. - * - * @param request {@link NetworkRequest} describing this request. - * @param networkCallback The {@link NetworkCallback} that the system will call as suitable - * networks change state. - * The callback is invoked on the default internal Handler. - * @throws RuntimeException if the app already has too many callbacks registered. - */ - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - public void registerNetworkCallback(@NonNull NetworkRequest request, - @NonNull NetworkCallback networkCallback) { - registerNetworkCallback(request, networkCallback, getDefaultHandler()); - } - - /** - * Registers to receive notifications about all networks which satisfy the given - * {@link NetworkRequest}. The callbacks will continue to be called until - * either the application exits or {@link #unregisterNetworkCallback(NetworkCallback)} is - * called. - * - *

    To avoid performance issues due to apps leaking callbacks, the system will limit the - * number of outstanding requests to 100 per app (identified by their UID), shared with - * all variants of this method, of {@link #requestNetwork} as well as - * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}. - * Requesting a network with this method will count toward this limit. If this limit is - * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources, - * make sure to unregister the callbacks with - * {@link #unregisterNetworkCallback(NetworkCallback)}. - * - * - * @param request {@link NetworkRequest} describing this request. - * @param networkCallback The {@link NetworkCallback} that the system will call as suitable - * networks change state. - * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. - * @throws RuntimeException if the app already has too many callbacks registered. - */ - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - public void registerNetworkCallback(@NonNull NetworkRequest request, - @NonNull NetworkCallback networkCallback, @NonNull Handler handler) { - CallbackHandler cbHandler = new CallbackHandler(handler); - NetworkCapabilities nc = request.networkCapabilities; - sendRequestForNetwork(nc, networkCallback, 0, LISTEN, TYPE_NONE, cbHandler); - } - - /** - * Registers a PendingIntent to be sent when a network is available which satisfies the given - * {@link NetworkRequest}. - * - * This function behaves identically to the version that takes a NetworkCallback, but instead - * of {@link NetworkCallback} a {@link PendingIntent} is used. This means - * the request may outlive the calling application and get called back when a suitable - * network is found. - *

    - * The operation is an Intent broadcast that goes to a broadcast receiver that - * you registered with {@link Context#registerReceiver} or through the - * <receiver> tag in an AndroidManifest.xml file - *

    - * The operation Intent is delivered with two extras, a {@link Network} typed - * extra called {@link #EXTRA_NETWORK} and a {@link NetworkRequest} - * typed extra called {@link #EXTRA_NETWORK_REQUEST} containing - * the original requests parameters. - *

    - * If there is already a request for this Intent registered (with the equality of - * two Intents defined by {@link Intent#filterEquals}), then it will be removed and - * replaced by this one, effectively releasing the previous {@link NetworkRequest}. - *

    - * The request may be released normally by calling - * {@link #unregisterNetworkCallback(android.app.PendingIntent)}. - * - *

    To avoid performance issues due to apps leaking callbacks, the system will limit the - * number of outstanding requests to 100 per app (identified by their UID), shared with - * all variants of this method, of {@link #requestNetwork} as well as - * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}. - * Requesting a network with this method will count toward this limit. If this limit is - * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources, - * make sure to unregister the callbacks with {@link #unregisterNetworkCallback(PendingIntent)} - * or {@link #releaseNetworkRequest(PendingIntent)}. - * - * @param request {@link NetworkRequest} describing this request. - * @param operation Action to perform when the network is available (corresponds - * to the {@link NetworkCallback#onAvailable} call. Typically - * comes from {@link PendingIntent#getBroadcast}. Cannot be null. - * @throws RuntimeException if the app already has too many callbacks registered. - */ - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - public void registerNetworkCallback(@NonNull NetworkRequest request, - @NonNull PendingIntent operation) { - printStackTrace(); - checkPendingIntentNotNull(operation); - try { - mService.pendingListenForNetwork( - request.networkCapabilities, operation, mContext.getOpPackageName(), - getAttributionTag()); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } catch (ServiceSpecificException e) { - throw convertServiceException(e); - } - } - - /** - * Registers to receive notifications about changes in the application's default network. This - * may be a physical network or a virtual network, such as a VPN that applies to the - * application. The callbacks will continue to be called until either the application exits or - * {@link #unregisterNetworkCallback(NetworkCallback)} is called. - * - *

    To avoid performance issues due to apps leaking callbacks, the system will limit the - * number of outstanding requests to 100 per app (identified by their UID), shared with - * all variants of this method, of {@link #requestNetwork} as well as - * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}. - * Requesting a network with this method will count toward this limit. If this limit is - * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources, - * make sure to unregister the callbacks with - * {@link #unregisterNetworkCallback(NetworkCallback)}. - * - * @param networkCallback The {@link NetworkCallback} that the system will call as the - * application's default network changes. - * The callback is invoked on the default internal Handler. - * @throws RuntimeException if the app already has too many callbacks registered. - */ - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - public void registerDefaultNetworkCallback(@NonNull NetworkCallback networkCallback) { - registerDefaultNetworkCallback(networkCallback, getDefaultHandler()); - } - - /** - * Registers to receive notifications about changes in the application's default network. This - * may be a physical network or a virtual network, such as a VPN that applies to the - * application. The callbacks will continue to be called until either the application exits or - * {@link #unregisterNetworkCallback(NetworkCallback)} is called. - * - *

    To avoid performance issues due to apps leaking callbacks, the system will limit the - * number of outstanding requests to 100 per app (identified by their UID), shared with - * all variants of this method, of {@link #requestNetwork} as well as - * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}. - * Requesting a network with this method will count toward this limit. If this limit is - * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources, - * make sure to unregister the callbacks with - * {@link #unregisterNetworkCallback(NetworkCallback)}. - * - * @param networkCallback The {@link NetworkCallback} that the system will call as the - * application's default network changes. - * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. - * @throws RuntimeException if the app already has too many callbacks registered. - */ - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - public void registerDefaultNetworkCallback(@NonNull NetworkCallback networkCallback, - @NonNull Handler handler) { - registerDefaultNetworkCallbackForUid(Process.INVALID_UID, networkCallback, handler); - } - - /** - * Registers to receive notifications about changes in the default network for the specified - * UID. This may be a physical network or a virtual network, such as a VPN that applies to the - * UID. The callbacks will continue to be called until either the application exits or - * {@link #unregisterNetworkCallback(NetworkCallback)} is called. - * - *

    To avoid performance issues due to apps leaking callbacks, the system will limit the - * number of outstanding requests to 100 per app (identified by their UID), shared with - * all variants of this method, of {@link #requestNetwork} as well as - * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}. - * Requesting a network with this method will count toward this limit. If this limit is - * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources, - * make sure to unregister the callbacks with - * {@link #unregisterNetworkCallback(NetworkCallback)}. - * - * @param uid the UID for which to track default network changes. - * @param networkCallback The {@link NetworkCallback} that the system will call as the - * UID's default network changes. - * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. - * @throws RuntimeException if the app already has too many callbacks registered. - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - @SuppressLint({"ExecutorRegistration", "PairedRegistration"}) - @RequiresPermission(anyOf = { - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, - android.Manifest.permission.NETWORK_SETTINGS}) - public void registerDefaultNetworkCallbackForUid(int uid, - @NonNull NetworkCallback networkCallback, @NonNull Handler handler) { - CallbackHandler cbHandler = new CallbackHandler(handler); - sendRequestForNetwork(uid, null /* need */, networkCallback, 0 /* timeoutMs */, - TRACK_DEFAULT, TYPE_NONE, cbHandler); - } - - /** - * Registers to receive notifications about changes in the system default network. The callbacks - * will continue to be called until either the application exits or - * {@link #unregisterNetworkCallback(NetworkCallback)} is called. - * - * This method should not be used to determine networking state seen by applications, because in - * many cases, most or even all application traffic may not use the default network directly, - * and traffic from different applications may go on different networks by default. As an - * example, if a VPN is connected, traffic from all applications might be sent through the VPN - * and not onto the system default network. Applications or system components desiring to do - * determine network state as seen by applications should use other methods such as - * {@link #registerDefaultNetworkCallback(NetworkCallback, Handler)}. - * - *

    To avoid performance issues due to apps leaking callbacks, the system will limit the - * number of outstanding requests to 100 per app (identified by their UID), shared with - * all variants of this method, of {@link #requestNetwork} as well as - * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}. - * Requesting a network with this method will count toward this limit. If this limit is - * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources, - * make sure to unregister the callbacks with - * {@link #unregisterNetworkCallback(NetworkCallback)}. - * - * @param networkCallback The {@link NetworkCallback} that the system will call as the - * system default network changes. - * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. - * @throws RuntimeException if the app already has too many callbacks registered. - * - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - @SuppressLint({"ExecutorRegistration", "PairedRegistration"}) - @RequiresPermission(anyOf = { - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, - android.Manifest.permission.NETWORK_SETTINGS}) - public void registerSystemDefaultNetworkCallback(@NonNull NetworkCallback networkCallback, - @NonNull Handler handler) { - CallbackHandler cbHandler = new CallbackHandler(handler); - sendRequestForNetwork(null /* NetworkCapabilities need */, networkCallback, 0, - TRACK_SYSTEM_DEFAULT, TYPE_NONE, cbHandler); - } - - /** - * Registers to receive notifications about the best matching network which satisfy the given - * {@link NetworkRequest}. The callbacks will continue to be called until - * either the application exits or {@link #unregisterNetworkCallback(NetworkCallback)} is - * called. - * - *

    To avoid performance issues due to apps leaking callbacks, the system will limit the - * number of outstanding requests to 100 per app (identified by their UID), shared with - * {@link #registerNetworkCallback} and its variants and {@link #requestNetwork} as well as - * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}. - * Requesting a network with this method will count toward this limit. If this limit is - * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources, - * make sure to unregister the callbacks with - * {@link #unregisterNetworkCallback(NetworkCallback)}. - * - * - * @param request {@link NetworkRequest} describing this request. - * @param networkCallback The {@link NetworkCallback} that the system will call as suitable - * networks change state. - * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. - * @throws RuntimeException if the app already has too many callbacks registered. - */ - @SuppressLint("ExecutorRegistration") - public void registerBestMatchingNetworkCallback(@NonNull NetworkRequest request, - @NonNull NetworkCallback networkCallback, @NonNull Handler handler) { - final NetworkCapabilities nc = request.networkCapabilities; - final CallbackHandler cbHandler = new CallbackHandler(handler); - sendRequestForNetwork(nc, networkCallback, 0, LISTEN_FOR_BEST, TYPE_NONE, cbHandler); - } - - /** - * Requests bandwidth update for a given {@link Network} and returns whether the update request - * is accepted by ConnectivityService. Once accepted, ConnectivityService will poll underlying - * network connection for updated bandwidth information. The caller will be notified via - * {@link ConnectivityManager.NetworkCallback} if there is an update. Notice that this - * method assumes that the caller has previously called - * {@link #registerNetworkCallback(NetworkRequest, NetworkCallback)} to listen for network - * changes. - * - * @param network {@link Network} specifying which network you're interested. - * @return {@code true} on success, {@code false} if the {@link Network} is no longer valid. - */ - public boolean requestBandwidthUpdate(@NonNull Network network) { - try { - return mService.requestBandwidthUpdate(network); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Unregisters a {@code NetworkCallback} and possibly releases networks originating from - * {@link #requestNetwork(NetworkRequest, NetworkCallback)} and - * {@link #registerNetworkCallback(NetworkRequest, NetworkCallback)} calls. - * If the given {@code NetworkCallback} had previously been used with - * {@code #requestNetwork}, any networks that had been connected to only to satisfy that request - * will be disconnected. - * - * Notifications that would have triggered that {@code NetworkCallback} will immediately stop - * triggering it as soon as this call returns. - * - * @param networkCallback The {@link NetworkCallback} used when making the request. - */ - public void unregisterNetworkCallback(@NonNull NetworkCallback networkCallback) { - printStackTrace(); - checkCallbackNotNull(networkCallback); - final List reqs = new ArrayList<>(); - // Find all requests associated to this callback and stop callback triggers immediately. - // Callback is reusable immediately. http://b/20701525, http://b/35921499. - synchronized (sCallbacks) { - if (networkCallback.networkRequest == null) { - throw new IllegalArgumentException("NetworkCallback was not registered"); - } - if (networkCallback.networkRequest == ALREADY_UNREGISTERED) { - Log.d(TAG, "NetworkCallback was already unregistered"); - return; - } - for (Map.Entry e : sCallbacks.entrySet()) { - if (e.getValue() == networkCallback) { - reqs.add(e.getKey()); - } - } - // TODO: throw exception if callback was registered more than once (http://b/20701525). - for (NetworkRequest r : reqs) { - try { - mService.releaseNetworkRequest(r); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - // Only remove mapping if rpc was successful. - sCallbacks.remove(r); - } - networkCallback.networkRequest = ALREADY_UNREGISTERED; - } - } - - /** - * Unregisters a callback previously registered via - * {@link #registerNetworkCallback(NetworkRequest, android.app.PendingIntent)}. - * - * @param operation A PendingIntent equal (as defined by {@link Intent#filterEquals}) to the - * PendingIntent passed to - * {@link #registerNetworkCallback(NetworkRequest, android.app.PendingIntent)}. - * Cannot be null. - */ - public void unregisterNetworkCallback(@NonNull PendingIntent operation) { - releaseNetworkRequest(operation); - } - - /** - * Informs the system whether it should switch to {@code network} regardless of whether it is - * validated or not. If {@code accept} is true, and the network was explicitly selected by the - * user (e.g., by selecting a Wi-Fi network in the Settings app), then the network will become - * the system default network regardless of any other network that's currently connected. If - * {@code always} is true, then the choice is remembered, so that the next time the user - * connects to this network, the system will switch to it. - * - * @param network The network to accept. - * @param accept Whether to accept the network even if unvalidated. - * @param always Whether to remember this choice in the future. - * - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - @RequiresPermission(anyOf = { - android.Manifest.permission.NETWORK_SETTINGS, - android.Manifest.permission.NETWORK_SETUP_WIZARD, - android.Manifest.permission.NETWORK_STACK, - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) - public void setAcceptUnvalidated(@NonNull Network network, boolean accept, boolean always) { - try { - mService.setAcceptUnvalidated(network, accept, always); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Informs the system whether it should consider the network as validated even if it only has - * partial connectivity. If {@code accept} is true, then the network will be considered as - * validated even if connectivity is only partial. If {@code always} is true, then the choice - * is remembered, so that the next time the user connects to this network, the system will - * switch to it. - * - * @param network The network to accept. - * @param accept Whether to consider the network as validated even if it has partial - * connectivity. - * @param always Whether to remember this choice in the future. - * - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - @RequiresPermission(anyOf = { - android.Manifest.permission.NETWORK_SETTINGS, - android.Manifest.permission.NETWORK_SETUP_WIZARD, - android.Manifest.permission.NETWORK_STACK, - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) - public void setAcceptPartialConnectivity(@NonNull Network network, boolean accept, - boolean always) { - try { - mService.setAcceptPartialConnectivity(network, accept, always); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Informs the system to penalize {@code network}'s score when it becomes unvalidated. This is - * only meaningful if the system is configured not to penalize such networks, e.g., if the - * {@code config_networkAvoidBadWifi} configuration variable is set to 0 and the {@code - * NETWORK_AVOID_BAD_WIFI setting is unset}. - * - * @param network The network to accept. - * - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - @RequiresPermission(anyOf = { - android.Manifest.permission.NETWORK_SETTINGS, - android.Manifest.permission.NETWORK_SETUP_WIZARD, - android.Manifest.permission.NETWORK_STACK, - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) - public void setAvoidUnvalidated(@NonNull Network network) { - try { - mService.setAvoidUnvalidated(network); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Requests that the system open the captive portal app on the specified network. - * - *

    This is to be used on networks where a captive portal was detected, as per - * {@link NetworkCapabilities#NET_CAPABILITY_CAPTIVE_PORTAL}. - * - * @param network The network to log into. - * - * @hide - */ - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - @RequiresPermission(anyOf = { - android.Manifest.permission.NETWORK_SETTINGS, - android.Manifest.permission.NETWORK_STACK, - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK - }) - public void startCaptivePortalApp(@NonNull Network network) { - try { - mService.startCaptivePortalApp(network); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Requests that the system open the captive portal app with the specified extras. - * - *

    This endpoint is exclusively for use by the NetworkStack and is protected by the - * corresponding permission. - * @param network Network on which the captive portal was detected. - * @param appExtras Extras to include in the app start intent. - * @hide - */ - @SystemApi - @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) - public void startCaptivePortalApp(@NonNull Network network, @NonNull Bundle appExtras) { - try { - mService.startCaptivePortalAppInternal(network, appExtras); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Determine whether the device is configured to avoid bad wifi. - * @hide - */ - @SystemApi - @RequiresPermission(anyOf = { - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, - android.Manifest.permission.NETWORK_STACK}) - public boolean shouldAvoidBadWifi() { - try { - return mService.shouldAvoidBadWifi(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * It is acceptable to briefly use multipath data to provide seamless connectivity for - * time-sensitive user-facing operations when the system default network is temporarily - * unresponsive. The amount of data should be limited (less than one megabyte for every call to - * this method), and the operation should be infrequent to ensure that data usage is limited. - * - * An example of such an operation might be a time-sensitive foreground activity, such as a - * voice command, that the user is performing while walking out of range of a Wi-Fi network. - */ - public static final int MULTIPATH_PREFERENCE_HANDOVER = 1 << 0; - - /** - * It is acceptable to use small amounts of multipath data on an ongoing basis to provide - * a backup channel for traffic that is primarily going over another network. - * - * An example might be maintaining backup connections to peers or servers for the purpose of - * fast fallback if the default network is temporarily unresponsive or disconnects. The traffic - * on backup paths should be negligible compared to the traffic on the main path. - */ - public static final int MULTIPATH_PREFERENCE_RELIABILITY = 1 << 1; - - /** - * It is acceptable to use metered data to improve network latency and performance. - */ - public static final int MULTIPATH_PREFERENCE_PERFORMANCE = 1 << 2; - - /** - * Return value to use for unmetered networks. On such networks we currently set all the flags - * to true. - * @hide - */ - public static final int MULTIPATH_PREFERENCE_UNMETERED = - MULTIPATH_PREFERENCE_HANDOVER | - MULTIPATH_PREFERENCE_RELIABILITY | - MULTIPATH_PREFERENCE_PERFORMANCE; - - /** - * Provides a hint to the calling application on whether it is desirable to use the - * multinetwork APIs (e.g., {@link Network#openConnection}, {@link Network#bindSocket}, etc.) - * for multipath data transfer on this network when it is not the system default network. - * Applications desiring to use multipath network protocols should call this method before - * each such operation. - * - * @param network The network on which the application desires to use multipath data. - * If {@code null}, this method will return the a preference that will generally - * apply to metered networks. - * @return a bitwise OR of zero or more of the {@code MULTIPATH_PREFERENCE_*} constants. - */ - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - public @MultipathPreference int getMultipathPreference(@Nullable Network network) { - try { - return mService.getMultipathPreference(network); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Resets all connectivity manager settings back to factory defaults. - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - @RequiresPermission(anyOf = { - android.Manifest.permission.NETWORK_SETTINGS, - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) - public void factoryReset() { - try { - mService.factoryReset(); - mTetheringManager.stopAllTethering(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Binds the current process to {@code network}. All Sockets created in the future - * (and not explicitly bound via a bound SocketFactory from - * {@link Network#getSocketFactory() Network.getSocketFactory()}) will be bound to - * {@code network}. All host name resolutions will be limited to {@code network} as well. - * Note that if {@code network} ever disconnects, all Sockets created in this way will cease to - * work and all host name resolutions will fail. This is by design so an application doesn't - * accidentally use Sockets it thinks are still bound to a particular {@link Network}. - * To clear binding pass {@code null} for {@code network}. Using individually bound - * Sockets created by Network.getSocketFactory().createSocket() and - * performing network-specific host name resolutions via - * {@link Network#getAllByName Network.getAllByName} is preferred to calling - * {@code bindProcessToNetwork}. - * - * @param network The {@link Network} to bind the current process to, or {@code null} to clear - * the current binding. - * @return {@code true} on success, {@code false} if the {@link Network} is no longer valid. - */ - public boolean bindProcessToNetwork(@Nullable Network network) { - // Forcing callers to call through non-static function ensures ConnectivityManager - // instantiated. - return setProcessDefaultNetwork(network); - } - - /** - * Binds the current process to {@code network}. All Sockets created in the future - * (and not explicitly bound via a bound SocketFactory from - * {@link Network#getSocketFactory() Network.getSocketFactory()}) will be bound to - * {@code network}. All host name resolutions will be limited to {@code network} as well. - * Note that if {@code network} ever disconnects, all Sockets created in this way will cease to - * work and all host name resolutions will fail. This is by design so an application doesn't - * accidentally use Sockets it thinks are still bound to a particular {@link Network}. - * To clear binding pass {@code null} for {@code network}. Using individually bound - * Sockets created by Network.getSocketFactory().createSocket() and - * performing network-specific host name resolutions via - * {@link Network#getAllByName Network.getAllByName} is preferred to calling - * {@code setProcessDefaultNetwork}. - * - * @param network The {@link Network} to bind the current process to, or {@code null} to clear - * the current binding. - * @return {@code true} on success, {@code false} if the {@link Network} is no longer valid. - * @deprecated This function can throw {@link IllegalStateException}. Use - * {@link #bindProcessToNetwork} instead. {@code bindProcessToNetwork} - * is a direct replacement. - */ - @Deprecated - public static boolean setProcessDefaultNetwork(@Nullable Network network) { - int netId = (network == null) ? NETID_UNSET : network.netId; - boolean isSameNetId = (netId == NetworkUtils.getBoundNetworkForProcess()); - - if (netId != NETID_UNSET) { - netId = network.getNetIdForResolv(); - } - - if (!NetworkUtils.bindProcessToNetwork(netId)) { - return false; - } - - if (!isSameNetId) { - // Set HTTP proxy system properties to match network. - // TODO: Deprecate this static method and replace it with a non-static version. - try { - Proxy.setHttpProxyConfiguration(getInstance().getDefaultProxy()); - } catch (SecurityException e) { - // The process doesn't have ACCESS_NETWORK_STATE, so we can't fetch the proxy. - Log.e(TAG, "Can't set proxy properties", e); - } - // Must flush DNS cache as new network may have different DNS resolutions. - InetAddressCompat.clearDnsCache(); - // Must flush socket pool as idle sockets will be bound to previous network and may - // cause subsequent fetches to be performed on old network. - NetworkEventDispatcher.getInstance().onNetworkConfigurationChanged(); - } - - return true; - } - - /** - * Returns the {@link Network} currently bound to this process via - * {@link #bindProcessToNetwork}, or {@code null} if no {@link Network} is explicitly bound. - * - * @return {@code Network} to which this process is bound, or {@code null}. - */ - @Nullable - public Network getBoundNetworkForProcess() { - // Forcing callers to call thru non-static function ensures ConnectivityManager - // instantiated. - return getProcessDefaultNetwork(); - } - - /** - * Returns the {@link Network} currently bound to this process via - * {@link #bindProcessToNetwork}, or {@code null} if no {@link Network} is explicitly bound. - * - * @return {@code Network} to which this process is bound, or {@code null}. - * @deprecated Using this function can lead to other functions throwing - * {@link IllegalStateException}. Use {@link #getBoundNetworkForProcess} instead. - * {@code getBoundNetworkForProcess} is a direct replacement. - */ - @Deprecated - @Nullable - public static Network getProcessDefaultNetwork() { - int netId = NetworkUtils.getBoundNetworkForProcess(); - if (netId == NETID_UNSET) return null; - return new Network(netId); - } - - private void unsupportedStartingFrom(int version) { - if (Process.myUid() == Process.SYSTEM_UID) { - // The getApplicationInfo() call we make below is not supported in system context. Let - // the call through here, and rely on the fact that ConnectivityService will refuse to - // allow the system to use these APIs anyway. - return; - } - - if (mContext.getApplicationInfo().targetSdkVersion >= version) { - throw new UnsupportedOperationException( - "This method is not supported in target SDK version " + version + " and above"); - } - } - - // Checks whether the calling app can use the legacy routing API (startUsingNetworkFeature, - // stopUsingNetworkFeature, requestRouteToHost), and if not throw UnsupportedOperationException. - // TODO: convert the existing system users (Tethering, GnssLocationProvider) to the new APIs and - // remove these exemptions. Note that this check is not secure, and apps can still access these - // functions by accessing ConnectivityService directly. However, it should be clear that doing - // so is unsupported and may break in the future. http://b/22728205 - private void checkLegacyRoutingApiAccess() { - unsupportedStartingFrom(VERSION_CODES.M); - } - - /** - * Binds host resolutions performed by this process to {@code network}. - * {@link #bindProcessToNetwork} takes precedence over this setting. - * - * @param network The {@link Network} to bind host resolutions from the current process to, or - * {@code null} to clear the current binding. - * @return {@code true} on success, {@code false} if the {@link Network} is no longer valid. - * @hide - * @deprecated This is strictly for legacy usage to support {@link #startUsingNetworkFeature}. - */ - @Deprecated - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public static boolean setProcessDefaultNetworkForHostResolution(Network network) { - return NetworkUtils.bindProcessToNetworkForHostResolution( - (network == null) ? NETID_UNSET : network.getNetIdForResolv()); - } - - /** - * Device is not restricting metered network activity while application is running on - * background. - */ - public static final int RESTRICT_BACKGROUND_STATUS_DISABLED = 1; - - /** - * Device is restricting metered network activity while application is running on background, - * but application is allowed to bypass it. - *

    - * In this state, application should take action to mitigate metered network access. - * For example, a music streaming application should switch to a low-bandwidth bitrate. - */ - public static final int RESTRICT_BACKGROUND_STATUS_WHITELISTED = 2; - - /** - * Device is restricting metered network activity while application is running on background. - *

    - * In this state, application should not try to use the network while running on background, - * because it would be denied. - */ - public static final int RESTRICT_BACKGROUND_STATUS_ENABLED = 3; - - /** - * A change in the background metered network activity restriction has occurred. - *

    - * Applications should call {@link #getRestrictBackgroundStatus()} to check if the restriction - * applies to them. - *

    - * This is only sent to registered receivers, not manifest receivers. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_RESTRICT_BACKGROUND_CHANGED = - "android.net.conn.RESTRICT_BACKGROUND_CHANGED"; - - /** - * Determines if the calling application is subject to metered network restrictions while - * running on background. - * - * @return {@link #RESTRICT_BACKGROUND_STATUS_DISABLED}, - * {@link #RESTRICT_BACKGROUND_STATUS_ENABLED}, - * or {@link #RESTRICT_BACKGROUND_STATUS_WHITELISTED} - */ - public @RestrictBackgroundStatus int getRestrictBackgroundStatus() { - try { - return mService.getRestrictBackgroundStatusByCaller(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * The network watchlist is a list of domains and IP addresses that are associated with - * potentially harmful apps. This method returns the SHA-256 of the watchlist config file - * currently used by the system for validation purposes. - * - * @return Hash of network watchlist config file. Null if config does not exist. - */ - @Nullable - public byte[] getNetworkWatchlistConfigHash() { - try { - return mService.getNetworkWatchlistConfigHash(); - } catch (RemoteException e) { - Log.e(TAG, "Unable to get watchlist config hash"); - throw e.rethrowFromSystemServer(); - } - } - - /** - * Returns the {@code uid} of the owner of a network connection. - * - * @param protocol The protocol of the connection. Only {@code IPPROTO_TCP} and {@code - * IPPROTO_UDP} currently supported. - * @param local The local {@link InetSocketAddress} of a connection. - * @param remote The remote {@link InetSocketAddress} of a connection. - * @return {@code uid} if the connection is found and the app has permission to observe it - * (e.g., if it is associated with the calling VPN app's VpnService tunnel) or {@link - * android.os.Process#INVALID_UID} if the connection is not found. - * @throws {@link SecurityException} if the caller is not the active VpnService for the current - * user. - * @throws {@link IllegalArgumentException} if an unsupported protocol is requested. - */ - public int getConnectionOwnerUid( - int protocol, @NonNull InetSocketAddress local, @NonNull InetSocketAddress remote) { - ConnectionInfo connectionInfo = new ConnectionInfo(protocol, local, remote); - try { - return mService.getConnectionOwnerUid(connectionInfo); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - private void printStackTrace() { - if (DEBUG) { - final StackTraceElement[] callStack = Thread.currentThread().getStackTrace(); - final StringBuffer sb = new StringBuffer(); - for (int i = 3; i < callStack.length; i++) { - final String stackTrace = callStack[i].toString(); - if (stackTrace == null || stackTrace.contains("android.os")) { - break; - } - sb.append(" [").append(stackTrace).append("]"); - } - Log.d(TAG, "StackLog:" + sb.toString()); - } - } - - /** @hide */ - public TestNetworkManager startOrGetTestNetworkManager() { - final IBinder tnBinder; - try { - tnBinder = mService.startOrGetTestNetworkService(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - - return new TestNetworkManager(ITestNetworkManager.Stub.asInterface(tnBinder)); - } - - /** @hide */ - public ConnectivityDiagnosticsManager createDiagnosticsManager() { - return new ConnectivityDiagnosticsManager(mContext, mService); - } - - /** - * Simulates a Data Stall for the specified Network. - * - *

    This method should only be used for tests. - * - *

    The caller must be the owner of the specified Network. This simulates a data stall to - * have the system behave as if it had happened, but does not actually stall connectivity. - * - * @param detectionMethod The detection method used to identify the Data Stall. - * See ConnectivityDiagnosticsManager.DataStallReport.DETECTION_METHOD_*. - * @param timestampMillis The timestamp at which the stall 'occurred', in milliseconds, as per - * SystemClock.elapsedRealtime. - * @param network The Network for which a Data Stall is being simluated. - * @param extras The PersistableBundle of extras included in the Data Stall notification. - * @throws SecurityException if the caller is not the owner of the given network. - * @hide - */ - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_TEST_NETWORKS, - android.Manifest.permission.NETWORK_STACK}) - public void simulateDataStall(@DetectionMethod int detectionMethod, long timestampMillis, - @NonNull Network network, @NonNull PersistableBundle extras) { - try { - mService.simulateDataStall(detectionMethod, timestampMillis, network, extras); - } catch (RemoteException e) { - e.rethrowFromSystemServer(); - } - } - - @NonNull - private final List mQosCallbackConnections = new ArrayList<>(); - - /** - * Registers a {@link QosSocketInfo} with an associated {@link QosCallback}. The callback will - * receive available QoS events related to the {@link Network} and local ip + port - * specified within socketInfo. - *

    - * The same {@link QosCallback} must be unregistered before being registered a second time, - * otherwise {@link QosCallbackRegistrationException} is thrown. - *

    - * This API does not, in itself, require any permission if called with a network that is not - * restricted. However, the underlying implementation currently only supports the IMS network, - * which is always restricted. That means non-preinstalled callers can't possibly find this API - * useful, because they'd never be called back on networks that they would have access to. - * - * @throws SecurityException if {@link QosSocketInfo#getNetwork()} is restricted and the app is - * missing CONNECTIVITY_USE_RESTRICTED_NETWORKS permission. - * @throws QosCallback.QosCallbackRegistrationException if qosCallback is already registered. - * @throws RuntimeException if the app already has too many callbacks registered. - * - * Exceptions after the time of registration is passed through - * {@link QosCallback#onError(QosCallbackException)}. see: {@link QosCallbackException}. - * - * @param socketInfo the socket information used to match QoS events - * @param executor The executor on which the callback will be invoked. The provided - * {@link Executor} must run callback sequentially, otherwise the order of - * callbacks cannot be guaranteed.onQosCallbackRegistered - * @param callback receives qos events that satisfy socketInfo - * - * @hide - */ - @SystemApi - public void registerQosCallback(@NonNull final QosSocketInfo socketInfo, - @CallbackExecutor @NonNull final Executor executor, - @NonNull final QosCallback callback) { - Objects.requireNonNull(socketInfo, "socketInfo must be non-null"); - Objects.requireNonNull(executor, "executor must be non-null"); - Objects.requireNonNull(callback, "callback must be non-null"); - - try { - synchronized (mQosCallbackConnections) { - if (getQosCallbackConnection(callback) == null) { - final QosCallbackConnection connection = - new QosCallbackConnection(this, callback, executor); - mQosCallbackConnections.add(connection); - mService.registerQosSocketCallback(socketInfo, connection); - } else { - Log.e(TAG, "registerQosCallback: Callback already registered"); - throw new QosCallbackRegistrationException(); - } - } - } catch (final RemoteException e) { - Log.e(TAG, "registerQosCallback: Error while registering ", e); - - // The same unregister method method is called for consistency even though nothing - // will be sent to the ConnectivityService since the callback was never successfully - // registered. - unregisterQosCallback(callback); - e.rethrowFromSystemServer(); - } catch (final ServiceSpecificException e) { - Log.e(TAG, "registerQosCallback: Error while registering ", e); - unregisterQosCallback(callback); - throw convertServiceException(e); - } - } - - /** - * Unregisters the given {@link QosCallback}. The {@link QosCallback} will no longer receive - * events once unregistered and can be registered a second time. - *

    - * If the {@link QosCallback} does not have an active registration, it is a no-op. - * - * @param callback the callback being unregistered - * - * @hide - */ - @SystemApi - public void unregisterQosCallback(@NonNull final QosCallback callback) { - Objects.requireNonNull(callback, "The callback must be non-null"); - try { - synchronized (mQosCallbackConnections) { - final QosCallbackConnection connection = getQosCallbackConnection(callback); - if (connection != null) { - connection.stopReceivingMessages(); - mService.unregisterQosCallback(connection); - mQosCallbackConnections.remove(connection); - } else { - Log.d(TAG, "unregisterQosCallback: Callback not registered"); - } - } - } catch (final RemoteException e) { - Log.e(TAG, "unregisterQosCallback: Error while unregistering ", e); - e.rethrowFromSystemServer(); - } - } - - /** - * Gets the connection related to the callback. - * - * @param callback the callback to look up - * @return the related connection - */ - @Nullable - private QosCallbackConnection getQosCallbackConnection(final QosCallback callback) { - for (final QosCallbackConnection connection : mQosCallbackConnections) { - // Checking by reference here is intentional - if (connection.getCallback() == callback) { - return connection; - } - } - return null; - } - - /** - * Request a network to satisfy a set of {@link NetworkCapabilities}, but - * does not cause any networks to retain the NET_CAPABILITY_FOREGROUND capability. This can - * be used to request that the system provide a network without causing the network to be - * in the foreground. - * - *

    This method will attempt to find the best network that matches the passed - * {@link NetworkRequest}, and to bring up one that does if none currently satisfies the - * criteria. The platform will evaluate which network is the best at its own discretion. - * Throughput, latency, cost per byte, policy, user preference and other considerations - * may be factored in the decision of what is considered the best network. - * - *

    As long as this request is outstanding, the platform will try to maintain the best network - * matching this request, while always attempting to match the request to a better network if - * possible. If a better match is found, the platform will switch this request to the now-best - * network and inform the app of the newly best network by invoking - * {@link NetworkCallback#onAvailable(Network)} on the provided callback. Note that the platform - * will not try to maintain any other network than the best one currently matching the request: - * a network not matching any network request may be disconnected at any time. - * - *

    For example, an application could use this method to obtain a connected cellular network - * even if the device currently has a data connection over Ethernet. This may cause the cellular - * radio to consume additional power. Or, an application could inform the system that it wants - * a network supporting sending MMSes and have the system let it know about the currently best - * MMS-supporting network through the provided {@link NetworkCallback}. - * - *

    The status of the request can be followed by listening to the various callbacks described - * in {@link NetworkCallback}. The {@link Network} object passed to the callback methods can be - * used to direct traffic to the network (although accessing some networks may be subject to - * holding specific permissions). Callers will learn about the specific characteristics of the - * network through - * {@link NetworkCallback#onCapabilitiesChanged(Network, NetworkCapabilities)} and - * {@link NetworkCallback#onLinkPropertiesChanged(Network, LinkProperties)}. The methods of the - * provided {@link NetworkCallback} will only be invoked due to changes in the best network - * matching the request at any given time; therefore when a better network matching the request - * becomes available, the {@link NetworkCallback#onAvailable(Network)} method is called - * with the new network after which no further updates are given about the previously-best - * network, unless it becomes the best again at some later time. All callbacks are invoked - * in order on the same thread, which by default is a thread created by the framework running - * in the app. - * - *

    This{@link NetworkRequest} will live until released via - * {@link #unregisterNetworkCallback(NetworkCallback)} or the calling application exits, at - * which point the system may let go of the network at any time. - * - *

    It is presently unsupported to request a network with mutable - * {@link NetworkCapabilities} such as - * {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} or - * {@link NetworkCapabilities#NET_CAPABILITY_CAPTIVE_PORTAL} - * as these {@code NetworkCapabilities} represent states that a particular - * network may never attain, and whether a network will attain these states - * is unknown prior to bringing up the network so the framework does not - * know how to go about satisfying a request with these capabilities. - * - *

    To avoid performance issues due to apps leaking callbacks, the system will limit the - * number of outstanding requests to 100 per app (identified by their UID), shared with - * all variants of this method, of {@link #registerNetworkCallback} as well as - * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}. - * Requesting a network with this method will count toward this limit. If this limit is - * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources, - * make sure to unregister the callbacks with - * {@link #unregisterNetworkCallback(NetworkCallback)}. - * - * @param request {@link NetworkRequest} describing this request. - * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note - * the callback must not be shared - it uniquely specifies this request. - * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. - * If null, the callback is invoked on the default internal Handler. - * @throws IllegalArgumentException if {@code request} contains invalid network capabilities. - * @throws SecurityException if missing the appropriate permissions. - * @throws RuntimeException if the app already has too many callbacks registered. - * - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - @SuppressLint("ExecutorRegistration") - @RequiresPermission(anyOf = { - android.Manifest.permission.NETWORK_SETTINGS, - android.Manifest.permission.NETWORK_STACK, - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK - }) - public void requestBackgroundNetwork(@NonNull NetworkRequest request, - @NonNull NetworkCallback networkCallback, - @SuppressLint("ListenerLast") @NonNull Handler handler) { - final NetworkCapabilities nc = request.networkCapabilities; - sendRequestForNetwork(nc, networkCallback, 0, BACKGROUND_REQUEST, - TYPE_NONE, new CallbackHandler(handler)); - } - - /** - * Used by automotive devices to set the network preferences used to direct traffic at an - * application level as per the given OemNetworkPreferences. An example use-case would be an - * automotive OEM wanting to provide connectivity for applications critical to the usage of a - * vehicle via a particular network. - * - * Calling this will overwrite the existing preference. - * - * @param preference {@link OemNetworkPreferences} The application network preference to be set. - * @param executor the executor on which listener will be invoked. - * @param listener {@link OnSetOemNetworkPreferenceListener} optional listener used to - * communicate completion of setOemNetworkPreference(). This will only be - * called once upon successful completion of setOemNetworkPreference(). - * @throws IllegalArgumentException if {@code preference} contains invalid preference values. - * @throws SecurityException if missing the appropriate permissions. - * @throws UnsupportedOperationException if called on a non-automotive device. - * @hide - */ - @SystemApi - @RequiresPermission(android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE) - public void setOemNetworkPreference(@NonNull final OemNetworkPreferences preference, - @Nullable @CallbackExecutor final Executor executor, - @Nullable final Runnable listener) { - Objects.requireNonNull(preference, "OemNetworkPreferences must be non-null"); - if (null != listener) { - Objects.requireNonNull(executor, "Executor must be non-null"); - } - final IOnCompleteListener listenerInternal = listener == null ? null : - new IOnCompleteListener.Stub() { - @Override - public void onComplete() { - executor.execute(listener::run); - } - }; - - try { - mService.setOemNetworkPreference(preference, listenerInternal); - } catch (RemoteException e) { - Log.e(TAG, "setOemNetworkPreference() failed for preference: " + preference.toString()); - throw e.rethrowFromSystemServer(); - } - } - - /** - * Request that a user profile is put by default on a network matching a given preference. - * - * See the documentation for the individual preferences for a description of the supported - * behaviors. - * - * @param profile the profile concerned. - * @param preference the preference for this profile. - * @param executor an executor to execute the listener on. Optional if listener is null. - * @param listener an optional listener to listen for completion of the operation. - * @throws IllegalArgumentException if {@code profile} is not a valid user profile. - * @throws SecurityException if missing the appropriate permissions. - * @hide - */ - // This function is for establishing per-profile default networking and can only be called by - // the device policy manager, running as the system server. It would make no sense to call it - // on a context for a user because it does not establish a setting on behalf of a user, rather - // it establishes a setting for a user on behalf of the DPM. - @SuppressLint({"UserHandle"}) - @SystemApi(client = MODULE_LIBRARIES) - @RequiresPermission(android.Manifest.permission.NETWORK_STACK) - public void setProfileNetworkPreference(@NonNull final UserHandle profile, - @ProfileNetworkPreference final int preference, - @Nullable @CallbackExecutor final Executor executor, - @Nullable final Runnable listener) { - if (null != listener) { - Objects.requireNonNull(executor, "Pass a non-null executor, or a null listener"); - } - final IOnCompleteListener proxy; - if (null == listener) { - proxy = null; - } else { - proxy = new IOnCompleteListener.Stub() { - @Override - public void onComplete() { - executor.execute(listener::run); - } - }; - } - try { - mService.setProfileNetworkPreference(profile, preference, proxy); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - // The first network ID of IPSec tunnel interface. - private static final int TUN_INTF_NETID_START = 0xFC00; // 0xFC00 = 64512 - // The network ID range of IPSec tunnel interface. - private static final int TUN_INTF_NETID_RANGE = 0x0400; // 0x0400 = 1024 - - /** - * Get the network ID range reserved for IPSec tunnel interfaces. - * - * @return A Range which indicates the network ID range of IPSec tunnel interface. - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - @NonNull - public static Range getIpSecNetIdRange() { - return new Range(TUN_INTF_NETID_START, TUN_INTF_NETID_START + TUN_INTF_NETID_RANGE - 1); - } -} diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityResources.java b/packages/Connectivity/framework/src/android/net/ConnectivityResources.java deleted file mode 100644 index 18f0de0cc9a17..0000000000000 --- a/packages/Connectivity/framework/src/android/net/ConnectivityResources.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.res.Resources; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; - -import java.util.List; - -/** - * Utility to obtain the {@link com.android.server.ConnectivityService} {@link Resources}, in the - * ServiceConnectivityResources APK. - * @hide - */ -public class ConnectivityResources { - private static final String RESOURCES_APK_INTENT = - "com.android.server.connectivity.intent.action.SERVICE_CONNECTIVITY_RESOURCES_APK"; - private static final String RES_PKG_DIR = "/apex/com.android.tethering/"; - - @NonNull - private final Context mContext; - - @Nullable - private Context mResourcesContext = null; - - @Nullable - private static Context sTestResourcesContext = null; - - public ConnectivityResources(Context context) { - mContext = context; - } - - /** - * Convenience method to mock all resources for the duration of a test. - * - * Call with a null context to reset after the test. - */ - @VisibleForTesting - public static void setResourcesContextForTest(@Nullable Context testContext) { - sTestResourcesContext = testContext; - } - - /** - * Get the {@link Context} of the resources package. - */ - public synchronized Context getResourcesContext() { - if (sTestResourcesContext != null) { - return sTestResourcesContext; - } - - if (mResourcesContext != null) { - return mResourcesContext; - } - - final List pkgs = mContext.getPackageManager() - .queryIntentActivities(new Intent(RESOURCES_APK_INTENT), MATCH_SYSTEM_ONLY); - pkgs.removeIf(pkg -> !pkg.activityInfo.applicationInfo.sourceDir.startsWith(RES_PKG_DIR)); - if (pkgs.size() > 1) { - Log.wtf(ConnectivityResources.class.getSimpleName(), - "More than one package found: " + pkgs); - } - if (pkgs.isEmpty()) { - throw new IllegalStateException("No connectivity resource package found"); - } - - final Context pkgContext; - try { - pkgContext = mContext.createPackageContext( - pkgs.get(0).activityInfo.applicationInfo.packageName, 0 /* flags */); - } catch (PackageManager.NameNotFoundException e) { - throw new IllegalStateException("Resolved package not found", e); - } - - mResourcesContext = pkgContext; - return pkgContext; - } - - /** - * Get the {@link Resources} of the ServiceConnectivityResources APK. - */ - public Resources get() { - return getResourcesContext().getResources(); - } -} diff --git a/packages/Connectivity/framework/src/android/net/ConnectivitySettingsManager.java b/packages/Connectivity/framework/src/android/net/ConnectivitySettingsManager.java deleted file mode 100644 index 1a690991cade5..0000000000000 --- a/packages/Connectivity/framework/src/android/net/ConnectivitySettingsManager.java +++ /dev/null @@ -1,1087 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static android.net.ConnectivityManager.MULTIPATH_PREFERENCE_HANDOVER; -import static android.net.ConnectivityManager.MULTIPATH_PREFERENCE_PERFORMANCE; -import static android.net.ConnectivityManager.MULTIPATH_PREFERENCE_RELIABILITY; - -import android.annotation.IntDef; -import android.annotation.IntRange; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SystemApi; -import android.content.ContentResolver; -import android.content.Context; -import android.net.ConnectivityAnnotations.MultipathPreference; -import android.os.Process; -import android.os.UserHandle; -import android.provider.Settings; -import android.text.TextUtils; -import android.util.ArraySet; -import android.util.Range; - -import com.android.net.module.util.ProxyUtils; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.time.Duration; -import java.util.List; -import java.util.Set; -import java.util.StringJoiner; - -/** - * A manager class for connectivity module settings. - * - * @hide - */ -@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) -public class ConnectivitySettingsManager { - - private ConnectivitySettingsManager() {} - - /** Data activity timeout settings */ - - /** - * Inactivity timeout to track mobile data activity. - * - * If set to a positive integer, it indicates the inactivity timeout value in seconds to - * infer the data activity of mobile network. After a period of no activity on mobile - * networks with length specified by the timeout, an {@code ACTION_DATA_ACTIVITY_CHANGE} - * intent is fired to indicate a transition of network status from "active" to "idle". Any - * subsequent activity on mobile networks triggers the firing of {@code - * ACTION_DATA_ACTIVITY_CHANGE} intent indicating transition from "idle" to "active". - * - * Network activity refers to transmitting or receiving data on the network interfaces. - * - * Tracking is disabled if set to zero or negative value. - * - * @hide - */ - public static final String DATA_ACTIVITY_TIMEOUT_MOBILE = "data_activity_timeout_mobile"; - - /** - * Timeout to tracking Wifi data activity. Same as {@code DATA_ACTIVITY_TIMEOUT_MOBILE} - * but for Wifi network. - * - * @hide - */ - public static final String DATA_ACTIVITY_TIMEOUT_WIFI = "data_activity_timeout_wifi"; - - /** Dns resolver settings */ - - /** - * Sample validity in seconds to configure for the system DNS resolver. - * - * @hide - */ - public static final String DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS = - "dns_resolver_sample_validity_seconds"; - - /** - * Success threshold in percent for use with the system DNS resolver. - * - * @hide - */ - public static final String DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT = - "dns_resolver_success_threshold_percent"; - - /** - * Minimum number of samples needed for statistics to be considered meaningful in the - * system DNS resolver. - * - * @hide - */ - public static final String DNS_RESOLVER_MIN_SAMPLES = "dns_resolver_min_samples"; - - /** - * Maximum number taken into account for statistics purposes in the system DNS resolver. - * - * @hide - */ - public static final String DNS_RESOLVER_MAX_SAMPLES = "dns_resolver_max_samples"; - - private static final int DNS_RESOLVER_DEFAULT_MIN_SAMPLES = 8; - private static final int DNS_RESOLVER_DEFAULT_MAX_SAMPLES = 64; - - /** Network switch notification settings */ - - /** - * The maximum number of notifications shown in 24 hours when switching networks. - * - * @hide - */ - public static final String NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT = - "network_switch_notification_daily_limit"; - - /** - * The minimum time in milliseconds between notifications when switching networks. - * - * @hide - */ - public static final String NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS = - "network_switch_notification_rate_limit_millis"; - - /** Captive portal settings */ - - /** - * The URL used for HTTP captive portal detection upon a new connection. - * A 204 response code from the server is used for validation. - * - * @hide - */ - public static final String CAPTIVE_PORTAL_HTTP_URL = "captive_portal_http_url"; - - /** - * What to do when connecting a network that presents a captive portal. - * Must be one of the CAPTIVE_PORTAL_MODE_* constants below. - * - * The default for this setting is CAPTIVE_PORTAL_MODE_PROMPT. - * - * @hide - */ - public static final String CAPTIVE_PORTAL_MODE = "captive_portal_mode"; - - /** - * Don't attempt to detect captive portals. - */ - public static final int CAPTIVE_PORTAL_MODE_IGNORE = 0; - - /** - * When detecting a captive portal, display a notification that - * prompts the user to sign in. - */ - public static final int CAPTIVE_PORTAL_MODE_PROMPT = 1; - - /** - * When detecting a captive portal, immediately disconnect from the - * network and do not reconnect to that network in the future. - */ - public static final int CAPTIVE_PORTAL_MODE_AVOID = 2; - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(value = { - CAPTIVE_PORTAL_MODE_IGNORE, - CAPTIVE_PORTAL_MODE_PROMPT, - CAPTIVE_PORTAL_MODE_AVOID, - }) - public @interface CaptivePortalMode {} - - /** Global http proxy settings */ - - /** - * Host name for global http proxy. Set via ConnectivityManager. - * - * @hide - */ - public static final String GLOBAL_HTTP_PROXY_HOST = "global_http_proxy_host"; - - /** - * Integer host port for global http proxy. Set via ConnectivityManager. - * - * @hide - */ - public static final String GLOBAL_HTTP_PROXY_PORT = "global_http_proxy_port"; - - /** - * Exclusion list for global proxy. This string contains a list of - * comma-separated domains where the global proxy does not apply. - * Domains should be listed in a comma- separated list. Example of - * acceptable formats: ".domain1.com,my.domain2.com" Use - * ConnectivityManager to set/get. - * - * @hide - */ - public static final String GLOBAL_HTTP_PROXY_EXCLUSION_LIST = - "global_http_proxy_exclusion_list"; - - /** - * The location PAC File for the proxy. - * - * @hide - */ - public static final String GLOBAL_HTTP_PROXY_PAC = "global_proxy_pac_url"; - - /** Private dns settings */ - - /** - * The requested Private DNS mode (string), and an accompanying specifier (string). - * - * Currently, the specifier holds the chosen provider name when the mode requests - * a specific provider. It may be used to store the provider name even when the - * mode changes so that temporarily disabling and re-enabling the specific - * provider mode does not necessitate retyping the provider hostname. - * - * @hide - */ - public static final String PRIVATE_DNS_MODE = "private_dns_mode"; - - /** - * The specific Private DNS provider name. - * - * @hide - */ - public static final String PRIVATE_DNS_SPECIFIER = "private_dns_specifier"; - - /** - * Forced override of the default mode (hardcoded as "automatic", nee "opportunistic"). - * This allows changing the default mode without effectively disabling other modes, - * all of which require explicit user action to enable/configure. See also b/79719289. - * - * Value is a string, suitable for assignment to PRIVATE_DNS_MODE above. - * - * @hide - */ - public static final String PRIVATE_DNS_DEFAULT_MODE = "private_dns_default_mode"; - - /** Other settings */ - - /** - * The number of milliseconds to hold on to a PendingIntent based request. This delay gives - * the receivers of the PendingIntent an opportunity to make a new network request before - * the Network satisfying the request is potentially removed. - * - * @hide - */ - public static final String CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS = - "connectivity_release_pending_intent_delay_ms"; - - /** - * Whether the mobile data connection should remain active even when higher - * priority networks like WiFi are active, to help make network switching faster. - * - * See ConnectivityService for more info. - * - * (0 = disabled, 1 = enabled) - * - * @hide - */ - public static final String MOBILE_DATA_ALWAYS_ON = "mobile_data_always_on"; - - /** - * Whether the wifi data connection should remain active even when higher - * priority networks like Ethernet are active, to keep both networks. - * In the case where higher priority networks are connected, wifi will be - * unused unless an application explicitly requests to use it. - * - * See ConnectivityService for more info. - * - * (0 = disabled, 1 = enabled) - * - * @hide - */ - public static final String WIFI_ALWAYS_REQUESTED = "wifi_always_requested"; - - /** - * Whether to automatically switch away from wifi networks that lose Internet access. - * Only meaningful if config_networkAvoidBadWifi is set to 0, otherwise the system always - * avoids such networks. Valid values are: - * - * 0: Don't avoid bad wifi, don't prompt the user. Get stuck on bad wifi like it's 2013. - * null: Ask the user whether to switch away from bad wifi. - * 1: Avoid bad wifi. - * - * @hide - */ - public static final String NETWORK_AVOID_BAD_WIFI = "network_avoid_bad_wifi"; - - /** - * Don't avoid bad wifi, don't prompt the user. Get stuck on bad wifi like it's 2013. - */ - public static final int NETWORK_AVOID_BAD_WIFI_IGNORE = 0; - - /** - * Ask the user whether to switch away from bad wifi. - */ - public static final int NETWORK_AVOID_BAD_WIFI_PROMPT = 1; - - /** - * Avoid bad wifi. - */ - public static final int NETWORK_AVOID_BAD_WIFI_AVOID = 2; - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(value = { - NETWORK_AVOID_BAD_WIFI_IGNORE, - NETWORK_AVOID_BAD_WIFI_PROMPT, - NETWORK_AVOID_BAD_WIFI_AVOID, - }) - public @interface NetworkAvoidBadWifi {} - - /** - * User setting for ConnectivityManager.getMeteredMultipathPreference(). This value may be - * overridden by the system based on device or application state. If null, the value - * specified by config_networkMeteredMultipathPreference is used. - * - * @hide - */ - public static final String NETWORK_METERED_MULTIPATH_PREFERENCE = - "network_metered_multipath_preference"; - - /** - * A list of uids that should go on cellular networks in preference even when higher-priority - * networks are connected. - * - * @hide - */ - public static final String MOBILE_DATA_PREFERRED_UIDS = "mobile_data_preferred_uids"; - - /** - * One of the private DNS modes that indicates the private DNS mode is off. - */ - public static final int PRIVATE_DNS_MODE_OFF = 1; - - /** - * One of the private DNS modes that indicates the private DNS mode is automatic, which - * will try to use the current DNS as private DNS. - */ - public static final int PRIVATE_DNS_MODE_OPPORTUNISTIC = 2; - - /** - * One of the private DNS modes that indicates the private DNS mode is strict and the - * {@link #PRIVATE_DNS_SPECIFIER} is required, which will try to use the value of - * {@link #PRIVATE_DNS_SPECIFIER} as private DNS. - */ - public static final int PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = 3; - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(value = { - PRIVATE_DNS_MODE_OFF, - PRIVATE_DNS_MODE_OPPORTUNISTIC, - PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, - }) - public @interface PrivateDnsMode {} - - private static final String PRIVATE_DNS_MODE_OFF_STRING = "off"; - private static final String PRIVATE_DNS_MODE_OPPORTUNISTIC_STRING = "opportunistic"; - private static final String PRIVATE_DNS_MODE_PROVIDER_HOSTNAME_STRING = "hostname"; - - /** - * A list of apps that is allowed on restricted networks. - * - * @hide - */ - public static final String APPS_ALLOWED_ON_RESTRICTED_NETWORKS = - "apps_allowed_on_restricted_networks"; - - /** - * Get mobile data activity timeout from {@link Settings}. - * - * @param context The {@link Context} to query the setting. - * @param def The default timeout if no setting value. - * @return The {@link Duration} of timeout to track mobile data activity. - */ - @NonNull - public static Duration getMobileDataActivityTimeout(@NonNull Context context, - @NonNull Duration def) { - final int timeout = Settings.Global.getInt( - context.getContentResolver(), DATA_ACTIVITY_TIMEOUT_MOBILE, (int) def.getSeconds()); - return Duration.ofSeconds(timeout); - } - - /** - * Set mobile data activity timeout to {@link Settings}. - * Tracking is disabled if set to zero or negative value. - * - * Note: Only use the number of seconds in this duration, lower second(nanoseconds) will be - * ignored. - * - * @param context The {@link Context} to set the setting. - * @param timeout The mobile data activity timeout. - */ - public static void setMobileDataActivityTimeout(@NonNull Context context, - @NonNull Duration timeout) { - Settings.Global.putInt(context.getContentResolver(), DATA_ACTIVITY_TIMEOUT_MOBILE, - (int) timeout.getSeconds()); - } - - /** - * Get wifi data activity timeout from {@link Settings}. - * - * @param context The {@link Context} to query the setting. - * @param def The default timeout if no setting value. - * @return The {@link Duration} of timeout to track wifi data activity. - */ - @NonNull - public static Duration getWifiDataActivityTimeout(@NonNull Context context, - @NonNull Duration def) { - final int timeout = Settings.Global.getInt( - context.getContentResolver(), DATA_ACTIVITY_TIMEOUT_WIFI, (int) def.getSeconds()); - return Duration.ofSeconds(timeout); - } - - /** - * Set wifi data activity timeout to {@link Settings}. - * Tracking is disabled if set to zero or negative value. - * - * Note: Only use the number of seconds in this duration, lower second(nanoseconds) will be - * ignored. - * - * @param context The {@link Context} to set the setting. - * @param timeout The wifi data activity timeout. - */ - public static void setWifiDataActivityTimeout(@NonNull Context context, - @NonNull Duration timeout) { - Settings.Global.putInt(context.getContentResolver(), DATA_ACTIVITY_TIMEOUT_WIFI, - (int) timeout.getSeconds()); - } - - /** - * Get dns resolver sample validity duration from {@link Settings}. - * - * @param context The {@link Context} to query the setting. - * @param def The default duration if no setting value. - * @return The {@link Duration} of sample validity duration to configure for the system DNS - * resolver. - */ - @NonNull - public static Duration getDnsResolverSampleValidityDuration(@NonNull Context context, - @NonNull Duration def) { - final int duration = Settings.Global.getInt(context.getContentResolver(), - DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS, (int) def.getSeconds()); - return Duration.ofSeconds(duration); - } - - /** - * Set dns resolver sample validity duration to {@link Settings}. The duration must be a - * positive number of seconds. - * - * @param context The {@link Context} to set the setting. - * @param duration The sample validity duration. - */ - public static void setDnsResolverSampleValidityDuration(@NonNull Context context, - @NonNull Duration duration) { - final int time = (int) duration.getSeconds(); - if (time <= 0) { - throw new IllegalArgumentException("Invalid duration"); - } - Settings.Global.putInt( - context.getContentResolver(), DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS, time); - } - - /** - * Get dns resolver success threshold percent from {@link Settings}. - * - * @param context The {@link Context} to query the setting. - * @param def The default value if no setting value. - * @return The success threshold in percent for use with the system DNS resolver. - */ - public static int getDnsResolverSuccessThresholdPercent(@NonNull Context context, int def) { - return Settings.Global.getInt( - context.getContentResolver(), DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT, def); - } - - /** - * Set dns resolver success threshold percent to {@link Settings}. The threshold percent must - * be 0~100. - * - * @param context The {@link Context} to set the setting. - * @param percent The success threshold percent. - */ - public static void setDnsResolverSuccessThresholdPercent(@NonNull Context context, - @IntRange(from = 0, to = 100) int percent) { - if (percent < 0 || percent > 100) { - throw new IllegalArgumentException("Percent must be 0~100"); - } - Settings.Global.putInt( - context.getContentResolver(), DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT, percent); - } - - /** - * Get dns resolver samples range from {@link Settings}. - * - * @param context The {@link Context} to query the setting. - * @return The {@link Range} of samples needed for statistics to be considered - * meaningful in the system DNS resolver. - */ - @NonNull - public static Range getDnsResolverSampleRanges(@NonNull Context context) { - final int minSamples = Settings.Global.getInt(context.getContentResolver(), - DNS_RESOLVER_MIN_SAMPLES, DNS_RESOLVER_DEFAULT_MIN_SAMPLES); - final int maxSamples = Settings.Global.getInt(context.getContentResolver(), - DNS_RESOLVER_MAX_SAMPLES, DNS_RESOLVER_DEFAULT_MAX_SAMPLES); - return new Range<>(minSamples, maxSamples); - } - - /** - * Set dns resolver samples range to {@link Settings}. - * - * @param context The {@link Context} to set the setting. - * @param range The samples range. The minimum number should be more than 0 and the maximum - * number should be less that 64. - */ - public static void setDnsResolverSampleRanges(@NonNull Context context, - @NonNull Range range) { - if (range.getLower() < 0 || range.getUpper() > 64) { - throw new IllegalArgumentException("Argument must be 0~64"); - } - Settings.Global.putInt( - context.getContentResolver(), DNS_RESOLVER_MIN_SAMPLES, range.getLower()); - Settings.Global.putInt( - context.getContentResolver(), DNS_RESOLVER_MAX_SAMPLES, range.getUpper()); - } - - /** - * Get maximum count (from {@link Settings}) of switching network notifications shown in 24 - * hours. - * - * @param context The {@link Context} to query the setting. - * @param def The default value if no setting value. - * @return The maximum count of notifications shown in 24 hours when switching networks. - */ - public static int getNetworkSwitchNotificationMaximumDailyCount(@NonNull Context context, - int def) { - return Settings.Global.getInt( - context.getContentResolver(), NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT, def); - } - - /** - * Set maximum count (to {@link Settings}) of switching network notifications shown in 24 hours. - * The count must be at least 0. - * - * @param context The {@link Context} to set the setting. - * @param count The maximum count of switching network notifications shown in 24 hours. - */ - public static void setNetworkSwitchNotificationMaximumDailyCount(@NonNull Context context, - @IntRange(from = 0) int count) { - if (count < 0) { - throw new IllegalArgumentException("Count must be 0~10."); - } - Settings.Global.putInt( - context.getContentResolver(), NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT, count); - } - - /** - * Get minimum duration (from {@link Settings}) between each switching network notifications. - * - * @param context The {@link Context} to query the setting. - * @param def The default time if no setting value. - * @return The minimum duration between notifications when switching networks. - */ - @NonNull - public static Duration getNetworkSwitchNotificationRateDuration(@NonNull Context context, - @NonNull Duration def) { - final int duration = Settings.Global.getInt(context.getContentResolver(), - NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS, (int) def.toMillis()); - return Duration.ofMillis(duration); - } - - /** - * Set minimum duration (to {@link Settings}) between each switching network notifications. - * - * @param context The {@link Context} to set the setting. - * @param duration The minimum duration between notifications when switching networks. - */ - public static void setNetworkSwitchNotificationRateDuration(@NonNull Context context, - @NonNull Duration duration) { - final int time = (int) duration.toMillis(); - if (time < 0) { - throw new IllegalArgumentException("Invalid duration."); - } - Settings.Global.putInt(context.getContentResolver(), - NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS, time); - } - - /** - * Get URL (from {@link Settings}) used for HTTP captive portal detection upon a new connection. - * - * @param context The {@link Context} to query the setting. - * @return The URL used for HTTP captive portal detection upon a new connection. - */ - @Nullable - public static String getCaptivePortalHttpUrl(@NonNull Context context) { - return Settings.Global.getString(context.getContentResolver(), CAPTIVE_PORTAL_HTTP_URL); - } - - /** - * Set URL (to {@link Settings}) used for HTTP captive portal detection upon a new connection. - * This URL should respond with a 204 response to a GET request to indicate no captive portal is - * present. And this URL must be HTTP as redirect responses are used to find captive portal - * sign-in pages. If the URL set to null or be incorrect, it will result in captive portal - * detection failed and lost the connection. - * - * @param context The {@link Context} to set the setting. - * @param url The URL used for HTTP captive portal detection upon a new connection. - */ - public static void setCaptivePortalHttpUrl(@NonNull Context context, @Nullable String url) { - Settings.Global.putString(context.getContentResolver(), CAPTIVE_PORTAL_HTTP_URL, url); - } - - /** - * Get mode (from {@link Settings}) when connecting a network that presents a captive portal. - * - * @param context The {@link Context} to query the setting. - * @param def The default mode if no setting value. - * @return The mode when connecting a network that presents a captive portal. - */ - @CaptivePortalMode - public static int getCaptivePortalMode(@NonNull Context context, - @CaptivePortalMode int def) { - return Settings.Global.getInt(context.getContentResolver(), CAPTIVE_PORTAL_MODE, def); - } - - /** - * Set mode (to {@link Settings}) when connecting a network that presents a captive portal. - * - * @param context The {@link Context} to set the setting. - * @param mode The mode when connecting a network that presents a captive portal. - */ - public static void setCaptivePortalMode(@NonNull Context context, @CaptivePortalMode int mode) { - if (!(mode == CAPTIVE_PORTAL_MODE_IGNORE - || mode == CAPTIVE_PORTAL_MODE_PROMPT - || mode == CAPTIVE_PORTAL_MODE_AVOID)) { - throw new IllegalArgumentException("Invalid captive portal mode"); - } - Settings.Global.putInt(context.getContentResolver(), CAPTIVE_PORTAL_MODE, mode); - } - - /** - * Get the global HTTP proxy applied to the device, or null if none. - * - * @param context The {@link Context} to query the setting. - * @return The {@link ProxyInfo} which build from global http proxy settings. - */ - @Nullable - public static ProxyInfo getGlobalProxy(@NonNull Context context) { - final String host = Settings.Global.getString( - context.getContentResolver(), GLOBAL_HTTP_PROXY_HOST); - final int port = Settings.Global.getInt( - context.getContentResolver(), GLOBAL_HTTP_PROXY_PORT, 0 /* def */); - final String exclusionList = Settings.Global.getString( - context.getContentResolver(), GLOBAL_HTTP_PROXY_EXCLUSION_LIST); - final String pacFileUrl = Settings.Global.getString( - context.getContentResolver(), GLOBAL_HTTP_PROXY_PAC); - - if (TextUtils.isEmpty(host) && TextUtils.isEmpty(pacFileUrl)) { - return null; // No global proxy. - } - - if (TextUtils.isEmpty(pacFileUrl)) { - return ProxyInfo.buildDirectProxy( - host, port, ProxyUtils.exclusionStringAsList(exclusionList)); - } else { - return ProxyInfo.buildPacProxy(Uri.parse(pacFileUrl)); - } - } - - /** - * Set global http proxy settings from given {@link ProxyInfo}. - * - * @param context The {@link Context} to set the setting. - * @param proxyInfo The {@link ProxyInfo} for global http proxy settings which build from - * {@link ProxyInfo#buildPacProxy(Uri)} or - * {@link ProxyInfo#buildDirectProxy(String, int, List)} - */ - public static void setGlobalProxy(@NonNull Context context, @NonNull ProxyInfo proxyInfo) { - final String host = proxyInfo.getHost(); - final int port = proxyInfo.getPort(); - final String exclusionList = proxyInfo.getExclusionListAsString(); - final String pacFileUrl = proxyInfo.getPacFileUrl().toString(); - - if (TextUtils.isEmpty(pacFileUrl)) { - Settings.Global.putString(context.getContentResolver(), GLOBAL_HTTP_PROXY_HOST, host); - Settings.Global.putInt(context.getContentResolver(), GLOBAL_HTTP_PROXY_PORT, port); - Settings.Global.putString( - context.getContentResolver(), GLOBAL_HTTP_PROXY_EXCLUSION_LIST, exclusionList); - Settings.Global.putString( - context.getContentResolver(), GLOBAL_HTTP_PROXY_PAC, "" /* value */); - } else { - Settings.Global.putString( - context.getContentResolver(), GLOBAL_HTTP_PROXY_PAC, pacFileUrl); - Settings.Global.putString( - context.getContentResolver(), GLOBAL_HTTP_PROXY_HOST, "" /* value */); - Settings.Global.putInt( - context.getContentResolver(), GLOBAL_HTTP_PROXY_PORT, 0 /* value */); - Settings.Global.putString( - context.getContentResolver(), GLOBAL_HTTP_PROXY_EXCLUSION_LIST, "" /* value */); - } - } - - /** - * Clear all global http proxy settings. - * - * @param context The {@link Context} to set the setting. - */ - public static void clearGlobalProxy(@NonNull Context context) { - Settings.Global.putString( - context.getContentResolver(), GLOBAL_HTTP_PROXY_HOST, "" /* value */); - Settings.Global.putInt( - context.getContentResolver(), GLOBAL_HTTP_PROXY_PORT, 0 /* value */); - Settings.Global.putString( - context.getContentResolver(), GLOBAL_HTTP_PROXY_EXCLUSION_LIST, "" /* value */); - Settings.Global.putString( - context.getContentResolver(), GLOBAL_HTTP_PROXY_PAC, "" /* value */); - } - - private static String getPrivateDnsModeAsString(@PrivateDnsMode int mode) { - switch (mode) { - case PRIVATE_DNS_MODE_OFF: - return PRIVATE_DNS_MODE_OFF_STRING; - case PRIVATE_DNS_MODE_OPPORTUNISTIC: - return PRIVATE_DNS_MODE_OPPORTUNISTIC_STRING; - case PRIVATE_DNS_MODE_PROVIDER_HOSTNAME: - return PRIVATE_DNS_MODE_PROVIDER_HOSTNAME_STRING; - default: - throw new IllegalArgumentException("Invalid private dns mode: " + mode); - } - } - - private static int getPrivateDnsModeAsInt(String mode) { - switch (mode) { - case "off": - return PRIVATE_DNS_MODE_OFF; - case "hostname": - return PRIVATE_DNS_MODE_PROVIDER_HOSTNAME; - case "opportunistic": - return PRIVATE_DNS_MODE_OPPORTUNISTIC; - default: - throw new IllegalArgumentException("Invalid private dns mode: " + mode); - } - } - - /** - * Get private DNS mode from settings. - * - * @param context The Context to query the private DNS mode from settings. - * @return A string of private DNS mode. - */ - @PrivateDnsMode - public static int getPrivateDnsMode(@NonNull Context context) { - final ContentResolver cr = context.getContentResolver(); - String mode = Settings.Global.getString(cr, PRIVATE_DNS_MODE); - if (TextUtils.isEmpty(mode)) mode = Settings.Global.getString(cr, PRIVATE_DNS_DEFAULT_MODE); - // If both PRIVATE_DNS_MODE and PRIVATE_DNS_DEFAULT_MODE are not set, choose - // PRIVATE_DNS_MODE_OPPORTUNISTIC as default mode. - if (TextUtils.isEmpty(mode)) return PRIVATE_DNS_MODE_OPPORTUNISTIC; - return getPrivateDnsModeAsInt(mode); - } - - /** - * Set private DNS mode to settings. - * - * @param context The {@link Context} to set the private DNS mode. - * @param mode The private dns mode. This should be one of the PRIVATE_DNS_MODE_* constants. - */ - public static void setPrivateDnsMode(@NonNull Context context, @PrivateDnsMode int mode) { - if (!(mode == PRIVATE_DNS_MODE_OFF - || mode == PRIVATE_DNS_MODE_OPPORTUNISTIC - || mode == PRIVATE_DNS_MODE_PROVIDER_HOSTNAME)) { - throw new IllegalArgumentException("Invalid private dns mode: " + mode); - } - Settings.Global.putString(context.getContentResolver(), PRIVATE_DNS_MODE, - getPrivateDnsModeAsString(mode)); - } - - /** - * Get specific private dns provider name from {@link Settings}. - * - * @param context The {@link Context} to query the setting. - * @return The specific private dns provider name, or null if no setting value. - */ - @Nullable - public static String getPrivateDnsHostname(@NonNull Context context) { - return Settings.Global.getString(context.getContentResolver(), PRIVATE_DNS_SPECIFIER); - } - - /** - * Set specific private dns provider name to {@link Settings}. - * - * @param context The {@link Context} to set the setting. - * @param specifier The specific private dns provider name. - */ - public static void setPrivateDnsHostname(@NonNull Context context, - @Nullable String specifier) { - Settings.Global.putString(context.getContentResolver(), PRIVATE_DNS_SPECIFIER, specifier); - } - - /** - * Get default private dns mode from {@link Settings}. - * - * @param context The {@link Context} to query the setting. - * @return The default private dns mode. - */ - @PrivateDnsMode - @NonNull - public static String getPrivateDnsDefaultMode(@NonNull Context context) { - return Settings.Global.getString(context.getContentResolver(), PRIVATE_DNS_DEFAULT_MODE); - } - - /** - * Set default private dns mode to {@link Settings}. - * - * @param context The {@link Context} to set the setting. - * @param mode The default private dns mode. This should be one of the PRIVATE_DNS_MODE_* - * constants. - */ - public static void setPrivateDnsDefaultMode(@NonNull Context context, - @NonNull @PrivateDnsMode int mode) { - if (!(mode == PRIVATE_DNS_MODE_OFF - || mode == PRIVATE_DNS_MODE_OPPORTUNISTIC - || mode == PRIVATE_DNS_MODE_PROVIDER_HOSTNAME)) { - throw new IllegalArgumentException("Invalid private dns mode"); - } - Settings.Global.putString(context.getContentResolver(), PRIVATE_DNS_DEFAULT_MODE, - getPrivateDnsModeAsString(mode)); - } - - /** - * Get duration (from {@link Settings}) to keep a PendingIntent-based request. - * - * @param context The {@link Context} to query the setting. - * @param def The default duration if no setting value. - * @return The duration to keep a PendingIntent-based request. - */ - @NonNull - public static Duration getConnectivityKeepPendingIntentDuration(@NonNull Context context, - @NonNull Duration def) { - final int duration = Settings.Secure.getInt(context.getContentResolver(), - CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, (int) def.toMillis()); - return Duration.ofMillis(duration); - } - - /** - * Set duration (to {@link Settings}) to keep a PendingIntent-based request. - * - * @param context The {@link Context} to set the setting. - * @param duration The duration to keep a PendingIntent-based request. - */ - public static void setConnectivityKeepPendingIntentDuration(@NonNull Context context, - @NonNull Duration duration) { - final int time = (int) duration.toMillis(); - if (time < 0) { - throw new IllegalArgumentException("Invalid duration."); - } - Settings.Secure.putInt( - context.getContentResolver(), CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, time); - } - - /** - * Read from {@link Settings} whether the mobile data connection should remain active - * even when higher priority networks are active. - * - * @param context The {@link Context} to query the setting. - * @param def The default value if no setting value. - * @return Whether the mobile data connection should remain active even when higher - * priority networks are active. - */ - public static boolean getMobileDataAlwaysOn(@NonNull Context context, boolean def) { - final int enable = Settings.Global.getInt( - context.getContentResolver(), MOBILE_DATA_ALWAYS_ON, (def ? 1 : 0)); - return (enable != 0) ? true : false; - } - - /** - * Write into {@link Settings} whether the mobile data connection should remain active - * even when higher priority networks are active. - * - * @param context The {@link Context} to set the setting. - * @param enable Whether the mobile data connection should remain active even when higher - * priority networks are active. - */ - public static void setMobileDataAlwaysOn(@NonNull Context context, boolean enable) { - Settings.Global.putInt( - context.getContentResolver(), MOBILE_DATA_ALWAYS_ON, (enable ? 1 : 0)); - } - - /** - * Read from {@link Settings} whether the wifi data connection should remain active - * even when higher priority networks are active. - * - * @param context The {@link Context} to query the setting. - * @param def The default value if no setting value. - * @return Whether the wifi data connection should remain active even when higher - * priority networks are active. - */ - public static boolean getWifiAlwaysRequested(@NonNull Context context, boolean def) { - final int enable = Settings.Global.getInt( - context.getContentResolver(), WIFI_ALWAYS_REQUESTED, (def ? 1 : 0)); - return (enable != 0) ? true : false; - } - - /** - * Write into {@link Settings} whether the wifi data connection should remain active - * even when higher priority networks are active. - * - * @param context The {@link Context} to set the setting. - * @param enable Whether the wifi data connection should remain active even when higher - * priority networks are active - */ - public static void setWifiAlwaysRequested(@NonNull Context context, boolean enable) { - Settings.Global.putInt( - context.getContentResolver(), WIFI_ALWAYS_REQUESTED, (enable ? 1 : 0)); - } - - /** - * Get avoid bad wifi setting from {@link Settings}. - * - * @param context The {@link Context} to query the setting. - * @return The setting whether to automatically switch away from wifi networks that lose - * internet access. - */ - @NetworkAvoidBadWifi - public static int getNetworkAvoidBadWifi(@NonNull Context context) { - final String setting = - Settings.Global.getString(context.getContentResolver(), NETWORK_AVOID_BAD_WIFI); - if ("0".equals(setting)) { - return NETWORK_AVOID_BAD_WIFI_IGNORE; - } else if ("1".equals(setting)) { - return NETWORK_AVOID_BAD_WIFI_AVOID; - } else { - return NETWORK_AVOID_BAD_WIFI_PROMPT; - } - } - - /** - * Set avoid bad wifi setting to {@link Settings}. - * - * @param context The {@link Context} to set the setting. - * @param value Whether to automatically switch away from wifi networks that lose internet - * access. - */ - public static void setNetworkAvoidBadWifi(@NonNull Context context, - @NetworkAvoidBadWifi int value) { - final String setting; - if (value == NETWORK_AVOID_BAD_WIFI_IGNORE) { - setting = "0"; - } else if (value == NETWORK_AVOID_BAD_WIFI_AVOID) { - setting = "1"; - } else if (value == NETWORK_AVOID_BAD_WIFI_PROMPT) { - setting = null; - } else { - throw new IllegalArgumentException("Invalid avoid bad wifi setting"); - } - Settings.Global.putString(context.getContentResolver(), NETWORK_AVOID_BAD_WIFI, setting); - } - - /** - * Get network metered multipath preference from {@link Settings}. - * - * @param context The {@link Context} to query the setting. - * @return The network metered multipath preference which should be one of - * ConnectivityManager#MULTIPATH_PREFERENCE_* value or null if the value specified - * by config_networkMeteredMultipathPreference is used. - */ - @Nullable - public static String getNetworkMeteredMultipathPreference(@NonNull Context context) { - return Settings.Global.getString( - context.getContentResolver(), NETWORK_METERED_MULTIPATH_PREFERENCE); - } - - /** - * Set network metered multipath preference to {@link Settings}. - * - * @param context The {@link Context} to set the setting. - * @param preference The network metered multipath preference which should be one of - * ConnectivityManager#MULTIPATH_PREFERENCE_* value or null if the value - * specified by config_networkMeteredMultipathPreference is used. - */ - public static void setNetworkMeteredMultipathPreference(@NonNull Context context, - @NonNull @MultipathPreference String preference) { - if (!(Integer.valueOf(preference) == MULTIPATH_PREFERENCE_HANDOVER - || Integer.valueOf(preference) == MULTIPATH_PREFERENCE_RELIABILITY - || Integer.valueOf(preference) == MULTIPATH_PREFERENCE_PERFORMANCE)) { - throw new IllegalArgumentException("Invalid private dns mode"); - } - Settings.Global.putString( - context.getContentResolver(), NETWORK_METERED_MULTIPATH_PREFERENCE, preference); - } - - /** - * Get the list of uids(from {@link Settings}) that should go on cellular networks in preference - * even when higher-priority networks are connected. - * - * @param context The {@link Context} to query the setting. - * @return A list of uids that should go on cellular networks in preference even when - * higher-priority networks are connected or null if no setting value. - */ - @NonNull - public static Set getMobileDataPreferredUids(@NonNull Context context) { - final String uidList = Settings.Secure.getString( - context.getContentResolver(), MOBILE_DATA_PREFERRED_UIDS); - final Set uids = new ArraySet<>(); - if (TextUtils.isEmpty(uidList)) { - return uids; - } - for (String uid : uidList.split(";")) { - uids.add(Integer.valueOf(uid)); - } - return uids; - } - - /** - * Set the list of uids(to {@link Settings}) that should go on cellular networks in preference - * even when higher-priority networks are connected. - * - * @param context The {@link Context} to set the setting. - * @param uidList A list of uids that should go on cellular networks in preference even when - * higher-priority networks are connected. - */ - public static void setMobileDataPreferredUids(@NonNull Context context, - @NonNull Set uidList) { - final StringJoiner joiner = new StringJoiner(";"); - for (Integer uid : uidList) { - if (uid < 0 || UserHandle.getAppId(uid) > Process.LAST_APPLICATION_UID) { - throw new IllegalArgumentException("Invalid uid"); - } - joiner.add(uid.toString()); - } - Settings.Secure.putString( - context.getContentResolver(), MOBILE_DATA_PREFERRED_UIDS, joiner.toString()); - } - - /** - * Get the list of apps(from {@link Settings}) that is allowed on restricted networks. - * - * @param context The {@link Context} to query the setting. - * @return A list of apps that is allowed on restricted networks or null if no setting - * value. - */ - @NonNull - public static Set getAppsAllowedOnRestrictedNetworks(@NonNull Context context) { - final String appList = Settings.Secure.getString( - context.getContentResolver(), APPS_ALLOWED_ON_RESTRICTED_NETWORKS); - if (TextUtils.isEmpty(appList)) { - return new ArraySet<>(); - } - return new ArraySet<>(appList.split(";")); - } - - /** - * Set the list of apps(from {@link Settings}) that is allowed on restricted networks. - * - * Note: Please refer to android developer guidelines for valid app(package name). - * https://developer.android.com/guide/topics/manifest/manifest-element.html#package - * - * @param context The {@link Context} to set the setting. - * @param list A list of apps that is allowed on restricted networks. - */ - public static void setAppsAllowedOnRestrictedNetworks(@NonNull Context context, - @NonNull Set list) { - final StringJoiner joiner = new StringJoiner(";"); - for (String app : list) { - if (app == null || app.contains(";")) { - throw new IllegalArgumentException("Invalid app(package name)"); - } - joiner.add(app); - } - Settings.Secure.putString(context.getContentResolver(), APPS_ALLOWED_ON_RESTRICTED_NETWORKS, - joiner.toString()); - } -} diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityThread.java b/packages/Connectivity/framework/src/android/net/ConnectivityThread.java deleted file mode 100644 index 0b218e738b779..0000000000000 --- a/packages/Connectivity/framework/src/android/net/ConnectivityThread.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.os.HandlerThread; -import android.os.Looper; - -/** - * Shared singleton connectivity thread for the system. This is a thread for - * connectivity operations such as AsyncChannel connections to system services. - * Various connectivity manager objects can use this singleton as a common - * resource for their handlers instead of creating separate threads of their own. - * @hide - */ -public final class ConnectivityThread extends HandlerThread { - - // A class implementing the lazy holder idiom: the unique static instance - // of ConnectivityThread is instantiated in a thread-safe way (guaranteed by - // the language specs) the first time that Singleton is referenced in get() - // or getInstanceLooper(). - private static class Singleton { - private static final ConnectivityThread INSTANCE = createInstance(); - } - - private ConnectivityThread() { - super("ConnectivityThread"); - } - - private static ConnectivityThread createInstance() { - ConnectivityThread t = new ConnectivityThread(); - t.start(); - return t; - } - - public static ConnectivityThread get() { - return Singleton.INSTANCE; - } - - public static Looper getInstanceLooper() { - return Singleton.INSTANCE.getLooper(); - } -} diff --git a/packages/Connectivity/framework/src/android/net/DhcpInfo.java b/packages/Connectivity/framework/src/android/net/DhcpInfo.java deleted file mode 100644 index 912df67a0b45b..0000000000000 --- a/packages/Connectivity/framework/src/android/net/DhcpInfo.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.os.Parcel; -import android.os.Parcelable; - -/** - * A simple object for retrieving the results of a DHCP request. - */ -public class DhcpInfo implements Parcelable { - public int ipAddress; - public int gateway; - public int netmask; - public int dns1; - public int dns2; - public int serverAddress; - - public int leaseDuration; - - public DhcpInfo() { - super(); - } - - /** copy constructor {@hide} */ - public DhcpInfo(DhcpInfo source) { - if (source != null) { - ipAddress = source.ipAddress; - gateway = source.gateway; - netmask = source.netmask; - dns1 = source.dns1; - dns2 = source.dns2; - serverAddress = source.serverAddress; - leaseDuration = source.leaseDuration; - } - } - - public String toString() { - StringBuffer str = new StringBuffer(); - - str.append("ipaddr "); putAddress(str, ipAddress); - str.append(" gateway "); putAddress(str, gateway); - str.append(" netmask "); putAddress(str, netmask); - str.append(" dns1 "); putAddress(str, dns1); - str.append(" dns2 "); putAddress(str, dns2); - str.append(" DHCP server "); putAddress(str, serverAddress); - str.append(" lease ").append(leaseDuration).append(" seconds"); - - return str.toString(); - } - - private static void putAddress(StringBuffer buf, int addr) { - buf.append(NetworkUtils.intToInetAddress(addr).getHostAddress()); - } - - /** Implement the Parcelable interface */ - public int describeContents() { - return 0; - } - - /** Implement the Parcelable interface */ - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(ipAddress); - dest.writeInt(gateway); - dest.writeInt(netmask); - dest.writeInt(dns1); - dest.writeInt(dns2); - dest.writeInt(serverAddress); - dest.writeInt(leaseDuration); - } - - /** Implement the Parcelable interface */ - public static final @android.annotation.NonNull Creator CREATOR = - new Creator() { - public DhcpInfo createFromParcel(Parcel in) { - DhcpInfo info = new DhcpInfo(); - info.ipAddress = in.readInt(); - info.gateway = in.readInt(); - info.netmask = in.readInt(); - info.dns1 = in.readInt(); - info.dns2 = in.readInt(); - info.serverAddress = in.readInt(); - info.leaseDuration = in.readInt(); - return info; - } - - public DhcpInfo[] newArray(int size) { - return new DhcpInfo[size]; - } - }; -} diff --git a/packages/Connectivity/framework/src/android/net/DnsResolver.java b/packages/Connectivity/framework/src/android/net/DnsResolver.java deleted file mode 100644 index dac88ad907526..0000000000000 --- a/packages/Connectivity/framework/src/android/net/DnsResolver.java +++ /dev/null @@ -1,577 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static android.net.NetworkUtils.getDnsNetwork; -import static android.net.NetworkUtils.resNetworkCancel; -import static android.net.NetworkUtils.resNetworkQuery; -import static android.net.NetworkUtils.resNetworkResult; -import static android.net.NetworkUtils.resNetworkSend; -import static android.net.util.DnsUtils.haveIpv4; -import static android.net.util.DnsUtils.haveIpv6; -import static android.net.util.DnsUtils.rfc6724Sort; -import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR; -import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT; -import static android.system.OsConstants.ENONET; - -import android.annotation.CallbackExecutor; -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.os.CancellationSignal; -import android.os.Looper; -import android.os.MessageQueue; -import android.system.ErrnoException; -import android.util.Log; - -import com.android.net.module.util.DnsPacket; - -import java.io.FileDescriptor; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Executor; - -/** - * Dns resolver class for asynchronous dns querying - * - * Note that if a client sends a query with more than 1 record in the question section but - * the remote dns server does not support this, it may not respond at all, leading to a timeout. - * - */ -public final class DnsResolver { - private static final String TAG = "DnsResolver"; - private static final int FD_EVENTS = EVENT_INPUT | EVENT_ERROR; - private static final int MAXPACKET = 8 * 1024; - private static final int SLEEP_TIME_MS = 2; - - @IntDef(prefix = { "CLASS_" }, value = { - CLASS_IN - }) - @Retention(RetentionPolicy.SOURCE) - @interface QueryClass {} - public static final int CLASS_IN = 1; - - @IntDef(prefix = { "TYPE_" }, value = { - TYPE_A, - TYPE_AAAA - }) - @Retention(RetentionPolicy.SOURCE) - @interface QueryType {} - public static final int TYPE_A = 1; - public static final int TYPE_AAAA = 28; - - @IntDef(prefix = { "FLAG_" }, value = { - FLAG_EMPTY, - FLAG_NO_RETRY, - FLAG_NO_CACHE_STORE, - FLAG_NO_CACHE_LOOKUP - }) - @Retention(RetentionPolicy.SOURCE) - @interface QueryFlag {} - public static final int FLAG_EMPTY = 0; - public static final int FLAG_NO_RETRY = 1 << 0; - public static final int FLAG_NO_CACHE_STORE = 1 << 1; - public static final int FLAG_NO_CACHE_LOOKUP = 1 << 2; - - @IntDef(prefix = { "ERROR_" }, value = { - ERROR_PARSE, - ERROR_SYSTEM - }) - @Retention(RetentionPolicy.SOURCE) - @interface DnsError {} - /** - * Indicates that there was an error parsing the response the query. - * The cause of this error is available via getCause() and is a {@link ParseException}. - */ - public static final int ERROR_PARSE = 0; - /** - * Indicates that there was an error sending the query. - * The cause of this error is available via getCause() and is an ErrnoException. - */ - public static final int ERROR_SYSTEM = 1; - - private static final int NETID_UNSET = 0; - - private static final DnsResolver sInstance = new DnsResolver(); - - /** - * Get instance for DnsResolver - */ - public static @NonNull DnsResolver getInstance() { - return sInstance; - } - - private DnsResolver() {} - - /** - * Base interface for answer callbacks - * - * @param The type of the answer - */ - public interface Callback { - /** - * Success response to - * {@link android.net.DnsResolver#query query()} or - * {@link android.net.DnsResolver#rawQuery rawQuery()}. - * - * Invoked when the answer to a query was successfully parsed. - * - * @param answer answer to the query. - * @param rcode The response code in the DNS response. - * - * {@see android.net.DnsResolver#query query()} - */ - void onAnswer(@NonNull T answer, int rcode); - /** - * Error response to - * {@link android.net.DnsResolver#query query()} or - * {@link android.net.DnsResolver#rawQuery rawQuery()}. - * - * Invoked when there is no valid answer to - * {@link android.net.DnsResolver#query query()} - * {@link android.net.DnsResolver#rawQuery rawQuery()}. - * - * @param error a {@link DnsException} object with additional - * detail regarding the failure - */ - void onError(@NonNull DnsException error); - } - - /** - * Class to represent DNS error - */ - public static class DnsException extends Exception { - /** - * DNS error code as one of the ERROR_* constants - */ - @DnsError public final int code; - - DnsException(@DnsError int code, @Nullable Throwable cause) { - super(cause); - this.code = code; - } - } - - /** - * Send a raw DNS query. - * The answer will be provided asynchronously through the provided {@link Callback}. - * - * @param network {@link Network} specifying which network to query on. - * {@code null} for query on default network. - * @param query blob message to query - * @param flags flags as a combination of the FLAGS_* constants - * @param executor The {@link Executor} that the callback should be executed on. - * @param cancellationSignal used by the caller to signal if the query should be - * cancelled. May be {@code null}. - * @param callback a {@link Callback} which will be called to notify the caller - * of the result of dns query. - */ - public void rawQuery(@Nullable Network network, @NonNull byte[] query, @QueryFlag int flags, - @NonNull @CallbackExecutor Executor executor, - @Nullable CancellationSignal cancellationSignal, - @NonNull Callback callback) { - if (cancellationSignal != null && cancellationSignal.isCanceled()) { - return; - } - final Object lock = new Object(); - final FileDescriptor queryfd; - try { - queryfd = resNetworkSend((network != null) - ? network.getNetIdForResolv() : NETID_UNSET, query, query.length, flags); - } catch (ErrnoException e) { - executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e))); - return; - } - - synchronized (lock) { - registerFDListener(executor, queryfd, callback, cancellationSignal, lock); - if (cancellationSignal == null) return; - addCancellationSignal(cancellationSignal, queryfd, lock); - } - } - - /** - * Send a DNS query with the specified name, class and query type. - * The answer will be provided asynchronously through the provided {@link Callback}. - * - * @param network {@link Network} specifying which network to query on. - * {@code null} for query on default network. - * @param domain domain name to query - * @param nsClass dns class as one of the CLASS_* constants - * @param nsType dns resource record (RR) type as one of the TYPE_* constants - * @param flags flags as a combination of the FLAGS_* constants - * @param executor The {@link Executor} that the callback should be executed on. - * @param cancellationSignal used by the caller to signal if the query should be - * cancelled. May be {@code null}. - * @param callback a {@link Callback} which will be called to notify the caller - * of the result of dns query. - */ - public void rawQuery(@Nullable Network network, @NonNull String domain, - @QueryClass int nsClass, @QueryType int nsType, @QueryFlag int flags, - @NonNull @CallbackExecutor Executor executor, - @Nullable CancellationSignal cancellationSignal, - @NonNull Callback callback) { - if (cancellationSignal != null && cancellationSignal.isCanceled()) { - return; - } - final Object lock = new Object(); - final FileDescriptor queryfd; - try { - queryfd = resNetworkQuery((network != null) - ? network.getNetIdForResolv() : NETID_UNSET, domain, nsClass, nsType, flags); - } catch (ErrnoException e) { - executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e))); - return; - } - synchronized (lock) { - registerFDListener(executor, queryfd, callback, cancellationSignal, lock); - if (cancellationSignal == null) return; - addCancellationSignal(cancellationSignal, queryfd, lock); - } - } - - private class InetAddressAnswerAccumulator implements Callback { - private final List mAllAnswers; - private final Network mNetwork; - private int mRcode; - private DnsException mDnsException; - private final Callback> mUserCallback; - private final int mTargetAnswerCount; - private int mReceivedAnswerCount = 0; - - InetAddressAnswerAccumulator(@NonNull Network network, int size, - @NonNull Callback> callback) { - mNetwork = network; - mTargetAnswerCount = size; - mAllAnswers = new ArrayList<>(); - mUserCallback = callback; - } - - private boolean maybeReportError() { - if (mRcode != 0) { - mUserCallback.onAnswer(mAllAnswers, mRcode); - return true; - } - if (mDnsException != null) { - mUserCallback.onError(mDnsException); - return true; - } - return false; - } - - private void maybeReportAnswer() { - if (++mReceivedAnswerCount != mTargetAnswerCount) return; - if (mAllAnswers.isEmpty() && maybeReportError()) return; - mUserCallback.onAnswer(rfc6724Sort(mNetwork, mAllAnswers), mRcode); - } - - @Override - public void onAnswer(@NonNull byte[] answer, int rcode) { - // If at least one query succeeded, return an rcode of 0. - // Otherwise, arbitrarily return the first rcode received. - if (mReceivedAnswerCount == 0 || rcode == 0) { - mRcode = rcode; - } - try { - mAllAnswers.addAll(new DnsAddressAnswer(answer).getAddresses()); - } catch (DnsPacket.ParseException e) { - // Convert the com.android.net.module.util.DnsPacket.ParseException to an - // android.net.ParseException. This is the type that was used in Q and is implied - // by the public documentation of ERROR_PARSE. - // - // DnsPacket cannot throw android.net.ParseException directly because it's @hide. - ParseException pe = new ParseException(e.reason, e.getCause()); - pe.setStackTrace(e.getStackTrace()); - mDnsException = new DnsException(ERROR_PARSE, pe); - } - maybeReportAnswer(); - } - - @Override - public void onError(@NonNull DnsException error) { - mDnsException = error; - maybeReportAnswer(); - } - } - - /** - * Send a DNS query with the specified name on a network with both IPv4 and IPv6, - * get back a set of InetAddresses with rfc6724 sorting style asynchronously. - * - * This method will examine the connection ability on given network, and query IPv4 - * and IPv6 if connection is available. - * - * If at least one query succeeded with valid answer, rcode will be 0 - * - * The answer will be provided asynchronously through the provided {@link Callback}. - * - * @param network {@link Network} specifying which network to query on. - * {@code null} for query on default network. - * @param domain domain name to query - * @param flags flags as a combination of the FLAGS_* constants - * @param executor The {@link Executor} that the callback should be executed on. - * @param cancellationSignal used by the caller to signal if the query should be - * cancelled. May be {@code null}. - * @param callback a {@link Callback} which will be called to notify the - * caller of the result of dns query. - */ - public void query(@Nullable Network network, @NonNull String domain, @QueryFlag int flags, - @NonNull @CallbackExecutor Executor executor, - @Nullable CancellationSignal cancellationSignal, - @NonNull Callback> callback) { - if (cancellationSignal != null && cancellationSignal.isCanceled()) { - return; - } - final Object lock = new Object(); - final Network queryNetwork; - try { - queryNetwork = (network != null) ? network : getDnsNetwork(); - } catch (ErrnoException e) { - executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e))); - return; - } - final boolean queryIpv6 = haveIpv6(queryNetwork); - final boolean queryIpv4 = haveIpv4(queryNetwork); - - // This can only happen if queryIpv4 and queryIpv6 are both false. - // This almost certainly means that queryNetwork does not exist or no longer exists. - if (!queryIpv6 && !queryIpv4) { - executor.execute(() -> callback.onError( - new DnsException(ERROR_SYSTEM, new ErrnoException("resNetworkQuery", ENONET)))); - return; - } - - final FileDescriptor v4fd; - final FileDescriptor v6fd; - - int queryCount = 0; - - if (queryIpv6) { - try { - v6fd = resNetworkQuery(queryNetwork.getNetIdForResolv(), domain, CLASS_IN, - TYPE_AAAA, flags); - } catch (ErrnoException e) { - executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e))); - return; - } - queryCount++; - } else v6fd = null; - - // Avoiding gateways drop packets if queries are sent too close together - try { - Thread.sleep(SLEEP_TIME_MS); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - } - - if (queryIpv4) { - try { - v4fd = resNetworkQuery(queryNetwork.getNetIdForResolv(), domain, CLASS_IN, TYPE_A, - flags); - } catch (ErrnoException e) { - if (queryIpv6) resNetworkCancel(v6fd); // Closes fd, marks it invalid. - executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e))); - return; - } - queryCount++; - } else v4fd = null; - - final InetAddressAnswerAccumulator accumulator = - new InetAddressAnswerAccumulator(queryNetwork, queryCount, callback); - - synchronized (lock) { - if (queryIpv6) { - registerFDListener(executor, v6fd, accumulator, cancellationSignal, lock); - } - if (queryIpv4) { - registerFDListener(executor, v4fd, accumulator, cancellationSignal, lock); - } - if (cancellationSignal == null) return; - cancellationSignal.setOnCancelListener(() -> { - synchronized (lock) { - if (queryIpv4) cancelQuery(v4fd); - if (queryIpv6) cancelQuery(v6fd); - } - }); - } - } - - /** - * Send a DNS query with the specified name and query type, get back a set of - * InetAddresses with rfc6724 sorting style asynchronously. - * - * The answer will be provided asynchronously through the provided {@link Callback}. - * - * @param network {@link Network} specifying which network to query on. - * {@code null} for query on default network. - * @param domain domain name to query - * @param nsType dns resource record (RR) type as one of the TYPE_* constants - * @param flags flags as a combination of the FLAGS_* constants - * @param executor The {@link Executor} that the callback should be executed on. - * @param cancellationSignal used by the caller to signal if the query should be - * cancelled. May be {@code null}. - * @param callback a {@link Callback} which will be called to notify the caller - * of the result of dns query. - */ - public void query(@Nullable Network network, @NonNull String domain, - @QueryType int nsType, @QueryFlag int flags, - @NonNull @CallbackExecutor Executor executor, - @Nullable CancellationSignal cancellationSignal, - @NonNull Callback> callback) { - if (cancellationSignal != null && cancellationSignal.isCanceled()) { - return; - } - final Object lock = new Object(); - final FileDescriptor queryfd; - final Network queryNetwork; - try { - queryNetwork = (network != null) ? network : getDnsNetwork(); - queryfd = resNetworkQuery(queryNetwork.getNetIdForResolv(), domain, CLASS_IN, nsType, - flags); - } catch (ErrnoException e) { - executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e))); - return; - } - final InetAddressAnswerAccumulator accumulator = - new InetAddressAnswerAccumulator(queryNetwork, 1, callback); - synchronized (lock) { - registerFDListener(executor, queryfd, accumulator, cancellationSignal, lock); - if (cancellationSignal == null) return; - addCancellationSignal(cancellationSignal, queryfd, lock); - } - } - - /** - * Class to retrieve DNS response - * - * @hide - */ - public static final class DnsResponse { - public final @NonNull byte[] answerbuf; - public final int rcode; - public DnsResponse(@NonNull byte[] answerbuf, int rcode) { - this.answerbuf = answerbuf; - this.rcode = rcode; - } - } - - private void registerFDListener(@NonNull Executor executor, - @NonNull FileDescriptor queryfd, @NonNull Callback answerCallback, - @Nullable CancellationSignal cancellationSignal, @NonNull Object lock) { - final MessageQueue mainThreadMessageQueue = Looper.getMainLooper().getQueue(); - mainThreadMessageQueue.addOnFileDescriptorEventListener( - queryfd, - FD_EVENTS, - (fd, events) -> { - // b/134310704 - // Unregister fd event listener before resNetworkResult is called to prevent - // race condition caused by fd reused. - // For example when querying v4 and v6, it's possible that the first query ends - // and the fd is closed before the second request starts, which might return - // the same fd for the second request. By that time, the looper must have - // unregistered the fd, otherwise another event listener can't be registered. - mainThreadMessageQueue.removeOnFileDescriptorEventListener(fd); - - executor.execute(() -> { - DnsResponse resp = null; - ErrnoException exception = null; - synchronized (lock) { - if (cancellationSignal != null && cancellationSignal.isCanceled()) { - return; - } - try { - resp = resNetworkResult(fd); // Closes fd, marks it invalid. - } catch (ErrnoException e) { - Log.w(TAG, "resNetworkResult:" + e.toString()); - exception = e; - } - } - if (exception != null) { - answerCallback.onError(new DnsException(ERROR_SYSTEM, exception)); - return; - } - answerCallback.onAnswer(resp.answerbuf, resp.rcode); - }); - - // The file descriptor has already been unregistered, so it does not really - // matter what is returned here. In spirit 0 (meaning "unregister this FD") - // is still the closest to what the looper needs to do. When returning 0, - // Looper knows to ignore the fd if it has already been unregistered. - return 0; - }); - } - - private void cancelQuery(@NonNull FileDescriptor queryfd) { - if (!queryfd.valid()) return; - Looper.getMainLooper().getQueue().removeOnFileDescriptorEventListener(queryfd); - resNetworkCancel(queryfd); // Closes fd, marks it invalid. - } - - private void addCancellationSignal(@NonNull CancellationSignal cancellationSignal, - @NonNull FileDescriptor queryfd, @NonNull Object lock) { - cancellationSignal.setOnCancelListener(() -> { - synchronized (lock) { - cancelQuery(queryfd); - } - }); - } - - private static class DnsAddressAnswer extends DnsPacket { - private static final String TAG = "DnsResolver.DnsAddressAnswer"; - private static final boolean DBG = false; - - private final int mQueryType; - - DnsAddressAnswer(@NonNull byte[] data) throws ParseException { - super(data); - if ((mHeader.flags & (1 << 15)) == 0) { - throw new ParseException("Not an answer packet"); - } - if (mHeader.getRecordCount(QDSECTION) == 0) { - throw new ParseException("No question found"); - } - // Expect only one question in question section. - mQueryType = mRecords[QDSECTION].get(0).nsType; - } - - public @NonNull List getAddresses() { - final List results = new ArrayList(); - if (mHeader.getRecordCount(ANSECTION) == 0) return results; - - for (final DnsRecord ansSec : mRecords[ANSECTION]) { - // Only support A and AAAA, also ignore answers if query type != answer type. - int nsType = ansSec.nsType; - if (nsType != mQueryType || (nsType != TYPE_A && nsType != TYPE_AAAA)) { - continue; - } - try { - results.add(InetAddress.getByAddress(ansSec.getRR())); - } catch (UnknownHostException e) { - if (DBG) { - Log.w(TAG, "rr to address fail"); - } - } - } - return results; - } - } - -} diff --git a/packages/Connectivity/framework/src/android/net/DnsResolverServiceManager.java b/packages/Connectivity/framework/src/android/net/DnsResolverServiceManager.java deleted file mode 100644 index 79009e8d629eb..0000000000000 --- a/packages/Connectivity/framework/src/android/net/DnsResolverServiceManager.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.net; - -import android.annotation.NonNull; -import android.os.IBinder; - -/** - * Provides a way to obtain the DnsResolver binder objects. - * - * @hide - */ -public class DnsResolverServiceManager { - /** Service name for the DNS resolver. Keep in sync with DnsResolverService.h */ - public static final String DNS_RESOLVER_SERVICE = "dnsresolver"; - - private final IBinder mResolver; - - DnsResolverServiceManager(IBinder resolver) { - mResolver = resolver; - } - - /** - * Get an {@link IBinder} representing the DnsResolver stable AIDL interface - * - * @return {@link android.net.IDnsResolver} IBinder. - */ - @NonNull - public IBinder getService() { - return mResolver; - } -} diff --git a/packages/Connectivity/framework/src/android/net/ICaptivePortal.aidl b/packages/Connectivity/framework/src/android/net/ICaptivePortal.aidl deleted file mode 100644 index e35f8d46afe74..0000000000000 --- a/packages/Connectivity/framework/src/android/net/ICaptivePortal.aidl +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright (c) 2015, 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; - -/** - * Interface to inform NetworkMonitor of decisions of app handling captive portal. - * @hide - */ -oneway interface ICaptivePortal { - void appRequest(int request); - void appResponse(int response); -} diff --git a/packages/Connectivity/framework/src/android/net/IConnectivityDiagnosticsCallback.aidl b/packages/Connectivity/framework/src/android/net/IConnectivityDiagnosticsCallback.aidl deleted file mode 100644 index 82b64a9280009..0000000000000 --- a/packages/Connectivity/framework/src/android/net/IConnectivityDiagnosticsCallback.aidl +++ /dev/null @@ -1,28 +0,0 @@ -/** - * - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.net.ConnectivityDiagnosticsManager; -import android.net.Network; - -/** @hide */ -oneway interface IConnectivityDiagnosticsCallback { - void onConnectivityReportAvailable(in ConnectivityDiagnosticsManager.ConnectivityReport report); - void onDataStallSuspected(in ConnectivityDiagnosticsManager.DataStallReport report); - void onNetworkConnectivityReported(in Network n, boolean hasConnectivity); -} \ No newline at end of file diff --git a/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl b/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl deleted file mode 100644 index c434bbcb0f51d..0000000000000 --- a/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl +++ /dev/null @@ -1,229 +0,0 @@ -/** - * Copyright (c) 2008, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.app.PendingIntent; -import android.net.ConnectionInfo; -import android.net.ConnectivityDiagnosticsManager; -import android.net.IConnectivityDiagnosticsCallback; -import android.net.INetworkAgent; -import android.net.IOnCompleteListener; -import android.net.INetworkActivityListener; -import android.net.INetworkOfferCallback; -import android.net.IQosCallback; -import android.net.ISocketKeepaliveCallback; -import android.net.LinkProperties; -import android.net.Network; -import android.net.NetworkAgentConfig; -import android.net.NetworkCapabilities; -import android.net.NetworkInfo; -import android.net.NetworkRequest; -import android.net.NetworkScore; -import android.net.NetworkState; -import android.net.NetworkStateSnapshot; -import android.net.OemNetworkPreferences; -import android.net.ProxyInfo; -import android.net.UidRange; -import android.net.QosSocketInfo; -import android.os.Bundle; -import android.os.IBinder; -import android.os.Messenger; -import android.os.ParcelFileDescriptor; -import android.os.PersistableBundle; -import android.os.ResultReceiver; -import android.os.UserHandle; - -/** - * Interface that answers queries about, and allows changing, the - * state of network connectivity. - */ -/** {@hide} */ -interface IConnectivityManager -{ - Network getActiveNetwork(); - Network getActiveNetworkForUid(int uid, boolean ignoreBlocked); - @UnsupportedAppUsage - NetworkInfo getActiveNetworkInfo(); - NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked); - @UnsupportedAppUsage(maxTargetSdk = 28) - NetworkInfo getNetworkInfo(int networkType); - NetworkInfo getNetworkInfoForUid(in Network network, int uid, boolean ignoreBlocked); - @UnsupportedAppUsage - NetworkInfo[] getAllNetworkInfo(); - Network getNetworkForType(int networkType); - Network[] getAllNetworks(); - NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser( - int userId, String callingPackageName, String callingAttributionTag); - - boolean isNetworkSupported(int networkType); - - @UnsupportedAppUsage - LinkProperties getActiveLinkProperties(); - LinkProperties getLinkPropertiesForType(int networkType); - LinkProperties getLinkProperties(in Network network); - - NetworkCapabilities getNetworkCapabilities(in Network network, String callingPackageName, - String callingAttributionTag); - - @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) - NetworkState[] getAllNetworkState(); - - List getAllNetworkStateSnapshots(); - - boolean isActiveNetworkMetered(); - - boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress, - String callingPackageName, String callingAttributionTag); - - @UnsupportedAppUsage(maxTargetSdk = 29, - publicAlternatives = "Use {@code TetheringManager#getLastTetherError} as alternative") - int getLastTetherError(String iface); - - @UnsupportedAppUsage(maxTargetSdk = 29, - publicAlternatives = "Use {@code TetheringManager#getTetherableIfaces} as alternative") - String[] getTetherableIfaces(); - - @UnsupportedAppUsage(maxTargetSdk = 29, - publicAlternatives = "Use {@code TetheringManager#getTetheredIfaces} as alternative") - String[] getTetheredIfaces(); - - @UnsupportedAppUsage(maxTargetSdk = 29, - publicAlternatives = "Use {@code TetheringManager#getTetheringErroredIfaces} " - + "as Alternative") - String[] getTetheringErroredIfaces(); - - @UnsupportedAppUsage(maxTargetSdk = 29, - publicAlternatives = "Use {@code TetheringManager#getTetherableUsbRegexs} as alternative") - String[] getTetherableUsbRegexs(); - - @UnsupportedAppUsage(maxTargetSdk = 29, - publicAlternatives = "Use {@code TetheringManager#getTetherableWifiRegexs} as alternative") - String[] getTetherableWifiRegexs(); - - @UnsupportedAppUsage(maxTargetSdk = 28) - void reportInetCondition(int networkType, int percentage); - - void reportNetworkConnectivity(in Network network, boolean hasConnectivity); - - ProxyInfo getGlobalProxy(); - - void setGlobalProxy(in ProxyInfo p); - - ProxyInfo getProxyForNetwork(in Network nework); - - void setRequireVpnForUids(boolean requireVpn, in UidRange[] ranges); - void setLegacyLockdownVpnEnabled(boolean enabled); - - void setProvisioningNotificationVisible(boolean visible, int networkType, in String action); - - void setAirplaneMode(boolean enable); - - boolean requestBandwidthUpdate(in Network network); - - int registerNetworkProvider(in Messenger messenger, in String name); - void unregisterNetworkProvider(in Messenger messenger); - - void declareNetworkRequestUnfulfillable(in NetworkRequest request); - - Network registerNetworkAgent(in INetworkAgent na, in NetworkInfo ni, in LinkProperties lp, - in NetworkCapabilities nc, in NetworkScore score, in NetworkAgentConfig config, - in int factorySerialNumber); - - NetworkRequest requestNetwork(int uid, in NetworkCapabilities networkCapabilities, int reqType, - in Messenger messenger, int timeoutSec, in IBinder binder, int legacy, - int callbackFlags, String callingPackageName, String callingAttributionTag); - - NetworkRequest pendingRequestForNetwork(in NetworkCapabilities networkCapabilities, - in PendingIntent operation, String callingPackageName, String callingAttributionTag); - - void releasePendingNetworkRequest(in PendingIntent operation); - - NetworkRequest listenForNetwork(in NetworkCapabilities networkCapabilities, - in Messenger messenger, in IBinder binder, int callbackFlags, String callingPackageName, - String callingAttributionTag); - - void pendingListenForNetwork(in NetworkCapabilities networkCapabilities, - in PendingIntent operation, String callingPackageName, - String callingAttributionTag); - - void releaseNetworkRequest(in NetworkRequest networkRequest); - - void setAcceptUnvalidated(in Network network, boolean accept, boolean always); - void setAcceptPartialConnectivity(in Network network, boolean accept, boolean always); - void setAvoidUnvalidated(in Network network); - void startCaptivePortalApp(in Network network); - void startCaptivePortalAppInternal(in Network network, in Bundle appExtras); - - boolean shouldAvoidBadWifi(); - int getMultipathPreference(in Network Network); - - NetworkRequest getDefaultRequest(); - - int getRestoreDefaultNetworkDelay(int networkType); - - void factoryReset(); - - void startNattKeepalive(in Network network, int intervalSeconds, - in ISocketKeepaliveCallback cb, String srcAddr, int srcPort, String dstAddr); - - void startNattKeepaliveWithFd(in Network network, in ParcelFileDescriptor pfd, int resourceId, - int intervalSeconds, in ISocketKeepaliveCallback cb, String srcAddr, - String dstAddr); - - void startTcpKeepalive(in Network network, in ParcelFileDescriptor pfd, int intervalSeconds, - in ISocketKeepaliveCallback cb); - - void stopKeepalive(in Network network, int slot); - - String getCaptivePortalServerUrl(); - - byte[] getNetworkWatchlistConfigHash(); - - int getConnectionOwnerUid(in ConnectionInfo connectionInfo); - - void registerConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback, - in NetworkRequest request, String callingPackageName); - void unregisterConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback); - - IBinder startOrGetTestNetworkService(); - - void simulateDataStall(int detectionMethod, long timestampMillis, in Network network, - in PersistableBundle extras); - - void systemReady(); - - void registerNetworkActivityListener(in INetworkActivityListener l); - - void unregisterNetworkActivityListener(in INetworkActivityListener l); - - boolean isDefaultNetworkActive(); - - void registerQosSocketCallback(in QosSocketInfo socketInfo, in IQosCallback callback); - void unregisterQosCallback(in IQosCallback callback); - - void setOemNetworkPreference(in OemNetworkPreferences preference, - in IOnCompleteListener listener); - - void setProfileNetworkPreference(in UserHandle profile, int preference, - in IOnCompleteListener listener); - - int getRestrictBackgroundStatusByCaller(); - - void offerNetwork(int providerId, in NetworkScore score, - in NetworkCapabilities caps, in INetworkOfferCallback callback); - void unofferNetwork(in INetworkOfferCallback callback); -} diff --git a/packages/Connectivity/framework/src/android/net/INetworkActivityListener.aidl b/packages/Connectivity/framework/src/android/net/INetworkActivityListener.aidl deleted file mode 100644 index 79687dd3bf06e..0000000000000 --- a/packages/Connectivity/framework/src/android/net/INetworkActivityListener.aidl +++ /dev/null @@ -1,24 +0,0 @@ -/* Copyright 2013, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -package android.net; - -/** - * @hide - */ -oneway interface INetworkActivityListener -{ - void onNetworkActive(); -} diff --git a/packages/Connectivity/framework/src/android/net/INetworkAgent.aidl b/packages/Connectivity/framework/src/android/net/INetworkAgent.aidl deleted file mode 100644 index d941d4b95b56a..0000000000000 --- a/packages/Connectivity/framework/src/android/net/INetworkAgent.aidl +++ /dev/null @@ -1,51 +0,0 @@ -/** - * 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. - */ -package android.net; - -import android.net.NattKeepalivePacketData; -import android.net.QosFilterParcelable; -import android.net.TcpKeepalivePacketData; - -import android.net.INetworkAgentRegistry; - -/** - * Interface to notify NetworkAgent of connectivity events. - * @hide - */ -oneway interface INetworkAgent { - void onRegistered(in INetworkAgentRegistry registry); - void onDisconnected(); - void onBandwidthUpdateRequested(); - void onValidationStatusChanged(int validationStatus, - in @nullable String captivePortalUrl); - void onSaveAcceptUnvalidated(boolean acceptUnvalidated); - void onStartNattSocketKeepalive(int slot, int intervalDurationMs, - in NattKeepalivePacketData packetData); - void onStartTcpSocketKeepalive(int slot, int intervalDurationMs, - in TcpKeepalivePacketData packetData); - void onStopSocketKeepalive(int slot); - void onSignalStrengthThresholdsUpdated(in int[] thresholds); - void onPreventAutomaticReconnect(); - void onAddNattKeepalivePacketFilter(int slot, - in NattKeepalivePacketData packetData); - void onAddTcpKeepalivePacketFilter(int slot, - in TcpKeepalivePacketData packetData); - void onRemoveKeepalivePacketFilter(int slot); - void onQosFilterCallbackRegistered(int qosCallbackId, in QosFilterParcelable filterParcel); - void onQosCallbackUnregistered(int qosCallbackId); - void onNetworkCreated(); - void onNetworkDestroyed(); -} diff --git a/packages/Connectivity/framework/src/android/net/INetworkAgentRegistry.aidl b/packages/Connectivity/framework/src/android/net/INetworkAgentRegistry.aidl deleted file mode 100644 index 9a58add5d2ba1..0000000000000 --- a/packages/Connectivity/framework/src/android/net/INetworkAgentRegistry.aidl +++ /dev/null @@ -1,46 +0,0 @@ -/** - * 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. - */ -package android.net; - -import android.net.LinkProperties; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.NetworkInfo; -import android.net.NetworkScore; -import android.net.QosSession; -import android.telephony.data.EpsBearerQosSessionAttributes; -import android.telephony.data.NrQosSessionAttributes; - -/** - * Interface for NetworkAgents to send network properties. - * @hide - */ -oneway interface INetworkAgentRegistry { - void sendNetworkCapabilities(in NetworkCapabilities nc); - void sendLinkProperties(in LinkProperties lp); - // TODO: consider replacing this by "markConnected()" and removing - void sendNetworkInfo(in NetworkInfo info); - void sendScore(in NetworkScore score); - void sendExplicitlySelected(boolean explicitlySelected, boolean acceptPartial); - void sendSocketKeepaliveEvent(int slot, int reason); - void sendUnderlyingNetworks(in @nullable List networks); - void sendEpsQosSessionAvailable(int callbackId, in QosSession session, in EpsBearerQosSessionAttributes attributes); - void sendNrQosSessionAvailable(int callbackId, in QosSession session, in NrQosSessionAttributes attributes); - void sendQosSessionLost(int qosCallbackId, in QosSession session); - void sendQosCallbackError(int qosCallbackId, int exceptionType); - void sendTeardownDelayMs(int teardownDelayMs); - void sendLingerDuration(int durationMs); -} diff --git a/packages/Connectivity/framework/src/android/net/INetworkOfferCallback.aidl b/packages/Connectivity/framework/src/android/net/INetworkOfferCallback.aidl deleted file mode 100644 index ecfba21b8ab61..0000000000000 --- a/packages/Connectivity/framework/src/android/net/INetworkOfferCallback.aidl +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.net.NetworkRequest; - -/** - * A callback registered with connectivity by network providers together with - * a NetworkOffer. - * - * When the network for this offer is needed to satisfy some application or - * system component, connectivity will call onNetworkNeeded on this callback. - * When this happens, the provider should try and bring up the network. - * - * When the network for this offer is no longer needed, for example because - * the application has withdrawn the request or if the request is being - * satisfied by a network that this offer will never be able to beat, - * connectivity calls onNetworkUnneeded. When this happens, the provider - * should stop trying to bring up the network, or tear it down if it has - * already been brought up. - * - * When NetworkProvider#offerNetwork is called, the provider can expect to - * immediately receive all requests that can be fulfilled by that offer and - * are not already satisfied by a better network. It is possible no such - * request is currently outstanding, because no requests have been made that - * can be satisfied by this offer, or because all such requests are already - * satisfied by a better network. - * onNetworkNeeded can be called at any time after registration and until the - * offer is withdrawn with NetworkProvider#unofferNetwork is called. This - * typically happens when a new network request is filed by an application, - * or when the network satisfying a request disconnects and this offer now - * stands a chance to supply the best network for it. - * - * @hide - */ -oneway interface INetworkOfferCallback { - /** - * Called when a network for this offer is needed to fulfill this request. - * @param networkRequest the request to satisfy - */ - void onNetworkNeeded(in NetworkRequest networkRequest); - - /** - * Informs the registrant that the offer is no longer valuable to fulfill this request. - */ - void onNetworkUnneeded(in NetworkRequest networkRequest); -} diff --git a/packages/Connectivity/framework/src/android/net/IOnCompleteListener.aidl b/packages/Connectivity/framework/src/android/net/IOnCompleteListener.aidl deleted file mode 100644 index 4bb89f6c89e45..0000000000000 --- a/packages/Connectivity/framework/src/android/net/IOnCompleteListener.aidl +++ /dev/null @@ -1,23 +0,0 @@ -/** - * - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -/** @hide */ -oneway interface IOnCompleteListener { - void onComplete(); -} diff --git a/packages/Connectivity/framework/src/android/net/IQosCallback.aidl b/packages/Connectivity/framework/src/android/net/IQosCallback.aidl deleted file mode 100644 index c9735419f7dd3..0000000000000 --- a/packages/Connectivity/framework/src/android/net/IQosCallback.aidl +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.os.Bundle; -import android.net.QosSession; -import android.telephony.data.EpsBearerQosSessionAttributes; -import android.telephony.data.NrQosSessionAttributes; - -/** - * AIDL interface for QosCallback - * - * @hide - */ -oneway interface IQosCallback -{ - void onQosEpsBearerSessionAvailable(in QosSession session, - in EpsBearerQosSessionAttributes attributes); - void onNrQosSessionAvailable(in QosSession session, - in NrQosSessionAttributes attributes); - void onQosSessionLost(in QosSession session); - void onError(in int type); -} diff --git a/packages/Connectivity/framework/src/android/net/ISocketKeepaliveCallback.aidl b/packages/Connectivity/framework/src/android/net/ISocketKeepaliveCallback.aidl deleted file mode 100644 index 020fbcacbfef9..0000000000000 --- a/packages/Connectivity/framework/src/android/net/ISocketKeepaliveCallback.aidl +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (c) 2019, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -/** - * Callback to provide status changes of keepalive offload. - * - * @hide - */ -oneway interface ISocketKeepaliveCallback -{ - /** The keepalive was successfully started. */ - void onStarted(int slot); - /** The keepalive was successfully stopped. */ - void onStopped(); - /** The keepalive was stopped because of an error. */ - void onError(int error); - /** The keepalive on a TCP socket was stopped because the socket received data. */ - void onDataReceived(); -} diff --git a/packages/Connectivity/framework/src/android/net/ITestNetworkManager.aidl b/packages/Connectivity/framework/src/android/net/ITestNetworkManager.aidl deleted file mode 100644 index 2a863adde581d..0000000000000 --- a/packages/Connectivity/framework/src/android/net/ITestNetworkManager.aidl +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) 2018, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.net.LinkAddress; -import android.net.LinkProperties; -import android.net.TestNetworkInterface; -import android.os.IBinder; -import android.os.ParcelFileDescriptor; - -/** - * Interface that allows for creation and management of test-only networks. - * - * @hide - */ -interface ITestNetworkManager -{ - TestNetworkInterface createTunInterface(in LinkAddress[] linkAddrs); - TestNetworkInterface createTapInterface(); - - void setupTestNetwork(in String iface, in LinkProperties lp, in boolean isMetered, - in int[] administratorUids, in IBinder binder); - - void teardownTestNetwork(int netId); -} diff --git a/packages/Connectivity/framework/src/android/net/InetAddressCompat.java b/packages/Connectivity/framework/src/android/net/InetAddressCompat.java deleted file mode 100644 index 6b7e75c75359e..0000000000000 --- a/packages/Connectivity/framework/src/android/net/InetAddressCompat.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.util.Log; - -import java.lang.reflect.InvocationTargetException; -import java.net.InetAddress; -import java.net.UnknownHostException; - -/** - * Compatibility utility for InetAddress core platform APIs. - * - * Connectivity has access to such APIs, but they are not part of the module_current stubs yet - * (only core_current). Most stable core platform APIs are included manually in the connectivity - * build rules, but because InetAddress is also part of the base java SDK that is earlier on the - * classpath, the extra core platform APIs are not seen. - * - * TODO (b/183097033): remove this utility as soon as core_current is part of module_current - * @hide - */ -public class InetAddressCompat { - - /** - * @see InetAddress#clearDnsCache() - */ - public static void clearDnsCache() { - try { - InetAddress.class.getMethod("clearDnsCache").invoke(null); - } catch (InvocationTargetException e) { - if (e.getCause() instanceof RuntimeException) { - throw (RuntimeException) e.getCause(); - } - throw new IllegalStateException("Unknown InvocationTargetException", e.getCause()); - } catch (IllegalAccessException | NoSuchMethodException e) { - Log.wtf(InetAddressCompat.class.getSimpleName(), "Error clearing DNS cache", e); - } - } - - /** - * @see InetAddress#getAllByNameOnNet(String, int) - */ - public static InetAddress[] getAllByNameOnNet(String host, int netId) throws - UnknownHostException { - return (InetAddress[]) callGetByNameMethod("getAllByNameOnNet", host, netId); - } - - /** - * @see InetAddress#getByNameOnNet(String, int) - */ - public static InetAddress getByNameOnNet(String host, int netId) throws - UnknownHostException { - return (InetAddress) callGetByNameMethod("getByNameOnNet", host, netId); - } - - private static Object callGetByNameMethod(String method, String host, int netId) - throws UnknownHostException { - try { - return InetAddress.class.getMethod(method, String.class, int.class) - .invoke(null, host, netId); - } catch (InvocationTargetException e) { - if (e.getCause() instanceof UnknownHostException) { - throw (UnknownHostException) e.getCause(); - } - if (e.getCause() instanceof RuntimeException) { - throw (RuntimeException) e.getCause(); - } - throw new IllegalStateException("Unknown InvocationTargetException", e.getCause()); - } catch (IllegalAccessException | NoSuchMethodException e) { - Log.wtf(InetAddressCompat.class.getSimpleName(), "Error calling " + method, e); - throw new IllegalStateException("Error querying via " + method, e); - } - } -} diff --git a/packages/Connectivity/framework/src/android/net/InetAddresses.java b/packages/Connectivity/framework/src/android/net/InetAddresses.java deleted file mode 100644 index 01b795e456fae..0000000000000 --- a/packages/Connectivity/framework/src/android/net/InetAddresses.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.NonNull; - -import libcore.net.InetAddressUtils; - -import java.net.InetAddress; - -/** - * Utility methods for {@link InetAddress} implementations. - */ -public class InetAddresses { - - private InetAddresses() {} - - /** - * Checks to see if the {@code address} is a numeric address (such as {@code "192.0.2.1"} or - * {@code "2001:db8::1:2"}). - * - *

    A numeric address is either an IPv4 address containing exactly 4 decimal numbers or an - * IPv6 numeric address. IPv4 addresses that consist of either hexadecimal or octal digits or - * do not have exactly 4 numbers are not treated as numeric. - * - *

    This method will never do a DNS lookup. - * - * @param address the address to parse. - * @return true if the supplied address is numeric, false otherwise. - */ - public static boolean isNumericAddress(@NonNull String address) { - return InetAddressUtils.isNumericAddress(address); - } - - /** - * Returns an InetAddress corresponding to the given numeric address (such - * as {@code "192.168.0.1"} or {@code "2001:4860:800d::68"}). - * - *

    See {@link #isNumericAddress(String)} (String)} for a definition as to what constitutes a - * numeric address. - * - *

    This method will never do a DNS lookup. - * - * @param address the address to parse, must be numeric. - * @return an {@link InetAddress} instance corresponding to the address. - * @throws IllegalArgumentException if {@code address} is not a numeric address. - */ - public static @NonNull InetAddress parseNumericAddress(@NonNull String address) { - return InetAddressUtils.parseNumericAddress(address); - } -} diff --git a/packages/Connectivity/framework/src/android/net/InvalidPacketException.java b/packages/Connectivity/framework/src/android/net/InvalidPacketException.java deleted file mode 100644 index 1873d778c0f20..0000000000000 --- a/packages/Connectivity/framework/src/android/net/InvalidPacketException.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.IntDef; -import android.annotation.SystemApi; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Thrown when a packet is invalid. - * @hide - */ -@SystemApi -public final class InvalidPacketException extends Exception { - private final int mError; - - // Must match SocketKeepalive#ERROR_INVALID_IP_ADDRESS. - /** Invalid IP address. */ - public static final int ERROR_INVALID_IP_ADDRESS = -21; - - // Must match SocketKeepalive#ERROR_INVALID_PORT. - /** Invalid port number. */ - public static final int ERROR_INVALID_PORT = -22; - - // Must match SocketKeepalive#ERROR_INVALID_LENGTH. - /** Invalid packet length. */ - public static final int ERROR_INVALID_LENGTH = -23; - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = { "ERROR_" }, value = { - ERROR_INVALID_IP_ADDRESS, - ERROR_INVALID_PORT, - ERROR_INVALID_LENGTH - }) - public @interface ErrorCode {} - - /** - * This packet is invalid. - * See the error code for details. - */ - public InvalidPacketException(@ErrorCode final int error) { - this.mError = error; - } - - /** Get error code. */ - public int getError() { - return mError; - } -} diff --git a/packages/Connectivity/framework/src/android/net/IpConfiguration.java b/packages/Connectivity/framework/src/android/net/IpConfiguration.java deleted file mode 100644 index d5f8b2edb6bbd..0000000000000 --- a/packages/Connectivity/framework/src/android/net/IpConfiguration.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SuppressLint; -import android.annotation.SystemApi; -import android.compat.annotation.UnsupportedAppUsage; -import android.os.Build; -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.Objects; - -/** - * A class representing a configured network. - * @hide - */ -@SystemApi -public final class IpConfiguration implements Parcelable { - private static final String TAG = "IpConfiguration"; - - // This enum has been used by apps through reflection for many releases. - // Therefore they can't just be removed. Duplicating these constants to - // give an alternate SystemApi is a worse option than exposing them. - @SuppressLint("Enum") - public enum IpAssignment { - /* Use statically configured IP settings. Configuration can be accessed - * with staticIpConfiguration */ - STATIC, - /* Use dynamically configured IP settings */ - DHCP, - /* no IP details are assigned, this is used to indicate - * that any existing IP settings should be retained */ - UNASSIGNED - } - - /** @hide */ - public IpAssignment ipAssignment; - - /** @hide */ - public StaticIpConfiguration staticIpConfiguration; - - // This enum has been used by apps through reflection for many releases. - // Therefore they can't just be removed. Duplicating these constants to - // give an alternate SystemApi is a worse option than exposing them. - @SuppressLint("Enum") - public enum ProxySettings { - /* No proxy is to be used. Any existing proxy settings - * should be cleared. */ - NONE, - /* Use statically configured proxy. Configuration can be accessed - * with httpProxy. */ - STATIC, - /* no proxy details are assigned, this is used to indicate - * that any existing proxy settings should be retained */ - UNASSIGNED, - /* Use a Pac based proxy. - */ - PAC - } - - /** @hide */ - public ProxySettings proxySettings; - - /** @hide */ - @UnsupportedAppUsage - public ProxyInfo httpProxy; - - private void init(IpAssignment ipAssignment, - ProxySettings proxySettings, - StaticIpConfiguration staticIpConfiguration, - ProxyInfo httpProxy) { - this.ipAssignment = ipAssignment; - this.proxySettings = proxySettings; - this.staticIpConfiguration = (staticIpConfiguration == null) ? - null : new StaticIpConfiguration(staticIpConfiguration); - this.httpProxy = (httpProxy == null) ? - null : new ProxyInfo(httpProxy); - } - - public IpConfiguration() { - init(IpAssignment.UNASSIGNED, ProxySettings.UNASSIGNED, null, null); - } - - /** @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public IpConfiguration(IpAssignment ipAssignment, - ProxySettings proxySettings, - StaticIpConfiguration staticIpConfiguration, - ProxyInfo httpProxy) { - init(ipAssignment, proxySettings, staticIpConfiguration, httpProxy); - } - - public IpConfiguration(@NonNull IpConfiguration source) { - this(); - if (source != null) { - init(source.ipAssignment, source.proxySettings, - source.staticIpConfiguration, source.httpProxy); - } - } - - public @NonNull IpAssignment getIpAssignment() { - return ipAssignment; - } - - public void setIpAssignment(@NonNull IpAssignment ipAssignment) { - this.ipAssignment = ipAssignment; - } - - public @Nullable StaticIpConfiguration getStaticIpConfiguration() { - return staticIpConfiguration; - } - - public void setStaticIpConfiguration(@Nullable StaticIpConfiguration staticIpConfiguration) { - this.staticIpConfiguration = staticIpConfiguration; - } - - public @NonNull ProxySettings getProxySettings() { - return proxySettings; - } - - public void setProxySettings(@NonNull ProxySettings proxySettings) { - this.proxySettings = proxySettings; - } - - public @Nullable ProxyInfo getHttpProxy() { - return httpProxy; - } - - public void setHttpProxy(@Nullable ProxyInfo httpProxy) { - this.httpProxy = httpProxy; - } - - @Override - public String toString() { - StringBuilder sbuf = new StringBuilder(); - sbuf.append("IP assignment: " + ipAssignment.toString()); - sbuf.append("\n"); - if (staticIpConfiguration != null) { - sbuf.append("Static configuration: " + staticIpConfiguration.toString()); - sbuf.append("\n"); - } - sbuf.append("Proxy settings: " + proxySettings.toString()); - sbuf.append("\n"); - if (httpProxy != null) { - sbuf.append("HTTP proxy: " + httpProxy.toString()); - sbuf.append("\n"); - } - - return sbuf.toString(); - } - - @Override - public boolean equals(@Nullable Object o) { - if (o == this) { - return true; - } - - if (!(o instanceof IpConfiguration)) { - return false; - } - - IpConfiguration other = (IpConfiguration) o; - return this.ipAssignment == other.ipAssignment && - this.proxySettings == other.proxySettings && - Objects.equals(this.staticIpConfiguration, other.staticIpConfiguration) && - Objects.equals(this.httpProxy, other.httpProxy); - } - - @Override - public int hashCode() { - return 13 + (staticIpConfiguration != null ? staticIpConfiguration.hashCode() : 0) + - 17 * ipAssignment.ordinal() + - 47 * proxySettings.ordinal() + - 83 * httpProxy.hashCode(); - } - - /** Implement the Parcelable interface */ - public int describeContents() { - return 0; - } - - /** Implement the Parcelable interface */ - public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeString(ipAssignment.name()); - dest.writeString(proxySettings.name()); - dest.writeParcelable(staticIpConfiguration, flags); - dest.writeParcelable(httpProxy, flags); - } - - /** Implement the Parcelable interface */ - public static final @NonNull Creator CREATOR = - new Creator() { - public IpConfiguration createFromParcel(Parcel in) { - IpConfiguration config = new IpConfiguration(); - config.ipAssignment = IpAssignment.valueOf(in.readString()); - config.proxySettings = ProxySettings.valueOf(in.readString()); - config.staticIpConfiguration = in.readParcelable(null); - config.httpProxy = in.readParcelable(null); - return config; - } - - public IpConfiguration[] newArray(int size) { - return new IpConfiguration[size]; - } - }; -} diff --git a/packages/Connectivity/framework/src/android/net/IpPrefix.java b/packages/Connectivity/framework/src/android/net/IpPrefix.java deleted file mode 100644 index bf4481afc53dd..0000000000000 --- a/packages/Connectivity/framework/src/android/net/IpPrefix.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.IntRange; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SystemApi; -import android.os.Parcel; -import android.os.Parcelable; -import android.util.Pair; - -import com.android.net.module.util.NetUtils; - -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.Arrays; -import java.util.Comparator; - -/** - * This class represents an IP prefix, i.e., a contiguous block of IP addresses aligned on a - * power of two boundary (also known as an "IP subnet"). A prefix is specified by two pieces of - * information: - * - *

      - *
    • A starting IP address (IPv4 or IPv6). This is the first IP address of the prefix. - *
    • A prefix length. This specifies the length of the prefix by specifing the number of bits - * in the IP address, starting from the most significant bit in network byte order, that - * are constant for all addresses in the prefix. - *
    - * - * For example, the prefix 192.0.2.0/24 covers the 256 IPv4 addresses from - * 192.0.2.0 to 192.0.2.255, inclusive, and the prefix - * 2001:db8:1:2 covers the 2^64 IPv6 addresses from 2001:db8:1:2:: to - * 2001:db8:1:2:ffff:ffff:ffff:ffff, inclusive. - * - * Objects of this class are immutable. - */ -public final class IpPrefix implements Parcelable { - private final byte[] address; // network byte order - private final int prefixLength; - - private void checkAndMaskAddressAndPrefixLength() { - if (address.length != 4 && address.length != 16) { - throw new IllegalArgumentException( - "IpPrefix has " + address.length + " bytes which is neither 4 nor 16"); - } - NetUtils.maskRawAddress(address, prefixLength); - } - - /** - * Constructs a new {@code IpPrefix} from a byte array containing an IPv4 or IPv6 address in - * network byte order and a prefix length. Silently truncates the address to the prefix length, - * so for example {@code 192.0.2.1/24} is silently converted to {@code 192.0.2.0/24}. - * - * @param address the IP address. Must be non-null and exactly 4 or 16 bytes long. - * @param prefixLength the prefix length. Must be >= 0 and <= (32 or 128) (IPv4 or IPv6). - * - * @hide - */ - public IpPrefix(@NonNull byte[] address, @IntRange(from = 0, to = 128) int prefixLength) { - this.address = address.clone(); - this.prefixLength = prefixLength; - checkAndMaskAddressAndPrefixLength(); - } - - /** - * Constructs a new {@code IpPrefix} from an IPv4 or IPv6 address and a prefix length. Silently - * truncates the address to the prefix length, so for example {@code 192.0.2.1/24} is silently - * converted to {@code 192.0.2.0/24}. - * - * @param address the IP address. Must be non-null. - * @param prefixLength the prefix length. Must be >= 0 and <= (32 or 128) (IPv4 or IPv6). - * @hide - */ - @SystemApi - public IpPrefix(@NonNull InetAddress address, @IntRange(from = 0, to = 128) int prefixLength) { - // We don't reuse the (byte[], int) constructor because it calls clone() on the byte array, - // which is unnecessary because getAddress() already returns a clone. - this.address = address.getAddress(); - this.prefixLength = prefixLength; - checkAndMaskAddressAndPrefixLength(); - } - - /** - * Constructs a new IpPrefix from a string such as "192.0.2.1/24" or "2001:db8::1/64". - * Silently truncates the address to the prefix length, so for example {@code 192.0.2.1/24} - * is silently converted to {@code 192.0.2.0/24}. - * - * @param prefix the prefix to parse - * - * @hide - */ - @SystemApi - public IpPrefix(@NonNull String prefix) { - // We don't reuse the (InetAddress, int) constructor because "error: call to this must be - // first statement in constructor". We could factor out setting the member variables to an - // init() method, but if we did, then we'd have to make the members non-final, or "error: - // cannot assign a value to final variable address". So we just duplicate the code here. - Pair ipAndMask = NetworkUtils.legacyParseIpAndMask(prefix); - this.address = ipAndMask.first.getAddress(); - this.prefixLength = ipAndMask.second; - checkAndMaskAddressAndPrefixLength(); - } - - /** - * Compares this {@code IpPrefix} object against the specified object in {@code obj}. Two - * objects are equal if they have the same startAddress and prefixLength. - * - * @param obj the object to be tested for equality. - * @return {@code true} if both objects are equal, {@code false} otherwise. - */ - @Override - public boolean equals(@Nullable Object obj) { - if (!(obj instanceof IpPrefix)) { - return false; - } - IpPrefix that = (IpPrefix) obj; - return Arrays.equals(this.address, that.address) && this.prefixLength == that.prefixLength; - } - - /** - * Gets the hashcode of the represented IP prefix. - * - * @return the appropriate hashcode value. - */ - @Override - public int hashCode() { - return Arrays.hashCode(address) + 11 * prefixLength; - } - - /** - * Returns a copy of the first IP address in the prefix. Modifying the returned object does not - * change this object's contents. - * - * @return the address in the form of a byte array. - */ - public @NonNull InetAddress getAddress() { - try { - return InetAddress.getByAddress(address); - } catch (UnknownHostException e) { - // Cannot happen. InetAddress.getByAddress can only throw an exception if the byte - // array is the wrong length, but we check that in the constructor. - throw new IllegalArgumentException("Address is invalid"); - } - } - - /** - * Returns a copy of the IP address bytes in network order (the highest order byte is the zeroth - * element). Modifying the returned array does not change this object's contents. - * - * @return the address in the form of a byte array. - */ - public @NonNull byte[] getRawAddress() { - return address.clone(); - } - - /** - * Returns the prefix length of this {@code IpPrefix}. - * - * @return the prefix length. - */ - @IntRange(from = 0, to = 128) - public int getPrefixLength() { - return prefixLength; - } - - /** - * Determines whether the prefix contains the specified address. - * - * @param address An {@link InetAddress} to test. - * @return {@code true} if the prefix covers the given address. {@code false} otherwise. - */ - public boolean contains(@NonNull InetAddress address) { - byte[] addrBytes = address.getAddress(); - if (addrBytes == null || addrBytes.length != this.address.length) { - return false; - } - NetUtils.maskRawAddress(addrBytes, prefixLength); - return Arrays.equals(this.address, addrBytes); - } - - /** - * Returns whether the specified prefix is entirely contained in this prefix. - * - * Note this is mathematical inclusion, so a prefix is always contained within itself. - * @param otherPrefix the prefix to test - * @hide - */ - public boolean containsPrefix(@NonNull IpPrefix otherPrefix) { - if (otherPrefix.getPrefixLength() < prefixLength) return false; - final byte[] otherAddress = otherPrefix.getRawAddress(); - NetUtils.maskRawAddress(otherAddress, prefixLength); - return Arrays.equals(otherAddress, address); - } - - /** - * @hide - */ - public boolean isIPv6() { - return getAddress() instanceof Inet6Address; - } - - /** - * @hide - */ - public boolean isIPv4() { - return getAddress() instanceof Inet4Address; - } - - /** - * Returns a string representation of this {@code IpPrefix}. - * - * @return a string such as {@code "192.0.2.0/24"} or {@code "2001:db8:1:2::/64"}. - */ - public String toString() { - try { - return InetAddress.getByAddress(address).getHostAddress() + "/" + prefixLength; - } catch(UnknownHostException e) { - // Cosmic rays? - throw new IllegalStateException("IpPrefix with invalid address! Shouldn't happen.", e); - } - } - - /** - * Implement the Parcelable interface. - */ - public int describeContents() { - return 0; - } - - /** - * Implement the Parcelable interface. - */ - public void writeToParcel(Parcel dest, int flags) { - dest.writeByteArray(address); - dest.writeInt(prefixLength); - } - - /** - * Returns a comparator ordering IpPrefixes by length, shorter to longer. - * Contents of the address will break ties. - * @hide - */ - public static Comparator lengthComparator() { - return new Comparator() { - @Override - public int compare(IpPrefix prefix1, IpPrefix prefix2) { - if (prefix1.isIPv4()) { - if (prefix2.isIPv6()) return -1; - } else { - if (prefix2.isIPv4()) return 1; - } - final int p1len = prefix1.getPrefixLength(); - final int p2len = prefix2.getPrefixLength(); - if (p1len < p2len) return -1; - if (p2len < p1len) return 1; - final byte[] a1 = prefix1.address; - final byte[] a2 = prefix2.address; - final int len = a1.length < a2.length ? a1.length : a2.length; - for (int i = 0; i < len; ++i) { - if (a1[i] < a2[i]) return -1; - if (a1[i] > a2[i]) return 1; - } - if (a2.length < len) return 1; - if (a1.length < len) return -1; - return 0; - } - }; - } - - /** - * Implement the Parcelable interface. - */ - public static final @android.annotation.NonNull Creator CREATOR = - new Creator() { - public IpPrefix createFromParcel(Parcel in) { - byte[] address = in.createByteArray(); - int prefixLength = in.readInt(); - return new IpPrefix(address, prefixLength); - } - - public IpPrefix[] newArray(int size) { - return new IpPrefix[size]; - } - }; -} diff --git a/packages/Connectivity/framework/src/android/net/KeepalivePacketData.java b/packages/Connectivity/framework/src/android/net/KeepalivePacketData.java deleted file mode 100644 index 5877f1f4e2697..0000000000000 --- a/packages/Connectivity/framework/src/android/net/KeepalivePacketData.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static android.net.InvalidPacketException.ERROR_INVALID_IP_ADDRESS; -import static android.net.InvalidPacketException.ERROR_INVALID_PORT; - -import android.annotation.IntRange; -import android.annotation.NonNull; -import android.annotation.SystemApi; -import android.util.Log; - -import com.android.net.module.util.IpUtils; - -import java.net.InetAddress; - -/** - * Represents the actual packets that are sent by the - * {@link android.net.SocketKeepalive} API. - * @hide - */ -@SystemApi -public class KeepalivePacketData { - private static final String TAG = "KeepalivePacketData"; - - /** Source IP address */ - @NonNull - private final InetAddress mSrcAddress; - - /** Destination IP address */ - @NonNull - private final InetAddress mDstAddress; - - /** Source port */ - private final int mSrcPort; - - /** Destination port */ - private final int mDstPort; - - /** Packet data. A raw byte string of packet data, not including the link-layer header. */ - private final byte[] mPacket; - - // Note: If you add new fields, please modify the parcelling code in the child classes. - - - // This should only be constructed via static factory methods, such as - // nattKeepalivePacket. - /** - * A holding class for data necessary to build a keepalive packet. - */ - protected KeepalivePacketData(@NonNull InetAddress srcAddress, - @IntRange(from = 0, to = 65535) int srcPort, @NonNull InetAddress dstAddress, - @IntRange(from = 0, to = 65535) int dstPort, - @NonNull byte[] data) throws InvalidPacketException { - this.mSrcAddress = srcAddress; - this.mDstAddress = dstAddress; - this.mSrcPort = srcPort; - this.mDstPort = dstPort; - this.mPacket = data; - - // Check we have two IP addresses of the same family. - if (srcAddress == null || dstAddress == null || !srcAddress.getClass().getName() - .equals(dstAddress.getClass().getName())) { - Log.e(TAG, "Invalid or mismatched InetAddresses in KeepalivePacketData"); - throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS); - } - - // Check the ports. - if (!IpUtils.isValidUdpOrTcpPort(srcPort) || !IpUtils.isValidUdpOrTcpPort(dstPort)) { - Log.e(TAG, "Invalid ports in KeepalivePacketData"); - throw new InvalidPacketException(ERROR_INVALID_PORT); - } - } - - /** Get source IP address. */ - @NonNull - public InetAddress getSrcAddress() { - return mSrcAddress; - } - - /** Get destination IP address. */ - @NonNull - public InetAddress getDstAddress() { - return mDstAddress; - } - - /** Get source port number. */ - public int getSrcPort() { - return mSrcPort; - } - - /** Get destination port number. */ - public int getDstPort() { - return mDstPort; - } - - /** - * Returns a byte array of the given packet data. - */ - @NonNull - public byte[] getPacket() { - return mPacket.clone(); - } - -} diff --git a/packages/Connectivity/framework/src/android/net/LinkAddress.java b/packages/Connectivity/framework/src/android/net/LinkAddress.java deleted file mode 100644 index d48b8c71f495f..0000000000000 --- a/packages/Connectivity/framework/src/android/net/LinkAddress.java +++ /dev/null @@ -1,549 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static android.system.OsConstants.IFA_F_DADFAILED; -import static android.system.OsConstants.IFA_F_DEPRECATED; -import static android.system.OsConstants.IFA_F_OPTIMISTIC; -import static android.system.OsConstants.IFA_F_PERMANENT; -import static android.system.OsConstants.IFA_F_TENTATIVE; -import static android.system.OsConstants.RT_SCOPE_HOST; -import static android.system.OsConstants.RT_SCOPE_LINK; -import static android.system.OsConstants.RT_SCOPE_SITE; -import static android.system.OsConstants.RT_SCOPE_UNIVERSE; - -import android.annotation.IntRange; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SystemApi; -import android.compat.annotation.UnsupportedAppUsage; -import android.os.Build; -import android.os.Parcel; -import android.os.Parcelable; -import android.os.SystemClock; -import android.util.Pair; - -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.InterfaceAddress; -import java.net.UnknownHostException; -import java.util.Objects; - -/** - * Identifies an IP address on a network link. - * - * A {@code LinkAddress} consists of: - *
      - *
    • An IP address and prefix length (e.g., {@code 2001:db8::1/64} or {@code 192.0.2.1/24}). - * The address must be unicast, as multicast addresses cannot be assigned to interfaces. - *
    • Address flags: A bitmask of {@code OsConstants.IFA_F_*} values representing properties - * of the address (e.g., {@code android.system.OsConstants.IFA_F_OPTIMISTIC}). - *
    • Address scope: One of the {@code OsConstants.IFA_F_*} values; defines the scope in which - * the address is unique (e.g., - * {@code android.system.OsConstants.RT_SCOPE_LINK} or - * {@code android.system.OsConstants.RT_SCOPE_UNIVERSE}). - *
    - */ -public class LinkAddress implements Parcelable { - - /** - * Indicates the deprecation or expiration time is unknown - * @hide - */ - @SystemApi - public static final long LIFETIME_UNKNOWN = -1; - - /** - * Indicates this address is permanent. - * @hide - */ - @SystemApi - public static final long LIFETIME_PERMANENT = Long.MAX_VALUE; - - /** - * IPv4 or IPv6 address. - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) - private InetAddress address; - - /** - * Prefix length. - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) - private int prefixLength; - - /** - * Address flags. A bitmask of {@code IFA_F_*} values. Note that {@link #getFlags()} may not - * return these exact values. For example, it may set or clear the {@code IFA_F_DEPRECATED} - * flag depending on the current preferred lifetime. - */ - private int flags; - - /** - * Address scope. One of the RT_SCOPE_* constants. - */ - private int scope; - - /** - * The time, as reported by {@link SystemClock#elapsedRealtime}, when this LinkAddress will be - * or was deprecated. At the time existing connections can still use this address until it - * expires, but new connections should use the new address. {@link #LIFETIME_UNKNOWN} indicates - * this information is not available. {@link #LIFETIME_PERMANENT} indicates this - * {@link LinkAddress} will never be deprecated. - */ - private long deprecationTime; - - /** - * The time, as reported by {@link SystemClock#elapsedRealtime}, when this {@link LinkAddress} - * will expire and be removed from the interface. {@link #LIFETIME_UNKNOWN} indicates this - * information is not available. {@link #LIFETIME_PERMANENT} indicates this {@link LinkAddress} - * will never expire. - */ - private long expirationTime; - - /** - * Utility function to determines the scope of a unicast address. Per RFC 4291 section 2.5 and - * RFC 6724 section 3.2. - * @hide - */ - private static int scopeForUnicastAddress(InetAddress addr) { - if (addr.isAnyLocalAddress()) { - return RT_SCOPE_HOST; - } - - if (addr.isLoopbackAddress() || addr.isLinkLocalAddress()) { - return RT_SCOPE_LINK; - } - - // isSiteLocalAddress() returns true for private IPv4 addresses, but RFC 6724 section 3.2 - // says that they are assigned global scope. - if (!(addr instanceof Inet4Address) && addr.isSiteLocalAddress()) { - return RT_SCOPE_SITE; - } - - return RT_SCOPE_UNIVERSE; - } - - /** - * Utility function to check if |address| is a Unique Local IPv6 Unicast Address - * (a.k.a. "ULA"; RFC 4193). - * - * Per RFC 4193 section 8, fc00::/7 identifies these addresses. - */ - private boolean isIpv6ULA() { - if (isIpv6()) { - byte[] bytes = address.getAddress(); - return ((bytes[0] & (byte)0xfe) == (byte)0xfc); - } - return false; - } - - /** - * @return true if the address is IPv6. - * @hide - */ - @SystemApi - public boolean isIpv6() { - return address instanceof Inet6Address; - } - - /** - * For backward compatibility. - * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely - * just yet. - * @return true if the address is IPv6. - * @hide - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) - public boolean isIPv6() { - return isIpv6(); - } - - /** - * @return true if the address is IPv4 or is a mapped IPv4 address. - * @hide - */ - @SystemApi - public boolean isIpv4() { - return address instanceof Inet4Address; - } - - /** - * Utility function for the constructors. - */ - private void init(InetAddress address, int prefixLength, int flags, int scope, - long deprecationTime, long expirationTime) { - if (address == null || - address.isMulticastAddress() || - prefixLength < 0 || - (address instanceof Inet4Address && prefixLength > 32) || - (prefixLength > 128)) { - throw new IllegalArgumentException("Bad LinkAddress params " + address + - "/" + prefixLength); - } - - // deprecation time and expiration time must be both provided, or neither. - if ((deprecationTime == LIFETIME_UNKNOWN) != (expirationTime == LIFETIME_UNKNOWN)) { - throw new IllegalArgumentException( - "Must not specify only one of deprecation time and expiration time"); - } - - // deprecation time needs to be a positive value. - if (deprecationTime != LIFETIME_UNKNOWN && deprecationTime < 0) { - throw new IllegalArgumentException("invalid deprecation time " + deprecationTime); - } - - // expiration time needs to be a positive value. - if (expirationTime != LIFETIME_UNKNOWN && expirationTime < 0) { - throw new IllegalArgumentException("invalid expiration time " + expirationTime); - } - - // expiration time can't be earlier than deprecation time - if (deprecationTime != LIFETIME_UNKNOWN && expirationTime != LIFETIME_UNKNOWN - && expirationTime < deprecationTime) { - throw new IllegalArgumentException("expiration earlier than deprecation (" - + deprecationTime + ", " + expirationTime + ")"); - } - - this.address = address; - this.prefixLength = prefixLength; - this.flags = flags; - this.scope = scope; - this.deprecationTime = deprecationTime; - this.expirationTime = expirationTime; - } - - /** - * Constructs a new {@code LinkAddress} from an {@code InetAddress} and prefix length, with - * the specified flags and scope. Flags and scope are not checked for validity. - * - * @param address The IP address. - * @param prefixLength The prefix length. Must be >= 0 and <= (32 or 128) (IPv4 or IPv6). - * @param flags A bitmask of {@code IFA_F_*} values representing properties of the address. - * @param scope An integer defining the scope in which the address is unique (e.g., - * {@link OsConstants#RT_SCOPE_LINK} or {@link OsConstants#RT_SCOPE_SITE}). - * @hide - */ - @SystemApi - public LinkAddress(@NonNull InetAddress address, @IntRange(from = 0, to = 128) int prefixLength, - int flags, int scope) { - init(address, prefixLength, flags, scope, LIFETIME_UNKNOWN, LIFETIME_UNKNOWN); - } - - /** - * Constructs a new {@code LinkAddress} from an {@code InetAddress}, prefix length, with - * the specified flags, scope, deprecation time, and expiration time. Flags and scope are not - * checked for validity. The value of the {@code IFA_F_DEPRECATED} and {@code IFA_F_PERMANENT} - * flag will be adjusted based on the passed-in lifetimes. - * - * @param address The IP address. - * @param prefixLength The prefix length. Must be >= 0 and <= (32 or 128) (IPv4 or IPv6). - * @param flags A bitmask of {@code IFA_F_*} values representing properties of the address. - * @param scope An integer defining the scope in which the address is unique (e.g., - * {@link OsConstants#RT_SCOPE_LINK} or {@link OsConstants#RT_SCOPE_SITE}). - * @param deprecationTime The time, as reported by {@link SystemClock#elapsedRealtime}, when - * this {@link LinkAddress} will be or was deprecated. At the time - * existing connections can still use this address until it expires, but - * new connections should use the new address. {@link #LIFETIME_UNKNOWN} - * indicates this information is not available. - * {@link #LIFETIME_PERMANENT} indicates this {@link LinkAddress} will - * never be deprecated. - * @param expirationTime The time, as reported by {@link SystemClock#elapsedRealtime}, when this - * {@link LinkAddress} will expire and be removed from the interface. - * {@link #LIFETIME_UNKNOWN} indicates this information is not available. - * {@link #LIFETIME_PERMANENT} indicates this {@link LinkAddress} will - * never expire. - * @hide - */ - @SystemApi - public LinkAddress(@NonNull InetAddress address, @IntRange(from = 0, to = 128) int prefixLength, - int flags, int scope, long deprecationTime, long expirationTime) { - init(address, prefixLength, flags, scope, deprecationTime, expirationTime); - } - - /** - * Constructs a new {@code LinkAddress} from an {@code InetAddress} and a prefix length. - * The flags are set to zero and the scope is determined from the address. - * @param address The IP address. - * @param prefixLength The prefix length. Must be >= 0 and <= (32 or 128) (IPv4 or IPv6). - * @hide - */ - @SystemApi - public LinkAddress(@NonNull InetAddress address, - @IntRange(from = 0, to = 128) int prefixLength) { - this(address, prefixLength, 0, 0); - this.scope = scopeForUnicastAddress(address); - } - - /** - * Constructs a new {@code LinkAddress} from an {@code InterfaceAddress}. - * The flags are set to zero and the scope is determined from the address. - * @param interfaceAddress The interface address. - * @hide - */ - public LinkAddress(@NonNull InterfaceAddress interfaceAddress) { - this(interfaceAddress.getAddress(), - interfaceAddress.getNetworkPrefixLength()); - } - - /** - * Constructs a new {@code LinkAddress} from a string such as "192.0.2.5/24" or - * "2001:db8::1/64". The flags are set to zero and the scope is determined from the address. - * @param address The string to parse. - * @hide - */ - @SystemApi - public LinkAddress(@NonNull String address) { - this(address, 0, 0); - this.scope = scopeForUnicastAddress(this.address); - } - - /** - * Constructs a new {@code LinkAddress} from a string such as "192.0.2.5/24" or - * "2001:db8::1/64", with the specified flags and scope. - * @param address The string to parse. - * @param flags The address flags. - * @param scope The address scope. - * @hide - */ - @SystemApi - public LinkAddress(@NonNull String address, int flags, int scope) { - // This may throw an IllegalArgumentException; catching it is the caller's responsibility. - // TODO: consider rejecting mapped IPv4 addresses such as "::ffff:192.0.2.5/24". - Pair ipAndMask = NetworkUtils.legacyParseIpAndMask(address); - init(ipAndMask.first, ipAndMask.second, flags, scope, LIFETIME_UNKNOWN, LIFETIME_UNKNOWN); - } - - /** - * Returns a string representation of this address, such as "192.0.2.1/24" or "2001:db8::1/64". - * The string representation does not contain the flags and scope, just the address and prefix - * length. - */ - @Override - public String toString() { - return address.getHostAddress() + "/" + prefixLength; - } - - /** - * Compares this {@code LinkAddress} instance against {@code obj}. Two addresses are equal if - * their address, prefix length, flags and scope are equal. Thus, for example, two addresses - * that have the same address and prefix length are not equal if one of them is deprecated and - * the other is not. - * - * @param obj the object to be tested for equality. - * @return {@code true} if both objects are equal, {@code false} otherwise. - */ - @Override - public boolean equals(@Nullable Object obj) { - if (!(obj instanceof LinkAddress)) { - return false; - } - LinkAddress linkAddress = (LinkAddress) obj; - return this.address.equals(linkAddress.address) - && this.prefixLength == linkAddress.prefixLength - && this.flags == linkAddress.flags - && this.scope == linkAddress.scope - && this.deprecationTime == linkAddress.deprecationTime - && this.expirationTime == linkAddress.expirationTime; - } - - /** - * Returns a hashcode for this address. - */ - @Override - public int hashCode() { - return Objects.hash(address, prefixLength, flags, scope, deprecationTime, expirationTime); - } - - /** - * Determines whether this {@code LinkAddress} and the provided {@code LinkAddress} - * represent the same address. Two {@code LinkAddresses} represent the same address - * if they have the same IP address and prefix length, even if their properties are - * different. - * - * @param other the {@code LinkAddress} to compare to. - * @return {@code true} if both objects have the same address and prefix length, {@code false} - * otherwise. - * @hide - */ - @SystemApi - public boolean isSameAddressAs(@Nullable LinkAddress other) { - if (other == null) { - return false; - } - return address.equals(other.address) && prefixLength == other.prefixLength; - } - - /** - * Returns the {@link InetAddress} of this {@code LinkAddress}. - */ - public InetAddress getAddress() { - return address; - } - - /** - * Returns the prefix length of this {@code LinkAddress}. - */ - @IntRange(from = 0, to = 128) - public int getPrefixLength() { - return prefixLength; - } - - /** - * Returns the prefix length of this {@code LinkAddress}. - * TODO: Delete all callers and remove in favour of getPrefixLength(). - * @hide - */ - @UnsupportedAppUsage - @IntRange(from = 0, to = 128) - public int getNetworkPrefixLength() { - return getPrefixLength(); - } - - /** - * Returns the flags of this {@code LinkAddress}. - */ - public int getFlags() { - int flags = this.flags; - if (deprecationTime != LIFETIME_UNKNOWN) { - if (SystemClock.elapsedRealtime() >= deprecationTime) { - flags |= IFA_F_DEPRECATED; - } else { - // If deprecation time is in the future, or permanent. - flags &= ~IFA_F_DEPRECATED; - } - } - - if (expirationTime == LIFETIME_PERMANENT) { - flags |= IFA_F_PERMANENT; - } else if (expirationTime != LIFETIME_UNKNOWN) { - // If we know this address expired or will expire in the future, then this address - // should not be permanent. - flags &= ~IFA_F_PERMANENT; - } - - // Do no touch the original flags. Return the adjusted flags here. - return flags; - } - - /** - * Returns the scope of this {@code LinkAddress}. - */ - public int getScope() { - return scope; - } - - /** - * Get the deprecation time, as reported by {@link SystemClock#elapsedRealtime}, when this - * {@link LinkAddress} will be or was deprecated. At the time existing connections can still use - * this address until it expires, but new connections should use the new address. - * - * @return The deprecation time in milliseconds. {@link #LIFETIME_UNKNOWN} indicates this - * information is not available. {@link #LIFETIME_PERMANENT} indicates this {@link LinkAddress} - * will never be deprecated. - * - * @hide - */ - @SystemApi - public long getDeprecationTime() { - return deprecationTime; - } - - /** - * Get the expiration time, as reported by {@link SystemClock#elapsedRealtime}, when this - * {@link LinkAddress} will expire and be removed from the interface. - * - * @return The expiration time in milliseconds. {@link #LIFETIME_UNKNOWN} indicates this - * information is not available. {@link #LIFETIME_PERMANENT} indicates this {@link LinkAddress} - * will never expire. - * - * @hide - */ - @SystemApi - public long getExpirationTime() { - return expirationTime; - } - - /** - * Returns true if this {@code LinkAddress} is global scope and preferred (i.e., not currently - * deprecated). - * - * @hide - */ - @SystemApi - public boolean isGlobalPreferred() { - /** - * Note that addresses flagged as IFA_F_OPTIMISTIC are - * simultaneously flagged as IFA_F_TENTATIVE (when the tentative - * state has cleared either DAD has succeeded or failed, and both - * flags are cleared regardless). - */ - int flags = getFlags(); - return (scope == RT_SCOPE_UNIVERSE - && !isIpv6ULA() - && (flags & (IFA_F_DADFAILED | IFA_F_DEPRECATED)) == 0L - && ((flags & IFA_F_TENTATIVE) == 0L || (flags & IFA_F_OPTIMISTIC) != 0L)); - } - - /** - * Implement the Parcelable interface. - */ - public int describeContents() { - return 0; - } - - /** - * Implement the Parcelable interface. - */ - public void writeToParcel(Parcel dest, int flags) { - dest.writeByteArray(address.getAddress()); - dest.writeInt(prefixLength); - dest.writeInt(this.flags); - dest.writeInt(scope); - dest.writeLong(deprecationTime); - dest.writeLong(expirationTime); - } - - /** - * Implement the Parcelable interface. - */ - public static final @android.annotation.NonNull Creator CREATOR = - new Creator() { - public LinkAddress createFromParcel(Parcel in) { - InetAddress address = null; - try { - address = InetAddress.getByAddress(in.createByteArray()); - } catch (UnknownHostException e) { - // Nothing we can do here. When we call the constructor, we'll throw an - // IllegalArgumentException, because a LinkAddress can't have a null - // InetAddress. - } - int prefixLength = in.readInt(); - int flags = in.readInt(); - int scope = in.readInt(); - long deprecationTime = in.readLong(); - long expirationTime = in.readLong(); - return new LinkAddress(address, prefixLength, flags, scope, deprecationTime, - expirationTime); - } - - public LinkAddress[] newArray(int size) { - return new LinkAddress[size]; - } - }; -} diff --git a/packages/Connectivity/framework/src/android/net/LinkProperties.java b/packages/Connectivity/framework/src/android/net/LinkProperties.java deleted file mode 100644 index 99f48b49c6b59..0000000000000 --- a/packages/Connectivity/framework/src/android/net/LinkProperties.java +++ /dev/null @@ -1,1823 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SystemApi; -import android.compat.annotation.UnsupportedAppUsage; -import android.os.Build; -import android.os.Parcel; -import android.os.Parcelable; -import android.text.TextUtils; - -import com.android.net.module.util.LinkPropertiesUtils; - -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Hashtable; -import java.util.List; -import java.util.Objects; -import java.util.StringJoiner; - -/** - * Describes the properties of a network link. - * - * A link represents a connection to a network. - * It may have multiple addresses and multiple gateways, - * multiple dns servers but only one http proxy and one - * network interface. - * - * Note that this is just a holder of data. Modifying it - * does not affect live networks. - * - */ -public final class LinkProperties implements Parcelable { - // The interface described by the network link. - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) - private String mIfaceName; - private final ArrayList mLinkAddresses = new ArrayList<>(); - private final ArrayList mDnses = new ArrayList<>(); - // PCSCF addresses are addresses of SIP proxies that only exist for the IMS core service. - private final ArrayList mPcscfs = new ArrayList(); - private final ArrayList mValidatedPrivateDnses = new ArrayList<>(); - private boolean mUsePrivateDns; - private String mPrivateDnsServerName; - private String mDomains; - private ArrayList mRoutes = new ArrayList<>(); - private Inet4Address mDhcpServerAddress; - private ProxyInfo mHttpProxy; - private int mMtu; - // in the format "rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max" - private String mTcpBufferSizes; - private IpPrefix mNat64Prefix; - private boolean mWakeOnLanSupported; - private Uri mCaptivePortalApiUrl; - private CaptivePortalData mCaptivePortalData; - - /** - * Indicates whether parceling should preserve fields that are set based on permissions of - * the process receiving the {@link LinkProperties}. - */ - private final transient boolean mParcelSensitiveFields; - - private static final int MIN_MTU = 68; - - private static final int MIN_MTU_V6 = 1280; - - private static final int MAX_MTU = 10000; - - private static final int INET6_ADDR_LENGTH = 16; - - // Stores the properties of links that are "stacked" above this link. - // Indexed by interface name to allow modification and to prevent duplicates being added. - private Hashtable mStackedLinks = new Hashtable<>(); - - /** - * @hide - */ - @UnsupportedAppUsage(implicitMember = - "values()[Landroid/net/LinkProperties$ProvisioningChange;") - public enum ProvisioningChange { - @UnsupportedAppUsage - STILL_NOT_PROVISIONED, - @UnsupportedAppUsage - LOST_PROVISIONING, - @UnsupportedAppUsage - GAINED_PROVISIONING, - @UnsupportedAppUsage - STILL_PROVISIONED, - } - - /** - * Compare the provisioning states of two LinkProperties instances. - * - * @hide - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public static ProvisioningChange compareProvisioning( - LinkProperties before, LinkProperties after) { - if (before.isProvisioned() && after.isProvisioned()) { - // On dual-stack networks, DHCPv4 renewals can occasionally fail. - // When this happens, IPv6-reachable services continue to function - // normally but IPv4-only services (naturally) fail. - // - // When an application using an IPv4-only service reports a bad - // network condition to the framework, attempts to re-validate - // the network succeed (since we support IPv6-only networks) and - // nothing is changed. - // - // For users, this is confusing and unexpected behaviour, and is - // not necessarily easy to diagnose. Therefore, we treat changing - // from a dual-stack network to an IPv6-only network equivalent to - // a total loss of provisioning. - // - // For one such example of this, see b/18867306. - // - // Additionally, losing IPv6 provisioning can result in TCP - // connections getting stuck until timeouts fire and other - // baffling failures. Therefore, loss of either IPv4 or IPv6 on a - // previously dual-stack network is deemed a lost of provisioning. - if ((before.isIpv4Provisioned() && !after.isIpv4Provisioned()) - || (before.isIpv6Provisioned() && !after.isIpv6Provisioned())) { - return ProvisioningChange.LOST_PROVISIONING; - } - return ProvisioningChange.STILL_PROVISIONED; - } else if (before.isProvisioned() && !after.isProvisioned()) { - return ProvisioningChange.LOST_PROVISIONING; - } else if (!before.isProvisioned() && after.isProvisioned()) { - return ProvisioningChange.GAINED_PROVISIONING; - } else { // !before.isProvisioned() && !after.isProvisioned() - return ProvisioningChange.STILL_NOT_PROVISIONED; - } - } - - /** - * Constructs a new {@code LinkProperties} with default values. - */ - public LinkProperties() { - mParcelSensitiveFields = false; - } - - /** - * @hide - */ - @SystemApi - public LinkProperties(@Nullable LinkProperties source) { - this(source, false /* parcelSensitiveFields */); - } - - /** - * Create a copy of a {@link LinkProperties} that may preserve fields that were set - * based on the permissions of the process that originally received it. - * - *

    By default {@link LinkProperties} does not preserve such fields during parceling, as - * they should not be shared outside of the process that receives them without appropriate - * checks. - * @param parcelSensitiveFields Whether the sensitive fields should be kept when parceling - * @hide - */ - @SystemApi - public LinkProperties(@Nullable LinkProperties source, boolean parcelSensitiveFields) { - mParcelSensitiveFields = parcelSensitiveFields; - if (source == null) return; - mIfaceName = source.mIfaceName; - mLinkAddresses.addAll(source.mLinkAddresses); - mDnses.addAll(source.mDnses); - mValidatedPrivateDnses.addAll(source.mValidatedPrivateDnses); - mUsePrivateDns = source.mUsePrivateDns; - mPrivateDnsServerName = source.mPrivateDnsServerName; - mPcscfs.addAll(source.mPcscfs); - mDomains = source.mDomains; - mRoutes.addAll(source.mRoutes); - mHttpProxy = (source.mHttpProxy == null) ? null : new ProxyInfo(source.mHttpProxy); - for (LinkProperties l: source.mStackedLinks.values()) { - addStackedLink(l); - } - setMtu(source.mMtu); - setDhcpServerAddress(source.getDhcpServerAddress()); - mTcpBufferSizes = source.mTcpBufferSizes; - mNat64Prefix = source.mNat64Prefix; - mWakeOnLanSupported = source.mWakeOnLanSupported; - mCaptivePortalApiUrl = source.mCaptivePortalApiUrl; - mCaptivePortalData = source.mCaptivePortalData; - } - - /** - * Sets the interface name for this link. All {@link RouteInfo} already set for this - * will have their interface changed to match this new value. - * - * @param iface The name of the network interface used for this link. - */ - public void setInterfaceName(@Nullable String iface) { - mIfaceName = iface; - ArrayList newRoutes = new ArrayList<>(mRoutes.size()); - for (RouteInfo route : mRoutes) { - newRoutes.add(routeWithInterface(route)); - } - mRoutes = newRoutes; - } - - /** - * Gets the interface name for this link. May be {@code null} if not set. - * - * @return The interface name set for this link or {@code null}. - */ - public @Nullable String getInterfaceName() { - return mIfaceName; - } - - /** - * @hide - */ - @SystemApi - public @NonNull List getAllInterfaceNames() { - List interfaceNames = new ArrayList<>(mStackedLinks.size() + 1); - if (mIfaceName != null) interfaceNames.add(mIfaceName); - for (LinkProperties stacked: mStackedLinks.values()) { - interfaceNames.addAll(stacked.getAllInterfaceNames()); - } - return interfaceNames; - } - - /** - * Returns all the addresses on this link. We often think of a link having a single address, - * however, particularly with Ipv6 several addresses are typical. Note that the - * {@code LinkProperties} actually contains {@link LinkAddress} objects which also include - * prefix lengths for each address. This is a simplified utility alternative to - * {@link LinkProperties#getLinkAddresses}. - * - * @return An unmodifiable {@link List} of {@link InetAddress} for this link. - * @hide - */ - @SystemApi - public @NonNull List getAddresses() { - final List addresses = new ArrayList<>(); - for (LinkAddress linkAddress : mLinkAddresses) { - addresses.add(linkAddress.getAddress()); - } - return Collections.unmodifiableList(addresses); - } - - /** - * Returns all the addresses on this link and all the links stacked above it. - * @hide - */ - @UnsupportedAppUsage - public @NonNull List getAllAddresses() { - List addresses = new ArrayList<>(); - for (LinkAddress linkAddress : mLinkAddresses) { - addresses.add(linkAddress.getAddress()); - } - for (LinkProperties stacked: mStackedLinks.values()) { - addresses.addAll(stacked.getAllAddresses()); - } - return addresses; - } - - private int findLinkAddressIndex(LinkAddress address) { - for (int i = 0; i < mLinkAddresses.size(); i++) { - if (mLinkAddresses.get(i).isSameAddressAs(address)) { - return i; - } - } - return -1; - } - - /** - * Adds a {@link LinkAddress} to this {@code LinkProperties} if a {@link LinkAddress} of the - * same address/prefix does not already exist. If it does exist it is replaced. - * @param address The {@code LinkAddress} to add. - * @return true if {@code address} was added or updated, false otherwise. - * @hide - */ - @SystemApi - public boolean addLinkAddress(@NonNull LinkAddress address) { - if (address == null) { - return false; - } - int i = findLinkAddressIndex(address); - if (i < 0) { - // Address was not present. Add it. - mLinkAddresses.add(address); - return true; - } else if (mLinkAddresses.get(i).equals(address)) { - // Address was present and has same properties. Do nothing. - return false; - } else { - // Address was present and has different properties. Update it. - mLinkAddresses.set(i, address); - return true; - } - } - - /** - * Removes a {@link LinkAddress} from this {@code LinkProperties}. Specifically, matches - * and {@link LinkAddress} with the same address and prefix. - * - * @param toRemove A {@link LinkAddress} specifying the address to remove. - * @return true if the address was removed, false if it did not exist. - * @hide - */ - @SystemApi - public boolean removeLinkAddress(@NonNull LinkAddress toRemove) { - int i = findLinkAddressIndex(toRemove); - if (i >= 0) { - mLinkAddresses.remove(i); - return true; - } - return false; - } - - /** - * Returns all the {@link LinkAddress} on this link. Typically a link will have - * one IPv4 address and one or more IPv6 addresses. - * - * @return An unmodifiable {@link List} of {@link LinkAddress} for this link. - */ - public @NonNull List getLinkAddresses() { - return Collections.unmodifiableList(mLinkAddresses); - } - - /** - * Returns all the addresses on this link and all the links stacked above it. - * @hide - */ - @SystemApi - public @NonNull List getAllLinkAddresses() { - List addresses = new ArrayList<>(mLinkAddresses); - for (LinkProperties stacked: mStackedLinks.values()) { - addresses.addAll(stacked.getAllLinkAddresses()); - } - return addresses; - } - - /** - * Replaces the {@link LinkAddress} in this {@code LinkProperties} with - * the given {@link Collection} of {@link LinkAddress}. - * - * @param addresses The {@link Collection} of {@link LinkAddress} to set in this - * object. - */ - public void setLinkAddresses(@NonNull Collection addresses) { - mLinkAddresses.clear(); - for (LinkAddress address: addresses) { - addLinkAddress(address); - } - } - - /** - * Adds the given {@link InetAddress} to the list of DNS servers, if not present. - * - * @param dnsServer The {@link InetAddress} to add to the list of DNS servers. - * @return true if the DNS server was added, false if it was already present. - * @hide - */ - @SystemApi - public boolean addDnsServer(@NonNull InetAddress dnsServer) { - if (dnsServer != null && !mDnses.contains(dnsServer)) { - mDnses.add(dnsServer); - return true; - } - return false; - } - - /** - * Removes the given {@link InetAddress} from the list of DNS servers. - * - * @param dnsServer The {@link InetAddress} to remove from the list of DNS servers. - * @return true if the DNS server was removed, false if it did not exist. - * @hide - */ - @SystemApi - public boolean removeDnsServer(@NonNull InetAddress dnsServer) { - return mDnses.remove(dnsServer); - } - - /** - * Replaces the DNS servers in this {@code LinkProperties} with - * the given {@link Collection} of {@link InetAddress} objects. - * - * @param dnsServers The {@link Collection} of DNS servers to set in this object. - */ - public void setDnsServers(@NonNull Collection dnsServers) { - mDnses.clear(); - for (InetAddress dnsServer: dnsServers) { - addDnsServer(dnsServer); - } - } - - /** - * Returns all the {@link InetAddress} for DNS servers on this link. - * - * @return An unmodifiable {@link List} of {@link InetAddress} for DNS servers on - * this link. - */ - public @NonNull List getDnsServers() { - return Collections.unmodifiableList(mDnses); - } - - /** - * Set whether private DNS is currently in use on this network. - * - * @param usePrivateDns The private DNS state. - * @hide - */ - @SystemApi - public void setUsePrivateDns(boolean usePrivateDns) { - mUsePrivateDns = usePrivateDns; - } - - /** - * Returns whether private DNS is currently in use on this network. When - * private DNS is in use, applications must not send unencrypted DNS - * queries as doing so could reveal private user information. Furthermore, - * if private DNS is in use and {@link #getPrivateDnsServerName} is not - * {@code null}, DNS queries must be sent to the specified DNS server. - * - * @return {@code true} if private DNS is in use, {@code false} otherwise. - */ - public boolean isPrivateDnsActive() { - return mUsePrivateDns; - } - - /** - * Set the name of the private DNS server to which private DNS queries - * should be sent when in strict mode. This value should be {@code null} - * when private DNS is off or in opportunistic mode. - * - * @param privateDnsServerName The private DNS server name. - * @hide - */ - @SystemApi - public void setPrivateDnsServerName(@Nullable String privateDnsServerName) { - mPrivateDnsServerName = privateDnsServerName; - } - - /** - * Set DHCP server address. - * - * @param serverAddress the server address to set. - */ - public void setDhcpServerAddress(@Nullable Inet4Address serverAddress) { - mDhcpServerAddress = serverAddress; - } - - /** - * Get DHCP server address - * - * @return The current DHCP server address. - */ - public @Nullable Inet4Address getDhcpServerAddress() { - return mDhcpServerAddress; - } - - /** - * Returns the private DNS server name that is in use. If not {@code null}, - * private DNS is in strict mode. In this mode, applications should ensure - * that all DNS queries are encrypted and sent to this hostname and that - * queries are only sent if the hostname's certificate is valid. If - * {@code null} and {@link #isPrivateDnsActive} is {@code true}, private - * DNS is in opportunistic mode, and applications should ensure that DNS - * queries are encrypted and sent to a DNS server returned by - * {@link #getDnsServers}. System DNS will handle each of these cases - * correctly, but applications implementing their own DNS lookups must make - * sure to follow these requirements. - * - * @return The private DNS server name. - */ - public @Nullable String getPrivateDnsServerName() { - return mPrivateDnsServerName; - } - - /** - * Adds the given {@link InetAddress} to the list of validated private DNS servers, - * if not present. This is distinct from the server name in that these are actually - * resolved addresses. - * - * @param dnsServer The {@link InetAddress} to add to the list of validated private DNS servers. - * @return true if the DNS server was added, false if it was already present. - * @hide - */ - public boolean addValidatedPrivateDnsServer(@NonNull InetAddress dnsServer) { - if (dnsServer != null && !mValidatedPrivateDnses.contains(dnsServer)) { - mValidatedPrivateDnses.add(dnsServer); - return true; - } - return false; - } - - /** - * Removes the given {@link InetAddress} from the list of validated private DNS servers. - * - * @param dnsServer The {@link InetAddress} to remove from the list of validated private DNS - * servers. - * @return true if the DNS server was removed, false if it did not exist. - * @hide - */ - public boolean removeValidatedPrivateDnsServer(@NonNull InetAddress dnsServer) { - return mValidatedPrivateDnses.remove(dnsServer); - } - - /** - * Replaces the validated private DNS servers in this {@code LinkProperties} with - * the given {@link Collection} of {@link InetAddress} objects. - * - * @param dnsServers The {@link Collection} of validated private DNS servers to set in this - * object. - * @hide - */ - @SystemApi - public void setValidatedPrivateDnsServers(@NonNull Collection dnsServers) { - mValidatedPrivateDnses.clear(); - for (InetAddress dnsServer: dnsServers) { - addValidatedPrivateDnsServer(dnsServer); - } - } - - /** - * Returns all the {@link InetAddress} for validated private DNS servers on this link. - * These are resolved from the private DNS server name. - * - * @return An unmodifiable {@link List} of {@link InetAddress} for validated private - * DNS servers on this link. - * @hide - */ - @SystemApi - public @NonNull List getValidatedPrivateDnsServers() { - return Collections.unmodifiableList(mValidatedPrivateDnses); - } - - /** - * Adds the given {@link InetAddress} to the list of PCSCF servers, if not present. - * - * @param pcscfServer The {@link InetAddress} to add to the list of PCSCF servers. - * @return true if the PCSCF server was added, false otherwise. - * @hide - */ - @SystemApi - public boolean addPcscfServer(@NonNull InetAddress pcscfServer) { - if (pcscfServer != null && !mPcscfs.contains(pcscfServer)) { - mPcscfs.add(pcscfServer); - return true; - } - return false; - } - - /** - * Removes the given {@link InetAddress} from the list of PCSCF servers. - * - * @param pcscfServer The {@link InetAddress} to remove from the list of PCSCF servers. - * @return true if the PCSCF server was removed, false otherwise. - * @hide - */ - public boolean removePcscfServer(@NonNull InetAddress pcscfServer) { - return mPcscfs.remove(pcscfServer); - } - - /** - * Replaces the PCSCF servers in this {@code LinkProperties} with - * the given {@link Collection} of {@link InetAddress} objects. - * - * @param pcscfServers The {@link Collection} of PCSCF servers to set in this object. - * @hide - */ - @SystemApi - public void setPcscfServers(@NonNull Collection pcscfServers) { - mPcscfs.clear(); - for (InetAddress pcscfServer: pcscfServers) { - addPcscfServer(pcscfServer); - } - } - - /** - * Returns all the {@link InetAddress} for PCSCF servers on this link. - * - * @return An unmodifiable {@link List} of {@link InetAddress} for PCSCF servers on - * this link. - * @hide - */ - @SystemApi - public @NonNull List getPcscfServers() { - return Collections.unmodifiableList(mPcscfs); - } - - /** - * Sets the DNS domain search path used on this link. - * - * @param domains A {@link String} listing in priority order the comma separated - * domains to search when resolving host names on this link. - */ - public void setDomains(@Nullable String domains) { - mDomains = domains; - } - - /** - * Get the DNS domains search path set for this link. May be {@code null} if not set. - * - * @return A {@link String} containing the comma separated domains to search when resolving host - * names on this link or {@code null}. - */ - public @Nullable String getDomains() { - return mDomains; - } - - /** - * Sets the Maximum Transmission Unit size to use on this link. This should not be used - * unless the system default (1500) is incorrect. Values less than 68 or greater than - * 10000 will be ignored. - * - * @param mtu The MTU to use for this link. - */ - public void setMtu(int mtu) { - mMtu = mtu; - } - - /** - * Gets any non-default MTU size set for this link. Note that if the default is being used - * this will return 0. - * - * @return The mtu value set for this link. - */ - public int getMtu() { - return mMtu; - } - - /** - * Sets the tcp buffers sizes to be used when this link is the system default. - * Should be of the form "rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max". - * - * @param tcpBufferSizes The tcp buffers sizes to use. - * - * @hide - */ - @SystemApi - public void setTcpBufferSizes(@Nullable String tcpBufferSizes) { - mTcpBufferSizes = tcpBufferSizes; - } - - /** - * Gets the tcp buffer sizes. May be {@code null} if not set. - * - * @return the tcp buffer sizes to use when this link is the system default or {@code null}. - * - * @hide - */ - @SystemApi - public @Nullable String getTcpBufferSizes() { - return mTcpBufferSizes; - } - - private RouteInfo routeWithInterface(RouteInfo route) { - return new RouteInfo( - route.getDestination(), - route.getGateway(), - mIfaceName, - route.getType(), - route.getMtu()); - } - - private int findRouteIndexByRouteKey(RouteInfo route) { - for (int i = 0; i < mRoutes.size(); i++) { - if (mRoutes.get(i).getRouteKey().equals(route.getRouteKey())) { - return i; - } - } - return -1; - } - - /** - * Adds a {@link RouteInfo} to this {@code LinkProperties}. If there is a {@link RouteInfo} - * with the same destination, gateway and interface with different properties - * (e.g., different MTU), it will be updated. If the {@link RouteInfo} had an - * interface name set and that differs from the interface set for this - * {@code LinkProperties} an {@link IllegalArgumentException} will be thrown. - * The proper course is to add either un-named or properly named {@link RouteInfo}. - * - * @param route A {@link RouteInfo} to add to this object. - * @return {@code true} was added or updated, false otherwise. - */ - public boolean addRoute(@NonNull RouteInfo route) { - String routeIface = route.getInterface(); - if (routeIface != null && !routeIface.equals(mIfaceName)) { - throw new IllegalArgumentException( - "Route added with non-matching interface: " + routeIface - + " vs. " + mIfaceName); - } - route = routeWithInterface(route); - - int i = findRouteIndexByRouteKey(route); - if (i == -1) { - // Route was not present. Add it. - mRoutes.add(route); - return true; - } else if (mRoutes.get(i).equals(route)) { - // Route was present and has same properties. Do nothing. - return false; - } else { - // Route was present and has different properties. Update it. - mRoutes.set(i, route); - return true; - } - } - - /** - * Removes a {@link RouteInfo} from this {@code LinkProperties}, if present. The route must - * specify an interface and the interface must match the interface of this - * {@code LinkProperties}, or it will not be removed. - * - * @param route A {@link RouteInfo} specifying the route to remove. - * @return {@code true} if the route was removed, {@code false} if it was not present. - * - * @hide - */ - @SystemApi - public boolean removeRoute(@NonNull RouteInfo route) { - return Objects.equals(mIfaceName, route.getInterface()) && mRoutes.remove(route); - } - - /** - * Returns all the {@link RouteInfo} set on this link. - * - * @return An unmodifiable {@link List} of {@link RouteInfo} for this link. - */ - public @NonNull List getRoutes() { - return Collections.unmodifiableList(mRoutes); - } - - /** - * Make sure this LinkProperties instance contains routes that cover the local subnet - * of its link addresses. Add any route that is missing. - * @hide - */ - public void ensureDirectlyConnectedRoutes() { - for (LinkAddress addr : mLinkAddresses) { - addRoute(new RouteInfo(addr, null, mIfaceName)); - } - } - - /** - * Returns all the routes on this link and all the links stacked above it. - * @hide - */ - @SystemApi - public @NonNull List getAllRoutes() { - List routes = new ArrayList<>(mRoutes); - for (LinkProperties stacked: mStackedLinks.values()) { - routes.addAll(stacked.getAllRoutes()); - } - return routes; - } - - /** - * Sets the recommended {@link ProxyInfo} to use on this link, or {@code null} for none. - * Note that Http Proxies are only a hint - the system recommends their use, but it does - * not enforce it and applications may ignore them. - * - * @param proxy A {@link ProxyInfo} defining the HTTP Proxy to use on this link. - */ - public void setHttpProxy(@Nullable ProxyInfo proxy) { - mHttpProxy = proxy; - } - - /** - * Gets the recommended {@link ProxyInfo} (or {@code null}) set on this link. - * - * @return The {@link ProxyInfo} set on this link or {@code null}. - */ - public @Nullable ProxyInfo getHttpProxy() { - return mHttpProxy; - } - - /** - * Returns the NAT64 prefix in use on this link, if any. - * - * @return the NAT64 prefix or {@code null}. - */ - public @Nullable IpPrefix getNat64Prefix() { - return mNat64Prefix; - } - - /** - * Sets the NAT64 prefix in use on this link. - * - * Currently, only 96-bit prefixes (i.e., where the 32-bit IPv4 address is at the end of the - * 128-bit IPv6 address) are supported or {@code null} for no prefix. - * - * @param prefix the NAT64 prefix. - */ - public void setNat64Prefix(@Nullable IpPrefix prefix) { - if (prefix != null && prefix.getPrefixLength() != 96) { - throw new IllegalArgumentException("Only 96-bit prefixes are supported: " + prefix); - } - mNat64Prefix = prefix; // IpPrefix objects are immutable. - } - - /** - * Adds a stacked link. - * - * If there is already a stacked link with the same interface name as link, - * that link is replaced with link. Otherwise, link is added to the list - * of stacked links. - * - * @param link The link to add. - * @return true if the link was stacked, false otherwise. - * @hide - */ - @UnsupportedAppUsage - public boolean addStackedLink(@NonNull LinkProperties link) { - if (link.getInterfaceName() != null) { - mStackedLinks.put(link.getInterfaceName(), link); - return true; - } - return false; - } - - /** - * Removes a stacked link. - * - * If there is a stacked link with the given interface name, it is - * removed. Otherwise, nothing changes. - * - * @param iface The interface name of the link to remove. - * @return true if the link was removed, false otherwise. - * @hide - */ - public boolean removeStackedLink(@NonNull String iface) { - LinkProperties removed = mStackedLinks.remove(iface); - return removed != null; - } - - /** - * Returns all the links stacked on top of this link. - * @hide - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public @NonNull List getStackedLinks() { - if (mStackedLinks.isEmpty()) { - return Collections.emptyList(); - } - final List stacked = new ArrayList<>(); - for (LinkProperties link : mStackedLinks.values()) { - stacked.add(new LinkProperties(link)); - } - return Collections.unmodifiableList(stacked); - } - - /** - * Clears this object to its initial state. - */ - public void clear() { - if (mParcelSensitiveFields) { - throw new UnsupportedOperationException( - "Cannot clear LinkProperties when parcelSensitiveFields is set"); - } - - mIfaceName = null; - mLinkAddresses.clear(); - mDnses.clear(); - mUsePrivateDns = false; - mPrivateDnsServerName = null; - mPcscfs.clear(); - mDomains = null; - mRoutes.clear(); - mHttpProxy = null; - mStackedLinks.clear(); - mMtu = 0; - mDhcpServerAddress = null; - mTcpBufferSizes = null; - mNat64Prefix = null; - mWakeOnLanSupported = false; - mCaptivePortalApiUrl = null; - mCaptivePortalData = null; - } - - /** - * Implement the Parcelable interface - */ - public int describeContents() { - return 0; - } - - @Override - public String toString() { - // Space as a separator, so no need for spaces at start/end of the individual fragments. - final StringJoiner resultJoiner = new StringJoiner(" ", "{", "}"); - - if (mIfaceName != null) { - resultJoiner.add("InterfaceName:"); - resultJoiner.add(mIfaceName); - } - - resultJoiner.add("LinkAddresses: ["); - if (!mLinkAddresses.isEmpty()) { - resultJoiner.add(TextUtils.join(",", mLinkAddresses)); - } - resultJoiner.add("]"); - - resultJoiner.add("DnsAddresses: ["); - if (!mDnses.isEmpty()) { - resultJoiner.add(TextUtils.join(",", mDnses)); - } - resultJoiner.add("]"); - - if (mUsePrivateDns) { - resultJoiner.add("UsePrivateDns: true"); - } - - if (mPrivateDnsServerName != null) { - resultJoiner.add("PrivateDnsServerName:"); - resultJoiner.add(mPrivateDnsServerName); - } - - if (!mPcscfs.isEmpty()) { - resultJoiner.add("PcscfAddresses: ["); - resultJoiner.add(TextUtils.join(",", mPcscfs)); - resultJoiner.add("]"); - } - - if (!mValidatedPrivateDnses.isEmpty()) { - final StringJoiner validatedPrivateDnsesJoiner = - new StringJoiner(",", "ValidatedPrivateDnsAddresses: [", "]"); - for (final InetAddress addr : mValidatedPrivateDnses) { - validatedPrivateDnsesJoiner.add(addr.getHostAddress()); - } - resultJoiner.add(validatedPrivateDnsesJoiner.toString()); - } - - resultJoiner.add("Domains:"); - resultJoiner.add(mDomains); - - resultJoiner.add("MTU:"); - resultJoiner.add(Integer.toString(mMtu)); - - if (mWakeOnLanSupported) { - resultJoiner.add("WakeOnLanSupported: true"); - } - - if (mDhcpServerAddress != null) { - resultJoiner.add("ServerAddress:"); - resultJoiner.add(mDhcpServerAddress.toString()); - } - - if (mCaptivePortalApiUrl != null) { - resultJoiner.add("CaptivePortalApiUrl: " + mCaptivePortalApiUrl); - } - - if (mCaptivePortalData != null) { - resultJoiner.add("CaptivePortalData: " + mCaptivePortalData); - } - - if (mTcpBufferSizes != null) { - resultJoiner.add("TcpBufferSizes:"); - resultJoiner.add(mTcpBufferSizes); - } - - resultJoiner.add("Routes: ["); - if (!mRoutes.isEmpty()) { - resultJoiner.add(TextUtils.join(",", mRoutes)); - } - resultJoiner.add("]"); - - if (mHttpProxy != null) { - resultJoiner.add("HttpProxy:"); - resultJoiner.add(mHttpProxy.toString()); - } - - if (mNat64Prefix != null) { - resultJoiner.add("Nat64Prefix:"); - resultJoiner.add(mNat64Prefix.toString()); - } - - final Collection stackedLinksValues = mStackedLinks.values(); - if (!stackedLinksValues.isEmpty()) { - final StringJoiner stackedLinksJoiner = new StringJoiner(",", "Stacked: [", "]"); - for (final LinkProperties lp : stackedLinksValues) { - stackedLinksJoiner.add("[ " + lp + " ]"); - } - resultJoiner.add(stackedLinksJoiner.toString()); - } - - return resultJoiner.toString(); - } - - /** - * Returns true if this link has an IPv4 address. - * - * @return {@code true} if there is an IPv4 address, {@code false} otherwise. - * @hide - */ - @SystemApi - public boolean hasIpv4Address() { - for (LinkAddress address : mLinkAddresses) { - if (address.getAddress() instanceof Inet4Address) { - return true; - } - } - return false; - } - - /** - * For backward compatibility. - * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely - * just yet. - * @return {@code true} if there is an IPv4 address, {@code false} otherwise. - * @hide - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) - public boolean hasIPv4Address() { - return hasIpv4Address(); - } - - /** - * Returns true if this link or any of its stacked interfaces has an IPv4 address. - * - * @return {@code true} if there is an IPv4 address, {@code false} otherwise. - */ - private boolean hasIpv4AddressOnInterface(String iface) { - // mIfaceName can be null. - return (Objects.equals(iface, mIfaceName) && hasIpv4Address()) - || (iface != null && mStackedLinks.containsKey(iface) - && mStackedLinks.get(iface).hasIpv4Address()); - } - - /** - * Returns true if this link has a global preferred IPv6 address. - * - * @return {@code true} if there is a global preferred IPv6 address, {@code false} otherwise. - * @hide - */ - @SystemApi - public boolean hasGlobalIpv6Address() { - for (LinkAddress address : mLinkAddresses) { - if (address.getAddress() instanceof Inet6Address && address.isGlobalPreferred()) { - return true; - } - } - return false; - } - - /** - * Returns true if this link has an IPv4 unreachable default route. - * - * @return {@code true} if there is an IPv4 unreachable default route, {@code false} otherwise. - * @hide - */ - public boolean hasIpv4UnreachableDefaultRoute() { - for (RouteInfo r : mRoutes) { - if (r.isIPv4UnreachableDefault()) { - return true; - } - } - return false; - } - - /** - * For backward compatibility. - * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely - * just yet. - * @return {@code true} if there is a global preferred IPv6 address, {@code false} otherwise. - * @hide - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) - public boolean hasGlobalIPv6Address() { - return hasGlobalIpv6Address(); - } - - /** - * Returns true if this link has an IPv4 default route. - * - * @return {@code true} if there is an IPv4 default route, {@code false} otherwise. - * @hide - */ - @SystemApi - public boolean hasIpv4DefaultRoute() { - for (RouteInfo r : mRoutes) { - if (r.isIPv4Default()) { - return true; - } - } - return false; - } - - /** - * Returns true if this link has an IPv6 unreachable default route. - * - * @return {@code true} if there is an IPv6 unreachable default route, {@code false} otherwise. - * @hide - */ - public boolean hasIpv6UnreachableDefaultRoute() { - for (RouteInfo r : mRoutes) { - if (r.isIPv6UnreachableDefault()) { - return true; - } - } - return false; - } - - /** - * For backward compatibility. - * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely - * just yet. - * @return {@code true} if there is an IPv4 default route, {@code false} otherwise. - * @hide - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) - public boolean hasIPv4DefaultRoute() { - return hasIpv4DefaultRoute(); - } - - /** - * Returns true if this link has an IPv6 default route. - * - * @return {@code true} if there is an IPv6 default route, {@code false} otherwise. - * @hide - */ - @SystemApi - public boolean hasIpv6DefaultRoute() { - for (RouteInfo r : mRoutes) { - if (r.isIPv6Default()) { - return true; - } - } - return false; - } - - /** - * For backward compatibility. - * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely - * just yet. - * @return {@code true} if there is an IPv6 default route, {@code false} otherwise. - * @hide - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) - public boolean hasIPv6DefaultRoute() { - return hasIpv6DefaultRoute(); - } - - /** - * Returns true if this link has an IPv4 DNS server. - * - * @return {@code true} if there is an IPv4 DNS server, {@code false} otherwise. - * @hide - */ - @SystemApi - public boolean hasIpv4DnsServer() { - for (InetAddress ia : mDnses) { - if (ia instanceof Inet4Address) { - return true; - } - } - return false; - } - - /** - * For backward compatibility. - * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely - * just yet. - * @return {@code true} if there is an IPv4 DNS server, {@code false} otherwise. - * @hide - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) - public boolean hasIPv4DnsServer() { - return hasIpv4DnsServer(); - } - - /** - * Returns true if this link has an IPv6 DNS server. - * - * @return {@code true} if there is an IPv6 DNS server, {@code false} otherwise. - * @hide - */ - @SystemApi - public boolean hasIpv6DnsServer() { - for (InetAddress ia : mDnses) { - if (ia instanceof Inet6Address) { - return true; - } - } - return false; - } - - /** - * For backward compatibility. - * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely - * just yet. - * @return {@code true} if there is an IPv6 DNS server, {@code false} otherwise. - * @hide - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) - public boolean hasIPv6DnsServer() { - return hasIpv6DnsServer(); - } - - /** - * Returns true if this link has an IPv4 PCSCF server. - * - * @return {@code true} if there is an IPv4 PCSCF server, {@code false} otherwise. - * @hide - */ - public boolean hasIpv4PcscfServer() { - for (InetAddress ia : mPcscfs) { - if (ia instanceof Inet4Address) { - return true; - } - } - return false; - } - - /** - * Returns true if this link has an IPv6 PCSCF server. - * - * @return {@code true} if there is an IPv6 PCSCF server, {@code false} otherwise. - * @hide - */ - public boolean hasIpv6PcscfServer() { - for (InetAddress ia : mPcscfs) { - if (ia instanceof Inet6Address) { - return true; - } - } - return false; - } - - /** - * Returns true if this link is provisioned for global IPv4 connectivity. - * This requires an IP address, default route, and DNS server. - * - * @return {@code true} if the link is provisioned, {@code false} otherwise. - * @hide - */ - @SystemApi - public boolean isIpv4Provisioned() { - return (hasIpv4Address() - && hasIpv4DefaultRoute() - && hasIpv4DnsServer()); - } - - /** - * Returns true if this link is provisioned for global IPv6 connectivity. - * This requires an IP address, default route, and DNS server. - * - * @return {@code true} if the link is provisioned, {@code false} otherwise. - * @hide - */ - @SystemApi - public boolean isIpv6Provisioned() { - return (hasGlobalIpv6Address() - && hasIpv6DefaultRoute() - && hasIpv6DnsServer()); - } - - /** - * For backward compatibility. - * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely - * just yet. - * @return {@code true} if the link is provisioned, {@code false} otherwise. - * @hide - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) - public boolean isIPv6Provisioned() { - return isIpv6Provisioned(); - } - - - /** - * Returns true if this link is provisioned for global connectivity, - * for at least one Internet Protocol family. - * - * @return {@code true} if the link is provisioned, {@code false} otherwise. - * @hide - */ - @SystemApi - public boolean isProvisioned() { - return (isIpv4Provisioned() || isIpv6Provisioned()); - } - - /** - * Evaluate whether the {@link InetAddress} is considered reachable. - * - * @return {@code true} if the given {@link InetAddress} is considered reachable, - * {@code false} otherwise. - * @hide - */ - @SystemApi - public boolean isReachable(@NonNull InetAddress ip) { - final List allRoutes = getAllRoutes(); - // If we don't have a route to this IP address, it's not reachable. - final RouteInfo bestRoute = RouteInfo.selectBestRoute(allRoutes, ip); - if (bestRoute == null) { - return false; - } - - // TODO: better source address evaluation for destination addresses. - - if (ip instanceof Inet4Address) { - // For IPv4, it suffices for now to simply have any address. - return hasIpv4AddressOnInterface(bestRoute.getInterface()); - } else if (ip instanceof Inet6Address) { - if (ip.isLinkLocalAddress()) { - // For now, just make sure link-local destinations have - // scopedIds set, since transmits will generally fail otherwise. - // TODO: verify it matches the ifindex of one of the interfaces. - return (((Inet6Address)ip).getScopeId() != 0); - } else { - // For non-link-local destinations check that either the best route - // is directly connected or that some global preferred address exists. - // TODO: reconsider all cases (disconnected ULA networks, ...). - return (!bestRoute.hasGateway() || hasGlobalIpv6Address()); - } - } - - return false; - } - - /** - * Compares this {@code LinkProperties} interface name against the target - * - * @param target LinkProperties to compare. - * @return {@code true} if both are identical, {@code false} otherwise. - * @hide - */ - @UnsupportedAppUsage - public boolean isIdenticalInterfaceName(@NonNull LinkProperties target) { - return LinkPropertiesUtils.isIdenticalInterfaceName(target, this); - } - - /** - * Compares this {@code LinkProperties} DHCP server address against the target - * - * @param target LinkProperties to compare. - * @return {@code true} if both are identical, {@code false} otherwise. - * @hide - */ - public boolean isIdenticalDhcpServerAddress(@NonNull LinkProperties target) { - return Objects.equals(mDhcpServerAddress, target.mDhcpServerAddress); - } - - /** - * Compares this {@code LinkProperties} interface addresses against the target - * - * @param target LinkProperties to compare. - * @return {@code true} if both are identical, {@code false} otherwise. - * @hide - */ - @UnsupportedAppUsage - public boolean isIdenticalAddresses(@NonNull LinkProperties target) { - return LinkPropertiesUtils.isIdenticalAddresses(target, this); - } - - /** - * Compares this {@code LinkProperties} DNS addresses against the target - * - * @param target LinkProperties to compare. - * @return {@code true} if both are identical, {@code false} otherwise. - * @hide - */ - @UnsupportedAppUsage - public boolean isIdenticalDnses(@NonNull LinkProperties target) { - return LinkPropertiesUtils.isIdenticalDnses(target, this); - } - - /** - * Compares this {@code LinkProperties} private DNS settings against the - * target. - * - * @param target LinkProperties to compare. - * @return {@code true} if both are identical, {@code false} otherwise. - * @hide - */ - public boolean isIdenticalPrivateDns(@NonNull LinkProperties target) { - return (isPrivateDnsActive() == target.isPrivateDnsActive() - && TextUtils.equals(getPrivateDnsServerName(), - target.getPrivateDnsServerName())); - } - - /** - * Compares this {@code LinkProperties} validated private DNS addresses against - * the target - * - * @param target LinkProperties to compare. - * @return {@code true} if both are identical, {@code false} otherwise. - * @hide - */ - public boolean isIdenticalValidatedPrivateDnses(@NonNull LinkProperties target) { - Collection targetDnses = target.getValidatedPrivateDnsServers(); - return (mValidatedPrivateDnses.size() == targetDnses.size()) - ? mValidatedPrivateDnses.containsAll(targetDnses) : false; - } - - /** - * Compares this {@code LinkProperties} PCSCF addresses against the target - * - * @param target LinkProperties to compare. - * @return {@code true} if both are identical, {@code false} otherwise. - * @hide - */ - public boolean isIdenticalPcscfs(@NonNull LinkProperties target) { - Collection targetPcscfs = target.getPcscfServers(); - return (mPcscfs.size() == targetPcscfs.size()) ? - mPcscfs.containsAll(targetPcscfs) : false; - } - - /** - * Compares this {@code LinkProperties} Routes against the target - * - * @param target LinkProperties to compare. - * @return {@code true} if both are identical, {@code false} otherwise. - * @hide - */ - @UnsupportedAppUsage - public boolean isIdenticalRoutes(@NonNull LinkProperties target) { - return LinkPropertiesUtils.isIdenticalRoutes(target, this); - } - - /** - * Compares this {@code LinkProperties} HttpProxy against the target - * - * @param target LinkProperties to compare. - * @return {@code true} if both are identical, {@code false} otherwise. - * @hide - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) - public boolean isIdenticalHttpProxy(@NonNull LinkProperties target) { - return LinkPropertiesUtils.isIdenticalHttpProxy(target, this); - } - - /** - * Compares this {@code LinkProperties} stacked links against the target - * - * @param target LinkProperties to compare. - * @return {@code true} if both are identical, {@code false} otherwise. - * @hide - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public boolean isIdenticalStackedLinks(@NonNull LinkProperties target) { - if (!mStackedLinks.keySet().equals(target.mStackedLinks.keySet())) { - return false; - } - for (LinkProperties stacked : mStackedLinks.values()) { - // Hashtable values can never be null. - String iface = stacked.getInterfaceName(); - if (!stacked.equals(target.mStackedLinks.get(iface))) { - return false; - } - } - return true; - } - - /** - * Compares this {@code LinkProperties} MTU against the target - * - * @param target LinkProperties to compare. - * @return {@code true} if both are identical, {@code false} otherwise. - * @hide - */ - public boolean isIdenticalMtu(@NonNull LinkProperties target) { - return getMtu() == target.getMtu(); - } - - /** - * Compares this {@code LinkProperties} Tcp buffer sizes against the target. - * - * @param target LinkProperties to compare. - * @return {@code true} if both are identical, {@code false} otherwise. - * @hide - */ - public boolean isIdenticalTcpBufferSizes(@NonNull LinkProperties target) { - return Objects.equals(mTcpBufferSizes, target.mTcpBufferSizes); - } - - /** - * Compares this {@code LinkProperties} NAT64 prefix against the target. - * - * @param target LinkProperties to compare. - * @return {@code true} if both are identical, {@code false} otherwise. - * @hide - */ - public boolean isIdenticalNat64Prefix(@NonNull LinkProperties target) { - return Objects.equals(mNat64Prefix, target.mNat64Prefix); - } - - /** - * Compares this {@code LinkProperties} WakeOnLan supported against the target. - * - * @param target LinkProperties to compare. - * @return {@code true} if both are identical, {@code false} otherwise. - * @hide - */ - public boolean isIdenticalWakeOnLan(LinkProperties target) { - return isWakeOnLanSupported() == target.isWakeOnLanSupported(); - } - - /** - * Compares this {@code LinkProperties}'s CaptivePortalApiUrl against the target. - * - * @param target LinkProperties to compare. - * @return {@code true} if both are identical, {@code false} otherwise. - * @hide - */ - public boolean isIdenticalCaptivePortalApiUrl(LinkProperties target) { - return Objects.equals(mCaptivePortalApiUrl, target.mCaptivePortalApiUrl); - } - - /** - * Compares this {@code LinkProperties}'s CaptivePortalData against the target. - * - * @param target LinkProperties to compare. - * @return {@code true} if both are identical, {@code false} otherwise. - * @hide - */ - public boolean isIdenticalCaptivePortalData(LinkProperties target) { - return Objects.equals(mCaptivePortalData, target.mCaptivePortalData); - } - - /** - * Set whether the network interface supports WakeOnLAN - * - * @param supported WakeOnLAN supported value - * - * @hide - */ - public void setWakeOnLanSupported(boolean supported) { - mWakeOnLanSupported = supported; - } - - /** - * Returns whether the network interface supports WakeOnLAN - * - * @return {@code true} if interface supports WakeOnLAN, {@code false} otherwise. - */ - public boolean isWakeOnLanSupported() { - return mWakeOnLanSupported; - } - - /** - * Set the URL of the captive portal API endpoint to get more information about the network. - * @hide - */ - @SystemApi - public void setCaptivePortalApiUrl(@Nullable Uri url) { - mCaptivePortalApiUrl = url; - } - - /** - * Get the URL of the captive portal API endpoint to get more information about the network. - * - *

    This is null unless the application has - * {@link android.Manifest.permission.NETWORK_SETTINGS} or - * {@link NetworkStack#PERMISSION_MAINLINE_NETWORK_STACK} permissions, and the network provided - * the URL. - * @hide - */ - @SystemApi - @Nullable - public Uri getCaptivePortalApiUrl() { - return mCaptivePortalApiUrl; - } - - /** - * Set the CaptivePortalData obtained from the captive portal API (RFC7710bis). - * @hide - */ - @SystemApi - public void setCaptivePortalData(@Nullable CaptivePortalData data) { - mCaptivePortalData = data; - } - - /** - * Get the CaptivePortalData obtained from the captive portal API (RFC7710bis). - * - *

    This is null unless the application has - * {@link android.Manifest.permission.NETWORK_SETTINGS} or - * {@link NetworkStack#PERMISSION_MAINLINE_NETWORK_STACK} permissions. - * @hide - */ - @SystemApi - @Nullable - public CaptivePortalData getCaptivePortalData() { - return mCaptivePortalData; - } - - /** - * Compares this {@code LinkProperties} instance against the target - * LinkProperties in {@code obj}. Two LinkPropertieses are equal if - * all their fields are equal in values. - * - * For collection fields, such as mDnses, containsAll() is used to check - * if two collections contains the same elements, independent of order. - * There are two thoughts regarding containsAll() - * 1. Duplicated elements. eg, (A, B, B) and (A, A, B) are equal. - * 2. Worst case performance is O(n^2). - * - * @param obj the object to be tested for equality. - * @return {@code true} if both objects are equal, {@code false} otherwise. - */ - @Override - public boolean equals(@Nullable Object obj) { - if (this == obj) return true; - - if (!(obj instanceof LinkProperties)) return false; - - LinkProperties target = (LinkProperties) obj; - /* - * This method does not check that stacked interfaces are equal, because - * stacked interfaces are not so much a property of the link as a - * description of connections between links. - */ - return isIdenticalInterfaceName(target) - && isIdenticalAddresses(target) - && isIdenticalDhcpServerAddress(target) - && isIdenticalDnses(target) - && isIdenticalPrivateDns(target) - && isIdenticalValidatedPrivateDnses(target) - && isIdenticalPcscfs(target) - && isIdenticalRoutes(target) - && isIdenticalHttpProxy(target) - && isIdenticalStackedLinks(target) - && isIdenticalMtu(target) - && isIdenticalTcpBufferSizes(target) - && isIdenticalNat64Prefix(target) - && isIdenticalWakeOnLan(target) - && isIdenticalCaptivePortalApiUrl(target) - && isIdenticalCaptivePortalData(target); - } - - /** - * Generate hashcode based on significant fields - * - * Equal objects must produce the same hash code, while unequal objects - * may have the same hash codes. - */ - @Override - public int hashCode() { - return ((null == mIfaceName) ? 0 : mIfaceName.hashCode() - + mLinkAddresses.size() * 31 - + mDnses.size() * 37 - + mValidatedPrivateDnses.size() * 61 - + ((null == mDomains) ? 0 : mDomains.hashCode()) - + mRoutes.size() * 41 - + ((null == mHttpProxy) ? 0 : mHttpProxy.hashCode()) - + mStackedLinks.hashCode() * 47) - + mMtu * 51 - + ((null == mTcpBufferSizes) ? 0 : mTcpBufferSizes.hashCode()) - + (mUsePrivateDns ? 57 : 0) - + ((null == mDhcpServerAddress) ? 0 : mDhcpServerAddress.hashCode()) - + mPcscfs.size() * 67 - + ((null == mPrivateDnsServerName) ? 0 : mPrivateDnsServerName.hashCode()) - + Objects.hash(mNat64Prefix) - + (mWakeOnLanSupported ? 71 : 0) - + Objects.hash(mCaptivePortalApiUrl, mCaptivePortalData); - } - - /** - * Implement the Parcelable interface. - */ - public void writeToParcel(Parcel dest, int flags) { - dest.writeString(getInterfaceName()); - dest.writeInt(mLinkAddresses.size()); - for (LinkAddress linkAddress : mLinkAddresses) { - dest.writeParcelable(linkAddress, flags); - } - - writeAddresses(dest, mDnses); - writeAddresses(dest, mValidatedPrivateDnses); - dest.writeBoolean(mUsePrivateDns); - dest.writeString(mPrivateDnsServerName); - writeAddresses(dest, mPcscfs); - dest.writeString(mDomains); - writeAddress(dest, mDhcpServerAddress); - dest.writeInt(mMtu); - dest.writeString(mTcpBufferSizes); - dest.writeInt(mRoutes.size()); - for (RouteInfo route : mRoutes) { - dest.writeParcelable(route, flags); - } - - if (mHttpProxy != null) { - dest.writeByte((byte)1); - dest.writeParcelable(mHttpProxy, flags); - } else { - dest.writeByte((byte)0); - } - dest.writeParcelable(mNat64Prefix, 0); - - ArrayList stackedLinks = new ArrayList<>(mStackedLinks.values()); - dest.writeList(stackedLinks); - - dest.writeBoolean(mWakeOnLanSupported); - dest.writeParcelable(mParcelSensitiveFields ? mCaptivePortalApiUrl : null, 0); - dest.writeParcelable(mParcelSensitiveFields ? mCaptivePortalData : null, 0); - } - - private static void writeAddresses(@NonNull Parcel dest, @NonNull List list) { - dest.writeInt(list.size()); - for (InetAddress d : list) { - writeAddress(dest, d); - } - } - - private static void writeAddress(@NonNull Parcel dest, @Nullable InetAddress addr) { - byte[] addressBytes = (addr == null ? null : addr.getAddress()); - dest.writeByteArray(addressBytes); - if (addr instanceof Inet6Address) { - final Inet6Address v6Addr = (Inet6Address) addr; - final boolean hasScopeId = v6Addr.getScopeId() != 0; - dest.writeBoolean(hasScopeId); - if (hasScopeId) dest.writeInt(v6Addr.getScopeId()); - } - } - - @Nullable - private static InetAddress readAddress(@NonNull Parcel p) throws UnknownHostException { - final byte[] addr = p.createByteArray(); - if (addr == null) return null; - - if (addr.length == INET6_ADDR_LENGTH) { - final boolean hasScopeId = p.readBoolean(); - final int scopeId = hasScopeId ? p.readInt() : 0; - return Inet6Address.getByAddress(null /* host */, addr, scopeId); - } - - return InetAddress.getByAddress(addr); - } - - /** - * Implement the Parcelable interface. - */ - public static final @android.annotation.NonNull Creator CREATOR = - new Creator() { - public LinkProperties createFromParcel(Parcel in) { - LinkProperties netProp = new LinkProperties(); - - String iface = in.readString(); - if (iface != null) { - netProp.setInterfaceName(iface); - } - int addressCount = in.readInt(); - for (int i = 0; i < addressCount; i++) { - netProp.addLinkAddress(in.readParcelable(null)); - } - addressCount = in.readInt(); - for (int i = 0; i < addressCount; i++) { - try { - netProp.addDnsServer(readAddress(in)); - } catch (UnknownHostException e) { } - } - addressCount = in.readInt(); - for (int i = 0; i < addressCount; i++) { - try { - netProp.addValidatedPrivateDnsServer(readAddress(in)); - } catch (UnknownHostException e) { } - } - netProp.setUsePrivateDns(in.readBoolean()); - netProp.setPrivateDnsServerName(in.readString()); - addressCount = in.readInt(); - for (int i = 0; i < addressCount; i++) { - try { - netProp.addPcscfServer(readAddress(in)); - } catch (UnknownHostException e) { } - } - netProp.setDomains(in.readString()); - try { - netProp.setDhcpServerAddress((Inet4Address) InetAddress - .getByAddress(in.createByteArray())); - } catch (UnknownHostException e) { } - netProp.setMtu(in.readInt()); - netProp.setTcpBufferSizes(in.readString()); - addressCount = in.readInt(); - for (int i = 0; i < addressCount; i++) { - netProp.addRoute(in.readParcelable(null)); - } - if (in.readByte() == 1) { - netProp.setHttpProxy(in.readParcelable(null)); - } - netProp.setNat64Prefix(in.readParcelable(null)); - ArrayList stackedLinks = new ArrayList(); - in.readList(stackedLinks, LinkProperties.class.getClassLoader()); - for (LinkProperties stackedLink: stackedLinks) { - netProp.addStackedLink(stackedLink); - } - netProp.setWakeOnLanSupported(in.readBoolean()); - - netProp.setCaptivePortalApiUrl(in.readParcelable(null)); - netProp.setCaptivePortalData(in.readParcelable(null)); - return netProp; - } - - public LinkProperties[] newArray(int size) { - return new LinkProperties[size]; - } - }; - - /** - * Check the valid MTU range based on IPv4 or IPv6. - * @hide - */ - public static boolean isValidMtu(int mtu, boolean ipv6) { - if (ipv6) { - return mtu >= MIN_MTU_V6 && mtu <= MAX_MTU; - } else { - return mtu >= MIN_MTU && mtu <= MAX_MTU; - } - } -} diff --git a/packages/Connectivity/framework/src/android/net/MacAddress.java b/packages/Connectivity/framework/src/android/net/MacAddress.java deleted file mode 100644 index 26a504a29c1cf..0000000000000 --- a/packages/Connectivity/framework/src/android/net/MacAddress.java +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.compat.annotation.UnsupportedAppUsage; -import android.net.wifi.WifiInfo; -import android.os.Build; -import android.os.Parcel; -import android.os.Parcelable; - -import com.android.net.module.util.MacAddressUtils; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.net.Inet6Address; -import java.net.UnknownHostException; -import java.security.SecureRandom; -import java.util.Arrays; -import java.util.Objects; - -/** - * Representation of a MAC address. - * - * This class only supports 48 bits long addresses and does not support 64 bits long addresses. - * Instances of this class are immutable. This class provides implementations of hashCode() - * and equals() that make it suitable for use as keys in standard implementations of - * {@link java.util.Map}. - */ -public final class MacAddress implements Parcelable { - - private static final int ETHER_ADDR_LEN = 6; - private static final byte[] ETHER_ADDR_BROADCAST = addr(0xff, 0xff, 0xff, 0xff, 0xff, 0xff); - - /** - * The MacAddress representing the unique broadcast MAC address. - */ - public static final MacAddress BROADCAST_ADDRESS = MacAddress.fromBytes(ETHER_ADDR_BROADCAST); - - /** - * The MacAddress zero MAC address. - * - *

    Not publicly exposed or treated specially since the OUI 00:00:00 is registered. - * @hide - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public static final MacAddress ALL_ZEROS_ADDRESS = new MacAddress(0); - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = { "TYPE_" }, value = { - TYPE_UNKNOWN, - TYPE_UNICAST, - TYPE_MULTICAST, - TYPE_BROADCAST, - }) - public @interface MacAddressType { } - - /** @hide Indicates a MAC address of unknown type. */ - public static final int TYPE_UNKNOWN = 0; - /** Indicates a MAC address is a unicast address. */ - public static final int TYPE_UNICAST = 1; - /** Indicates a MAC address is a multicast address. */ - public static final int TYPE_MULTICAST = 2; - /** Indicates a MAC address is the broadcast address. */ - public static final int TYPE_BROADCAST = 3; - - private static final long VALID_LONG_MASK = (1L << 48) - 1; - private static final long LOCALLY_ASSIGNED_MASK = MacAddress.fromString("2:0:0:0:0:0").mAddr; - private static final long MULTICAST_MASK = MacAddress.fromString("1:0:0:0:0:0").mAddr; - private static final long OUI_MASK = MacAddress.fromString("ff:ff:ff:0:0:0").mAddr; - private static final long NIC_MASK = MacAddress.fromString("0:0:0:ff:ff:ff").mAddr; - private static final MacAddress BASE_GOOGLE_MAC = MacAddress.fromString("da:a1:19:0:0:0"); - /** Default wifi MAC address used for a special purpose **/ - private static final MacAddress DEFAULT_MAC_ADDRESS = - MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS); - - // Internal representation of the MAC address as a single 8 byte long. - // The encoding scheme sets the two most significant bytes to 0. The 6 bytes of the - // MAC address are encoded in the 6 least significant bytes of the long, where the first - // byte of the array is mapped to the 3rd highest logical byte of the long, the second - // byte of the array is mapped to the 4th highest logical byte of the long, and so on. - private final long mAddr; - - private MacAddress(long addr) { - mAddr = (VALID_LONG_MASK & addr); - } - - /** - * Returns the type of this address. - * - * @return the int constant representing the MAC address type of this MacAddress. - */ - public @MacAddressType int getAddressType() { - if (equals(BROADCAST_ADDRESS)) { - return TYPE_BROADCAST; - } - if ((mAddr & MULTICAST_MASK) != 0) { - return TYPE_MULTICAST; - } - return TYPE_UNICAST; - } - - /** - * @return true if this MacAddress is a locally assigned address. - */ - public boolean isLocallyAssigned() { - return (mAddr & LOCALLY_ASSIGNED_MASK) != 0; - } - - /** - * Convert this MacAddress to a byte array. - * - * The returned array is in network order. For example, if this MacAddress is 1:2:3:4:5:6, - * the returned array is [1, 2, 3, 4, 5, 6]. - * - * @return a byte array representation of this MacAddress. - */ - public @NonNull byte[] toByteArray() { - return byteAddrFromLongAddr(mAddr); - } - - /** - * Returns a human-readable representation of this MacAddress. - * The exact format is implementation-dependent and should not be assumed to have any - * particular format. - */ - @Override - public @NonNull String toString() { - return stringAddrFromLongAddr(mAddr); - } - - /** - * @return a String representation of the OUI part of this MacAddress made of 3 hexadecimal - * numbers in [0,ff] joined by ':' characters. - */ - public @NonNull String toOuiString() { - return String.format( - "%02x:%02x:%02x", (mAddr >> 40) & 0xff, (mAddr >> 32) & 0xff, (mAddr >> 24) & 0xff); - } - - @Override - public int hashCode() { - return (int) ((mAddr >> 32) ^ mAddr); - } - - @Override - public boolean equals(@Nullable Object o) { - return (o instanceof MacAddress) && ((MacAddress) o).mAddr == mAddr; - } - - @Override - public void writeToParcel(Parcel out, int flags) { - out.writeLong(mAddr); - } - - @Override - public int describeContents() { - return 0; - } - - public static final @android.annotation.NonNull Parcelable.Creator CREATOR = - new Parcelable.Creator() { - public MacAddress createFromParcel(Parcel in) { - return new MacAddress(in.readLong()); - } - - public MacAddress[] newArray(int size) { - return new MacAddress[size]; - } - }; - - /** - * Returns true if the given byte array is an valid MAC address. - * A valid byte array representation for a MacAddress is a non-null array of length 6. - * - * @param addr a byte array. - * @return true if the given byte array is not null and has the length of a MAC address. - * - * @hide - */ - public static boolean isMacAddress(byte[] addr) { - return MacAddressUtils.isMacAddress(addr); - } - - /** - * Returns the MAC address type of the MAC address represented by the given byte array, - * or null if the given byte array does not represent a MAC address. - * A valid byte array representation for a MacAddress is a non-null array of length 6. - * - * @param addr a byte array representing a MAC address. - * @return the int constant representing the MAC address type of the MAC address represented - * by the given byte array, or type UNKNOWN if the byte array is not a valid MAC address. - * - * @hide - */ - public static int macAddressType(byte[] addr) { - if (!isMacAddress(addr)) { - return TYPE_UNKNOWN; - } - return MacAddress.fromBytes(addr).getAddressType(); - } - - /** - * Converts a String representation of a MAC address to a byte array representation. - * A valid String representation for a MacAddress is a series of 6 values in the - * range [0,ff] printed in hexadecimal and joined by ':' characters. - * - * @param addr a String representation of a MAC address. - * @return the byte representation of the MAC address. - * @throws IllegalArgumentException if the given String is not a valid representation. - * - * @hide - */ - public static @NonNull byte[] byteAddrFromStringAddr(String addr) { - Objects.requireNonNull(addr); - String[] parts = addr.split(":"); - if (parts.length != ETHER_ADDR_LEN) { - throw new IllegalArgumentException(addr + " was not a valid MAC address"); - } - byte[] bytes = new byte[ETHER_ADDR_LEN]; - for (int i = 0; i < ETHER_ADDR_LEN; i++) { - int x = Integer.valueOf(parts[i], 16); - if (x < 0 || 0xff < x) { - throw new IllegalArgumentException(addr + "was not a valid MAC address"); - } - bytes[i] = (byte) x; - } - return bytes; - } - - /** - * Converts a byte array representation of a MAC address to a String representation made - * of 6 hexadecimal numbers in [0,ff] joined by ':' characters. - * A valid byte array representation for a MacAddress is a non-null array of length 6. - * - * @param addr a byte array representation of a MAC address. - * @return the String representation of the MAC address. - * @throws IllegalArgumentException if the given byte array is not a valid representation. - * - * @hide - */ - public static @NonNull String stringAddrFromByteAddr(byte[] addr) { - if (!isMacAddress(addr)) { - return null; - } - return String.format("%02x:%02x:%02x:%02x:%02x:%02x", - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); - } - - private static byte[] byteAddrFromLongAddr(long addr) { - return MacAddressUtils.byteAddrFromLongAddr(addr); - } - - private static long longAddrFromByteAddr(byte[] addr) { - return MacAddressUtils.longAddrFromByteAddr(addr); - } - - // Internal conversion function equivalent to longAddrFromByteAddr(byteAddrFromStringAddr(addr)) - // that avoids the allocation of an intermediary byte[]. - private static long longAddrFromStringAddr(String addr) { - Objects.requireNonNull(addr); - String[] parts = addr.split(":"); - if (parts.length != ETHER_ADDR_LEN) { - throw new IllegalArgumentException(addr + " was not a valid MAC address"); - } - long longAddr = 0; - for (int i = 0; i < parts.length; i++) { - int x = Integer.valueOf(parts[i], 16); - if (x < 0 || 0xff < x) { - throw new IllegalArgumentException(addr + "was not a valid MAC address"); - } - longAddr = x + (longAddr << 8); - } - return longAddr; - } - - // Internal conversion function equivalent to stringAddrFromByteAddr(byteAddrFromLongAddr(addr)) - // that avoids the allocation of an intermediary byte[]. - private static @NonNull String stringAddrFromLongAddr(long addr) { - return String.format("%02x:%02x:%02x:%02x:%02x:%02x", - (addr >> 40) & 0xff, - (addr >> 32) & 0xff, - (addr >> 24) & 0xff, - (addr >> 16) & 0xff, - (addr >> 8) & 0xff, - addr & 0xff); - } - - /** - * Creates a MacAddress from the given String representation. A valid String representation - * for a MacAddress is a series of 6 values in the range [0,ff] printed in hexadecimal - * and joined by ':' characters. - * - * @param addr a String representation of a MAC address. - * @return the MacAddress corresponding to the given String representation. - * @throws IllegalArgumentException if the given String is not a valid representation. - */ - public static @NonNull MacAddress fromString(@NonNull String addr) { - return new MacAddress(longAddrFromStringAddr(addr)); - } - - /** - * Creates a MacAddress from the given byte array representation. - * A valid byte array representation for a MacAddress is a non-null array of length 6. - * - * @param addr a byte array representation of a MAC address. - * @return the MacAddress corresponding to the given byte array representation. - * @throws IllegalArgumentException if the given byte array is not a valid representation. - */ - public static @NonNull MacAddress fromBytes(@NonNull byte[] addr) { - return new MacAddress(longAddrFromByteAddr(addr)); - } - - /** - * Returns a generated MAC address whose 24 least significant bits constituting the - * NIC part of the address are randomly selected and has Google OUI base. - * - * The locally assigned bit is always set to 1. The multicast bit is always set to 0. - * - * @return a random locally assigned, unicast MacAddress with Google OUI. - * - * @hide - */ - public static @NonNull MacAddress createRandomUnicastAddressWithGoogleBase() { - return MacAddressUtils.createRandomUnicastAddress(BASE_GOOGLE_MAC, new SecureRandom()); - } - - // Convenience function for working around the lack of byte literals. - private static byte[] addr(int... in) { - if (in.length != ETHER_ADDR_LEN) { - throw new IllegalArgumentException(Arrays.toString(in) - + " was not an array with length equal to " + ETHER_ADDR_LEN); - } - byte[] out = new byte[ETHER_ADDR_LEN]; - for (int i = 0; i < ETHER_ADDR_LEN; i++) { - out[i] = (byte) in[i]; - } - return out; - } - - /** - * Checks if this MAC Address matches the provided range. - * - * @param baseAddress MacAddress representing the base address to compare with. - * @param mask MacAddress representing the mask to use during comparison. - * @return true if this MAC Address matches the given range. - * - */ - public boolean matches(@NonNull MacAddress baseAddress, @NonNull MacAddress mask) { - Objects.requireNonNull(baseAddress); - Objects.requireNonNull(mask); - return (mAddr & mask.mAddr) == (baseAddress.mAddr & mask.mAddr); - } - - /** - * Create a link-local Inet6Address from the MAC address. The EUI-48 MAC address is converted - * to an EUI-64 MAC address per RFC 4291. The resulting EUI-64 is used to construct a link-local - * IPv6 address per RFC 4862. - * - * @return A link-local Inet6Address constructed from the MAC address. - */ - public @Nullable Inet6Address getLinkLocalIpv6FromEui48Mac() { - byte[] macEui48Bytes = toByteArray(); - byte[] addr = new byte[16]; - - addr[0] = (byte) 0xfe; - addr[1] = (byte) 0x80; - addr[8] = (byte) (macEui48Bytes[0] ^ (byte) 0x02); // flip the link-local bit - addr[9] = macEui48Bytes[1]; - addr[10] = macEui48Bytes[2]; - addr[11] = (byte) 0xff; - addr[12] = (byte) 0xfe; - addr[13] = macEui48Bytes[3]; - addr[14] = macEui48Bytes[4]; - addr[15] = macEui48Bytes[5]; - - try { - return Inet6Address.getByAddress(null, addr, 0); - } catch (UnknownHostException e) { - return null; - } - } -} diff --git a/packages/Connectivity/framework/src/android/net/NattKeepalivePacketData.java b/packages/Connectivity/framework/src/android/net/NattKeepalivePacketData.java deleted file mode 100644 index c4f8fc281f25d..0000000000000 --- a/packages/Connectivity/framework/src/android/net/NattKeepalivePacketData.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static android.net.InvalidPacketException.ERROR_INVALID_IP_ADDRESS; -import static android.net.InvalidPacketException.ERROR_INVALID_PORT; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SystemApi; -import android.os.Parcel; -import android.os.Parcelable; -import android.system.OsConstants; - -import com.android.net.module.util.IpUtils; - -import java.net.Inet4Address; -import java.net.InetAddress; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.Objects; - -/** @hide */ -@SystemApi -public final class NattKeepalivePacketData extends KeepalivePacketData implements Parcelable { - private static final int IPV4_HEADER_LENGTH = 20; - private static final int UDP_HEADER_LENGTH = 8; - - // This should only be constructed via static factory methods, such as - // nattKeepalivePacket - public NattKeepalivePacketData(@NonNull InetAddress srcAddress, int srcPort, - @NonNull InetAddress dstAddress, int dstPort, @NonNull byte[] data) throws - InvalidPacketException { - super(srcAddress, srcPort, dstAddress, dstPort, data); - } - - /** - * Factory method to create Nat-T keepalive packet structure. - * @hide - */ - public static NattKeepalivePacketData nattKeepalivePacket( - InetAddress srcAddress, int srcPort, InetAddress dstAddress, int dstPort) - throws InvalidPacketException { - - if (!(srcAddress instanceof Inet4Address) || !(dstAddress instanceof Inet4Address)) { - throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS); - } - - if (dstPort != NattSocketKeepalive.NATT_PORT) { - throw new InvalidPacketException(ERROR_INVALID_PORT); - } - - int length = IPV4_HEADER_LENGTH + UDP_HEADER_LENGTH + 1; - ByteBuffer buf = ByteBuffer.allocate(length); - buf.order(ByteOrder.BIG_ENDIAN); - buf.putShort((short) 0x4500); // IP version and TOS - buf.putShort((short) length); - buf.putInt(0); // ID, flags, offset - buf.put((byte) 64); // TTL - buf.put((byte) OsConstants.IPPROTO_UDP); - int ipChecksumOffset = buf.position(); - buf.putShort((short) 0); // IP checksum - buf.put(srcAddress.getAddress()); - buf.put(dstAddress.getAddress()); - buf.putShort((short) srcPort); - buf.putShort((short) dstPort); - buf.putShort((short) (length - 20)); // UDP length - int udpChecksumOffset = buf.position(); - buf.putShort((short) 0); // UDP checksum - buf.put((byte) 0xff); // NAT-T keepalive - buf.putShort(ipChecksumOffset, IpUtils.ipChecksum(buf, 0)); - buf.putShort(udpChecksumOffset, IpUtils.udpChecksum(buf, 0, IPV4_HEADER_LENGTH)); - - return new NattKeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, buf.array()); - } - - /** Parcelable Implementation */ - public int describeContents() { - return 0; - } - - /** Write to parcel */ - public void writeToParcel(@NonNull Parcel out, int flags) { - out.writeString(getSrcAddress().getHostAddress()); - out.writeString(getDstAddress().getHostAddress()); - out.writeInt(getSrcPort()); - out.writeInt(getDstPort()); - } - - /** Parcelable Creator */ - public static final @NonNull Parcelable.Creator CREATOR = - new Parcelable.Creator() { - public NattKeepalivePacketData createFromParcel(Parcel in) { - final InetAddress srcAddress = - InetAddresses.parseNumericAddress(in.readString()); - final InetAddress dstAddress = - InetAddresses.parseNumericAddress(in.readString()); - final int srcPort = in.readInt(); - final int dstPort = in.readInt(); - try { - return NattKeepalivePacketData.nattKeepalivePacket(srcAddress, srcPort, - dstAddress, dstPort); - } catch (InvalidPacketException e) { - throw new IllegalArgumentException( - "Invalid NAT-T keepalive data: " + e.getError()); - } - } - - public NattKeepalivePacketData[] newArray(int size) { - return new NattKeepalivePacketData[size]; - } - }; - - @Override - public boolean equals(@Nullable final Object o) { - if (!(o instanceof NattKeepalivePacketData)) return false; - final NattKeepalivePacketData other = (NattKeepalivePacketData) o; - final InetAddress srcAddress = getSrcAddress(); - final InetAddress dstAddress = getDstAddress(); - return srcAddress.equals(other.getSrcAddress()) - && dstAddress.equals(other.getDstAddress()) - && getSrcPort() == other.getSrcPort() - && getDstPort() == other.getDstPort(); - } - - @Override - public int hashCode() { - return Objects.hash(getSrcAddress(), getDstAddress(), getSrcPort(), getDstPort()); - } -} diff --git a/packages/Connectivity/framework/src/android/net/NattSocketKeepalive.java b/packages/Connectivity/framework/src/android/net/NattSocketKeepalive.java deleted file mode 100644 index a15d165e65e70..0000000000000 --- a/packages/Connectivity/framework/src/android/net/NattSocketKeepalive.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.NonNull; -import android.os.ParcelFileDescriptor; -import android.os.RemoteException; -import android.util.Log; - -import java.net.InetAddress; -import java.util.concurrent.Executor; - -/** @hide */ -public final class NattSocketKeepalive extends SocketKeepalive { - /** The NAT-T destination port for IPsec */ - public static final int NATT_PORT = 4500; - - @NonNull private final InetAddress mSource; - @NonNull private final InetAddress mDestination; - private final int mResourceId; - - NattSocketKeepalive(@NonNull IConnectivityManager service, - @NonNull Network network, - @NonNull ParcelFileDescriptor pfd, - int resourceId, - @NonNull InetAddress source, - @NonNull InetAddress destination, - @NonNull Executor executor, - @NonNull Callback callback) { - super(service, network, pfd, executor, callback); - mSource = source; - mDestination = destination; - mResourceId = resourceId; - } - - @Override - void startImpl(int intervalSec) { - mExecutor.execute(() -> { - try { - mService.startNattKeepaliveWithFd(mNetwork, mPfd, mResourceId, - intervalSec, mCallback, - mSource.getHostAddress(), mDestination.getHostAddress()); - } catch (RemoteException e) { - Log.e(TAG, "Error starting socket keepalive: ", e); - throw e.rethrowFromSystemServer(); - } - }); - } - - @Override - void stopImpl() { - mExecutor.execute(() -> { - try { - if (mSlot != null) { - mService.stopKeepalive(mNetwork, mSlot); - } - } catch (RemoteException e) { - Log.e(TAG, "Error stopping socket keepalive: ", e); - throw e.rethrowFromSystemServer(); - } - }); - } -} diff --git a/packages/Connectivity/framework/src/android/net/Network.java b/packages/Connectivity/framework/src/android/net/Network.java deleted file mode 100644 index 1f490337de937..0000000000000 --- a/packages/Connectivity/framework/src/android/net/Network.java +++ /dev/null @@ -1,530 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SystemApi; -import android.compat.annotation.UnsupportedAppUsage; -import android.os.Build; -import android.os.Parcel; -import android.os.ParcelFileDescriptor; -import android.os.Parcelable; -import android.system.ErrnoException; -import android.system.Os; -import android.system.OsConstants; - -import com.android.internal.annotations.GuardedBy; - -import libcore.io.IoUtils; -import libcore.net.http.Dns; -import libcore.net.http.HttpURLConnectionFactory; - -import java.io.FileDescriptor; -import java.io.IOException; -import java.net.DatagramSocket; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.MalformedURLException; -import java.net.Socket; -import java.net.SocketAddress; -import java.net.SocketException; -import java.net.URL; -import java.net.URLConnection; -import java.net.UnknownHostException; -import java.util.Arrays; -import java.util.concurrent.TimeUnit; - -import javax.net.SocketFactory; - -/** - * Identifies a {@code Network}. This is supplied to applications via - * {@link ConnectivityManager.NetworkCallback} in response to the active - * {@link ConnectivityManager#requestNetwork} or passive - * {@link ConnectivityManager#registerNetworkCallback} calls. - * It is used to direct traffic to the given {@code Network}, either on a {@link Socket} basis - * through a targeted {@link SocketFactory} or process-wide via - * {@link ConnectivityManager#bindProcessToNetwork}. - */ -public class Network implements Parcelable { - - /** - * The unique id of the network. - * @hide - */ - @UnsupportedAppUsage - public final int netId; - - // Objects used to perform per-network operations such as getSocketFactory - // and openConnection, and a lock to protect access to them. - private volatile NetworkBoundSocketFactory mNetworkBoundSocketFactory = null; - // mUrlConnectionFactory is initialized lazily when it is first needed. - @GuardedBy("mLock") - private HttpURLConnectionFactory mUrlConnectionFactory; - private final Object mLock = new Object(); - - // Default connection pool values. These are evaluated at startup, just - // like the OkHttp code. Also like the OkHttp code, we will throw parse - // exceptions at class loading time if the properties are set but are not - // valid integers. - private static final boolean httpKeepAlive = - Boolean.parseBoolean(System.getProperty("http.keepAlive", "true")); - private static final int httpMaxConnections = - httpKeepAlive ? Integer.parseInt(System.getProperty("http.maxConnections", "5")) : 0; - private static final long httpKeepAliveDurationMs = - Long.parseLong(System.getProperty("http.keepAliveDuration", "300000")); // 5 minutes. - // Value used to obfuscate network handle longs. - // The HANDLE_MAGIC value MUST be kept in sync with the corresponding - // value in the native/android/net.c NDK implementation. - private static final long HANDLE_MAGIC = 0xcafed00dL; - private static final int HANDLE_MAGIC_SIZE = 32; - private static final int USE_LOCAL_NAMESERVERS_FLAG = 0x80000000; - - // A boolean to control how getAllByName()/getByName() behaves in the face - // of Private DNS. - // - // When true, these calls will request that DNS resolution bypass any - // Private DNS that might otherwise apply. Use of this feature is restricted - // and permission checks are made by netd (attempts to bypass Private DNS - // without appropriate permission are silently turned into vanilla DNS - // requests). This only affects DNS queries made using this network object. - // - // It it not parceled to receivers because (a) it can be set or cleared at - // anytime and (b) receivers should be explicit about attempts to bypass - // Private DNS so that the intent of the code is easily determined and - // code search audits are possible. - private final transient boolean mPrivateDnsBypass; - - /** - * @hide - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public Network(int netId) { - this(netId, false); - } - - /** - * @hide - */ - public Network(int netId, boolean privateDnsBypass) { - this.netId = netId; - this.mPrivateDnsBypass = privateDnsBypass; - } - - /** - * @hide - */ - @SystemApi - public Network(@NonNull Network that) { - this(that.netId, that.mPrivateDnsBypass); - } - - /** - * Operates the same as {@code InetAddress.getAllByName} except that host - * resolution is done on this network. - * - * @param host the hostname or literal IP string to be resolved. - * @return the array of addresses associated with the specified host. - * @throws UnknownHostException if the address lookup fails. - */ - public InetAddress[] getAllByName(String host) throws UnknownHostException { - return InetAddressCompat.getAllByNameOnNet(host, getNetIdForResolv()); - } - - /** - * Operates the same as {@code InetAddress.getByName} except that host - * resolution is done on this network. - * - * @param host the hostname to be resolved to an address or {@code null}. - * @return the {@code InetAddress} instance representing the host. - * @throws UnknownHostException - * if the address lookup fails. - */ - public InetAddress getByName(String host) throws UnknownHostException { - return InetAddressCompat.getByNameOnNet(host, getNetIdForResolv()); - } - - /** - * Obtain a Network object for which Private DNS is to be bypassed when attempting - * to use {@link #getAllByName(String)}/{@link #getByName(String)} methods on the given - * instance for hostname resolution. - * - * @hide - */ - @SystemApi - public @NonNull Network getPrivateDnsBypassingCopy() { - return new Network(netId, true); - } - - /** - * Get the unique id of the network. - * - * @hide - */ - @SystemApi - public int getNetId() { - return netId; - } - - /** - * Returns a netid marked with the Private DNS bypass flag. - * - * This flag must be kept in sync with the NETID_USE_LOCAL_NAMESERVERS flag - * in system/netd/include/NetdClient.h. - * - * @hide - */ - public int getNetIdForResolv() { - return mPrivateDnsBypass - ? (USE_LOCAL_NAMESERVERS_FLAG | netId) // Non-portable DNS resolution flag. - : netId; - } - - /** - * A {@code SocketFactory} that produces {@code Socket}'s bound to this network. - */ - private class NetworkBoundSocketFactory extends SocketFactory { - private Socket connectToHost(String host, int port, SocketAddress localAddress) - throws IOException { - // Lookup addresses only on this Network. - InetAddress[] hostAddresses = getAllByName(host); - // Try all addresses. - for (int i = 0; i < hostAddresses.length; i++) { - try { - Socket socket = createSocket(); - boolean failed = true; - try { - if (localAddress != null) socket.bind(localAddress); - socket.connect(new InetSocketAddress(hostAddresses[i], port)); - failed = false; - return socket; - } finally { - if (failed) IoUtils.closeQuietly(socket); - } - } catch (IOException e) { - if (i == (hostAddresses.length - 1)) throw e; - } - } - throw new UnknownHostException(host); - } - - @Override - public Socket createSocket(String host, int port, InetAddress localHost, int localPort) - throws IOException { - return connectToHost(host, port, new InetSocketAddress(localHost, localPort)); - } - - @Override - public Socket createSocket(InetAddress address, int port, InetAddress localAddress, - int localPort) throws IOException { - Socket socket = createSocket(); - boolean failed = true; - try { - socket.bind(new InetSocketAddress(localAddress, localPort)); - socket.connect(new InetSocketAddress(address, port)); - failed = false; - } finally { - if (failed) IoUtils.closeQuietly(socket); - } - return socket; - } - - @Override - public Socket createSocket(InetAddress host, int port) throws IOException { - Socket socket = createSocket(); - boolean failed = true; - try { - socket.connect(new InetSocketAddress(host, port)); - failed = false; - } finally { - if (failed) IoUtils.closeQuietly(socket); - } - return socket; - } - - @Override - public Socket createSocket(String host, int port) throws IOException { - return connectToHost(host, port, null); - } - - @Override - public Socket createSocket() throws IOException { - Socket socket = new Socket(); - boolean failed = true; - try { - bindSocket(socket); - failed = false; - } finally { - if (failed) IoUtils.closeQuietly(socket); - } - return socket; - } - } - - /** - * Returns a {@link SocketFactory} bound to this network. Any {@link Socket} created by - * this factory will have its traffic sent over this {@code Network}. Note that if this - * {@code Network} ever disconnects, this factory and any {@link Socket} it produced in the - * past or future will cease to work. - * - * @return a {@link SocketFactory} which produces {@link Socket} instances bound to this - * {@code Network}. - */ - public SocketFactory getSocketFactory() { - if (mNetworkBoundSocketFactory == null) { - synchronized (mLock) { - if (mNetworkBoundSocketFactory == null) { - mNetworkBoundSocketFactory = new NetworkBoundSocketFactory(); - } - } - } - return mNetworkBoundSocketFactory; - } - - private static HttpURLConnectionFactory createUrlConnectionFactory(Dns dnsLookup) { - // Set configuration on the HttpURLConnectionFactory that will be good for all - // connections created by this Network. Configuration that might vary is left - // until openConnection() and passed as arguments. - HttpURLConnectionFactory urlConnectionFactory = HttpURLConnectionFactory.createInstance(); - urlConnectionFactory.setDns(dnsLookup); // Let traffic go via dnsLookup - // A private connection pool just for this Network. - urlConnectionFactory.setNewConnectionPool(httpMaxConnections, - httpKeepAliveDurationMs, TimeUnit.MILLISECONDS); - return urlConnectionFactory; - } - - /** - * Opens the specified {@link URL} on this {@code Network}, such that all traffic will be sent - * on this Network. The URL protocol must be {@code HTTP} or {@code HTTPS}. - * - * @return a {@code URLConnection} to the resource referred to by this URL. - * @throws MalformedURLException if the URL protocol is not HTTP or HTTPS. - * @throws IOException if an error occurs while opening the connection. - * @see java.net.URL#openConnection() - */ - public URLConnection openConnection(URL url) throws IOException { - final ConnectivityManager cm = ConnectivityManager.getInstanceOrNull(); - if (cm == null) { - throw new IOException("No ConnectivityManager yet constructed, please construct one"); - } - // TODO: Should this be optimized to avoid fetching the global proxy for every request? - final ProxyInfo proxyInfo = cm.getProxyForNetwork(this); - final java.net.Proxy proxy; - if (proxyInfo != null) { - proxy = proxyInfo.makeProxy(); - } else { - proxy = java.net.Proxy.NO_PROXY; - } - return openConnection(url, proxy); - } - - /** - * Opens the specified {@link URL} on this {@code Network}, such that all traffic will be sent - * on this Network. The URL protocol must be {@code HTTP} or {@code HTTPS}. - * - * @param proxy the proxy through which the connection will be established. - * @return a {@code URLConnection} to the resource referred to by this URL. - * @throws MalformedURLException if the URL protocol is not HTTP or HTTPS. - * @throws IllegalArgumentException if the argument proxy is null. - * @throws IOException if an error occurs while opening the connection. - * @see java.net.URL#openConnection() - */ - public URLConnection openConnection(URL url, java.net.Proxy proxy) throws IOException { - if (proxy == null) throw new IllegalArgumentException("proxy is null"); - // TODO: This creates a connection pool and host resolver for - // every Network object, instead of one for every NetId. This is - // suboptimal, because an app could potentially have more than one - // Network object for the same NetId, causing increased memory footprint - // and performance penalties due to lack of connection reuse (connection - // setup time, congestion window growth time, etc.). - // - // Instead, investigate only having one connection pool and host resolver - // for every NetId, perhaps by using a static HashMap of NetIds to - // connection pools and host resolvers. The tricky part is deciding when - // to remove a map entry; a WeakHashMap shouldn't be used because whether - // a Network is referenced doesn't correlate with whether a new Network - // will be instantiated in the near future with the same NetID. A good - // solution would involve purging empty (or when all connections are timed - // out) ConnectionPools. - final HttpURLConnectionFactory urlConnectionFactory; - synchronized (mLock) { - if (mUrlConnectionFactory == null) { - Dns dnsLookup = hostname -> Arrays.asList(getAllByName(hostname)); - mUrlConnectionFactory = createUrlConnectionFactory(dnsLookup); - } - urlConnectionFactory = mUrlConnectionFactory; - } - SocketFactory socketFactory = getSocketFactory(); - return urlConnectionFactory.openConnection(url, socketFactory, proxy); - } - - /** - * Binds the specified {@link DatagramSocket} to this {@code Network}. All data traffic on the - * socket will be sent on this {@code Network}, irrespective of any process-wide network binding - * set by {@link ConnectivityManager#bindProcessToNetwork}. The socket must not be - * connected. - */ - public void bindSocket(DatagramSocket socket) throws IOException { - // Query a property of the underlying socket to ensure that the socket's file descriptor - // exists, is available to bind to a network and is not closed. - socket.getReuseAddress(); - final ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket); - bindSocket(pfd.getFileDescriptor()); - // ParcelFileDescriptor.fromSocket() creates a dup of the original fd. The original and the - // dup share the underlying socket in the kernel. The socket is never truly closed until the - // last fd pointing to the socket being closed. So close the dup one after binding the - // socket to control the lifetime of the dup fd. - pfd.close(); - } - - /** - * Binds the specified {@link Socket} to this {@code Network}. All data traffic on the socket - * will be sent on this {@code Network}, irrespective of any process-wide network binding set by - * {@link ConnectivityManager#bindProcessToNetwork}. The socket must not be connected. - */ - public void bindSocket(Socket socket) throws IOException { - // Query a property of the underlying socket to ensure that the socket's file descriptor - // exists, is available to bind to a network and is not closed. - socket.getReuseAddress(); - final ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket); - bindSocket(pfd.getFileDescriptor()); - // ParcelFileDescriptor.fromSocket() creates a dup of the original fd. The original and the - // dup share the underlying socket in the kernel. The socket is never truly closed until the - // last fd pointing to the socket being closed. So close the dup one after binding the - // socket to control the lifetime of the dup fd. - pfd.close(); - } - - /** - * Binds the specified {@link FileDescriptor} to this {@code Network}. All data traffic on the - * socket represented by this file descriptor will be sent on this {@code Network}, - * irrespective of any process-wide network binding set by - * {@link ConnectivityManager#bindProcessToNetwork}. The socket must not be connected. - */ - public void bindSocket(FileDescriptor fd) throws IOException { - try { - final SocketAddress peer = Os.getpeername(fd); - final InetAddress inetPeer = ((InetSocketAddress) peer).getAddress(); - if (!inetPeer.isAnyLocalAddress()) { - // Apparently, the kernel doesn't update a connected UDP socket's - // routing upon mark changes. - throw new SocketException("Socket is connected"); - } - } catch (ErrnoException e) { - // getpeername() failed. - if (e.errno != OsConstants.ENOTCONN) { - throw e.rethrowAsSocketException(); - } - } catch (ClassCastException e) { - // Wasn't an InetSocketAddress. - throw new SocketException("Only AF_INET/AF_INET6 sockets supported"); - } - - final int err = NetworkUtils.bindSocketToNetwork(fd, netId); - if (err != 0) { - // bindSocketToNetwork returns negative errno. - throw new ErrnoException("Binding socket to network " + netId, -err) - .rethrowAsSocketException(); - } - } - - /** - * Returns a {@link Network} object given a handle returned from {@link #getNetworkHandle}. - * - * @param networkHandle a handle returned from {@link #getNetworkHandle}. - * @return A {@link Network} object derived from {@code networkHandle}. - */ - public static Network fromNetworkHandle(long networkHandle) { - if (networkHandle == 0) { - throw new IllegalArgumentException( - "Network.fromNetworkHandle refusing to instantiate NETID_UNSET Network."); - } - if ((networkHandle & ((1L << HANDLE_MAGIC_SIZE) - 1)) != HANDLE_MAGIC) { - throw new IllegalArgumentException( - "Value passed to fromNetworkHandle() is not a network handle."); - } - final int netIdForResolv = (int) (networkHandle >>> HANDLE_MAGIC_SIZE); - return new Network((netIdForResolv & ~USE_LOCAL_NAMESERVERS_FLAG), - ((netIdForResolv & USE_LOCAL_NAMESERVERS_FLAG) != 0) /* privateDnsBypass */); - } - - /** - * Returns a handle representing this {@code Network}, for use with the NDK API. - */ - public long getNetworkHandle() { - // The network handle is explicitly not the same as the netId. - // - // The netId is an implementation detail which might be changed in the - // future, or which alone (i.e. in the absence of some additional - // context) might not be sufficient to fully identify a Network. - // - // As such, the intention is to prevent accidental misuse of the API - // that might result if a developer assumed that handles and netIds - // were identical and passing a netId to a call expecting a handle - // "just worked". Such accidental misuse, if widely deployed, might - // prevent future changes to the semantics of the netId field or - // inhibit the expansion of state required for Network objects. - // - // This extra layer of indirection might be seen as paranoia, and might - // never end up being necessary, but the added complexity is trivial. - // At some future date it may be desirable to realign the handle with - // Multiple Provisioning Domains API recommendations, as made by the - // IETF mif working group. - if (netId == 0) { - return 0L; // make this zero condition obvious for debugging - } - return (((long) getNetIdForResolv()) << HANDLE_MAGIC_SIZE) | HANDLE_MAGIC; - } - - // implement the Parcelable interface - public int describeContents() { - return 0; - } - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(netId); - } - - public static final @android.annotation.NonNull Creator CREATOR = - new Creator() { - public Network createFromParcel(Parcel in) { - int netId = in.readInt(); - - return new Network(netId); - } - - public Network[] newArray(int size) { - return new Network[size]; - } - }; - - @Override - public boolean equals(@Nullable Object obj) { - if (!(obj instanceof Network)) return false; - Network other = (Network)obj; - return this.netId == other.netId; - } - - @Override - public int hashCode() { - return netId * 11; - } - - @Override - public String toString() { - return Integer.toString(netId); - } -} diff --git a/packages/Connectivity/framework/src/android/net/NetworkAgent.java b/packages/Connectivity/framework/src/android/net/NetworkAgent.java deleted file mode 100644 index adcf338ba1b3d..0000000000000 --- a/packages/Connectivity/framework/src/android/net/NetworkAgent.java +++ /dev/null @@ -1,1324 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.IntDef; -import android.annotation.IntRange; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SuppressLint; -import android.annotation.SystemApi; -import android.annotation.TestApi; -import android.compat.annotation.UnsupportedAppUsage; -import android.content.Context; -import android.os.Build; -import android.os.Bundle; -import android.os.ConditionVariable; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.os.RemoteException; -import android.telephony.data.EpsBearerQosSessionAttributes; -import android.telephony.data.NrQosSessionAttributes; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.time.Duration; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * A utility class for handling for communicating between bearer-specific - * code and ConnectivityService. - * - * An agent manages the life cycle of a network. A network starts its - * life cycle when {@link register} is called on NetworkAgent. The network - * is then connecting. When full L3 connectivity has been established, - * the agent should call {@link markConnected} to inform the system that - * this network is ready to use. When the network disconnects its life - * ends and the agent should call {@link unregister}, at which point the - * system will clean up and free resources. - * Any reconnection becomes a new logical network, so after a network - * is disconnected the agent cannot be used any more. Network providers - * should create a new NetworkAgent instance to handle new connections. - * - * A bearer may have more than one NetworkAgent if it can simultaneously - * support separate networks (IMS / Internet / MMS Apns on cellular, or - * perhaps connections with different SSID or P2P for Wi-Fi). - * - * This class supports methods to start and stop sending keepalive packets. - * Keepalive packets are typically sent at periodic intervals over a network - * with NAT when there is no other traffic to avoid the network forcefully - * closing the connection. NetworkAgents that manage technologies that - * have hardware support for keepalive should implement the related - * methods to save battery life. NetworkAgent that cannot get support - * without waking up the CPU should not, as this would be prohibitive in - * terms of battery - these agents should simply not override the related - * methods, which results in the implementation returning - * {@link SocketKeepalive.ERROR_UNSUPPORTED} as appropriate. - * - * Keepalive packets need to be sent at relatively frequent intervals - * (a few seconds to a few minutes). As the contents of keepalive packets - * depend on the current network status, hardware needs to be configured - * to send them and has a limited amount of memory to do so. The HAL - * formalizes this as slots that an implementation can configure to send - * the correct packets. Devices typically have a small number of slots - * per radio technology, and the specific number of slots for each - * technology is specified in configuration files. - * {@see SocketKeepalive} for details. - * - * @hide - */ -@SystemApi -public abstract class NetworkAgent { - /** - * The {@link Network} corresponding to this object. - */ - @Nullable - private volatile Network mNetwork; - - @Nullable - private volatile INetworkAgentRegistry mRegistry; - - private interface RegistryAction { - void execute(@NonNull INetworkAgentRegistry registry) throws RemoteException; - } - - private final Handler mHandler; - private final String LOG_TAG; - private static final boolean DBG = true; - private static final boolean VDBG = false; - /** @hide */ - @TestApi - public static final int MIN_LINGER_TIMER_MS = 2000; - private final ArrayList mPreConnectedQueue = new ArrayList<>(); - private volatile long mLastBwRefreshTime = 0; - private static final long BW_REFRESH_MIN_WIN_MS = 500; - private boolean mBandwidthUpdateScheduled = false; - private AtomicBoolean mBandwidthUpdatePending = new AtomicBoolean(false); - @NonNull - private NetworkInfo mNetworkInfo; - @NonNull - private final Object mRegisterLock = new Object(); - - /** - * The ID of the {@link NetworkProvider} that created this object, or - * {@link NetworkProvider#ID_NONE} if unknown. - * @hide - */ - public final int providerId; - - // ConnectivityService parses message constants from itself and NetworkAgent with MessageUtils - // for debugging purposes, and crashes if some messages have the same values. - // TODO: have ConnectivityService store message names in different maps and remove this base - private static final int BASE = 200; - - /** - * Sent by ConnectivityService to the NetworkAgent to inform it of - * suspected connectivity problems on its network. The NetworkAgent - * should take steps to verify and correct connectivity. - * @hide - */ - public static final int CMD_SUSPECT_BAD = BASE; - - /** - * Sent by the NetworkAgent (note the EVENT vs CMD prefix) to - * ConnectivityService to pass the current NetworkInfo (connection state). - * Sent when the NetworkInfo changes, mainly due to change of state. - * obj = NetworkInfo - * @hide - */ - public static final int EVENT_NETWORK_INFO_CHANGED = BASE + 1; - - /** - * Sent by the NetworkAgent to ConnectivityService to pass the current - * NetworkCapabilties. - * obj = NetworkCapabilities - * @hide - */ - public static final int EVENT_NETWORK_CAPABILITIES_CHANGED = BASE + 2; - - /** - * Sent by the NetworkAgent to ConnectivityService to pass the current - * NetworkProperties. - * obj = NetworkProperties - * @hide - */ - public static final int EVENT_NETWORK_PROPERTIES_CHANGED = BASE + 3; - - /** - * Centralize the place where base network score, and network score scaling, will be - * stored, so as we can consistently compare apple and oranges, or wifi, ethernet and LTE - * @hide - */ - public static final int WIFI_BASE_SCORE = 60; - - /** - * Sent by the NetworkAgent to ConnectivityService to pass the current - * network score. - * arg1 = network score int - * @hide - */ - public static final int EVENT_NETWORK_SCORE_CHANGED = BASE + 4; - - /** - * Sent by the NetworkAgent to ConnectivityService to pass the current - * list of underlying networks. - * obj = array of Network objects - * @hide - */ - public static final int EVENT_UNDERLYING_NETWORKS_CHANGED = BASE + 5; - - /** - * Sent by the NetworkAgent to ConnectivityService to pass the current value of the teardown - * delay. - * arg1 = teardown delay in milliseconds - * @hide - */ - public static final int EVENT_TEARDOWN_DELAY_CHANGED = BASE + 6; - - /** - * The maximum value for the teardown delay, in milliseconds. - * @hide - */ - public static final int MAX_TEARDOWN_DELAY_MS = 5000; - - /** - * Sent by ConnectivityService to the NetworkAgent to inform the agent of the - * networks status - whether we could use the network or could not, due to - * either a bad network configuration (no internet link) or captive portal. - * - * arg1 = either {@code VALID_NETWORK} or {@code INVALID_NETWORK} - * obj = Bundle containing map from {@code REDIRECT_URL_KEY} to {@code String} - * representing URL that Internet probe was redirect to, if it was redirected, - * or mapping to {@code null} otherwise. - * @hide - */ - public static final int CMD_REPORT_NETWORK_STATUS = BASE + 7; - - /** - * Network validation suceeded. - * Corresponds to {@link NetworkCapabilities.NET_CAPABILITY_VALIDATED}. - */ - public static final int VALIDATION_STATUS_VALID = 1; - - /** - * Network validation was attempted and failed. This may be received more than once as - * subsequent validation attempts are made. - */ - public static final int VALIDATION_STATUS_NOT_VALID = 2; - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = { "VALIDATION_STATUS_" }, value = { - VALIDATION_STATUS_VALID, - VALIDATION_STATUS_NOT_VALID - }) - public @interface ValidationStatus {} - - // TODO: remove. - /** @hide */ - public static final int VALID_NETWORK = 1; - /** @hide */ - public static final int INVALID_NETWORK = 2; - - /** - * The key for the redirect URL in the Bundle argument of {@code CMD_REPORT_NETWORK_STATUS}. - * @hide - */ - public static final String REDIRECT_URL_KEY = "redirect URL"; - - /** - * Sent by the NetworkAgent to ConnectivityService to indicate this network was - * explicitly selected. This should be sent before the NetworkInfo is marked - * CONNECTED so it can be given special treatment at that time. - * - * obj = boolean indicating whether to use this network even if unvalidated - * @hide - */ - public static final int EVENT_SET_EXPLICITLY_SELECTED = BASE + 8; - - /** - * Sent by ConnectivityService to the NetworkAgent to inform the agent of - * whether the network should in the future be used even if not validated. - * This decision is made by the user, but it is the network transport's - * responsibility to remember it. - * - * arg1 = 1 if true, 0 if false - * @hide - */ - public static final int CMD_SAVE_ACCEPT_UNVALIDATED = BASE + 9; - - /** - * Sent by ConnectivityService to the NetworkAgent to inform the agent to pull - * the underlying network connection for updated bandwidth information. - * @hide - */ - public static final int CMD_REQUEST_BANDWIDTH_UPDATE = BASE + 10; - - /** - * Sent by ConnectivityService to the NetworkAgent to request that the specified packet be sent - * periodically on the given interval. - * - * arg1 = the hardware slot number of the keepalive to start - * arg2 = interval in seconds - * obj = KeepalivePacketData object describing the data to be sent - * - * Also used internally by ConnectivityService / KeepaliveTracker, with different semantics. - * @hide - */ - public static final int CMD_START_SOCKET_KEEPALIVE = BASE + 11; - - /** - * Requests that the specified keepalive packet be stopped. - * - * arg1 = hardware slot number of the keepalive to stop. - * - * Also used internally by ConnectivityService / KeepaliveTracker, with different semantics. - * @hide - */ - public static final int CMD_STOP_SOCKET_KEEPALIVE = BASE + 12; - - /** - * Sent by the NetworkAgent to ConnectivityService to provide status on a socket keepalive - * request. This may either be the reply to a CMD_START_SOCKET_KEEPALIVE, or an asynchronous - * error notification. - * - * This is also sent by KeepaliveTracker to the app's {@link SocketKeepalive}, - * so that the app's {@link SocketKeepalive.Callback} methods can be called. - * - * arg1 = hardware slot number of the keepalive - * arg2 = error code - * @hide - */ - public static final int EVENT_SOCKET_KEEPALIVE = BASE + 13; - - /** - * Sent by ConnectivityService to inform this network transport of signal strength thresholds - * that when crossed should trigger a system wakeup and a NetworkCapabilities update. - * - * obj = int[] describing signal strength thresholds. - * @hide - */ - public static final int CMD_SET_SIGNAL_STRENGTH_THRESHOLDS = BASE + 14; - - /** - * Sent by ConnectivityService to the NeworkAgent to inform the agent to avoid - * automatically reconnecting to this network (e.g. via autojoin). Happens - * when user selects "No" option on the "Stay connected?" dialog box. - * @hide - */ - public static final int CMD_PREVENT_AUTOMATIC_RECONNECT = BASE + 15; - - /** - * Sent by the KeepaliveTracker to NetworkAgent to add a packet filter. - * - * For TCP keepalive offloads, keepalive packets are sent by the firmware. However, because the - * remote site will send ACK packets in response to the keepalive packets, the firmware also - * needs to be configured to properly filter the ACKs to prevent the system from waking up. - * This does not happen with UDP, so this message is TCP-specific. - * arg1 = hardware slot number of the keepalive to filter for. - * obj = the keepalive packet to send repeatedly. - * @hide - */ - public static final int CMD_ADD_KEEPALIVE_PACKET_FILTER = BASE + 16; - - /** - * Sent by the KeepaliveTracker to NetworkAgent to remove a packet filter. See - * {@link #CMD_ADD_KEEPALIVE_PACKET_FILTER}. - * arg1 = hardware slot number of the keepalive packet filter to remove. - * @hide - */ - public static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER = BASE + 17; - - /** - * Sent by ConnectivityService to the NetworkAgent to complete the bidirectional connection. - * obj = INetworkAgentRegistry - */ - private static final int EVENT_AGENT_CONNECTED = BASE + 18; - - /** - * Sent by ConnectivityService to the NetworkAgent to inform the agent that it was disconnected. - */ - private static final int EVENT_AGENT_DISCONNECTED = BASE + 19; - - /** - * Sent by QosCallbackTracker to {@link NetworkAgent} to register a new filter with - * callback. - * - * arg1 = QoS agent callback ID - * obj = {@link QosFilter} - * @hide - */ - public static final int CMD_REGISTER_QOS_CALLBACK = BASE + 20; - - /** - * Sent by QosCallbackTracker to {@link NetworkAgent} to unregister a callback. - * - * arg1 = QoS agent callback ID - * @hide - */ - public static final int CMD_UNREGISTER_QOS_CALLBACK = BASE + 21; - - /** - * Sent by ConnectivityService to {@link NetworkAgent} to inform the agent that its native - * network was created and the Network object is now valid. - * - * @hide - */ - public static final int CMD_NETWORK_CREATED = BASE + 22; - - /** - * Sent by ConnectivityService to {@link NetworkAgent} to inform the agent that its native - * network was destroyed. - * - * @hide - */ - public static final int CMD_NETWORK_DESTROYED = BASE + 23; - - /** - * Sent by the NetworkAgent to ConnectivityService to set the linger duration for this network - * agent. - * arg1 = the linger duration, represents by {@link Duration}. - * - * @hide - */ - public static final int EVENT_LINGER_DURATION_CHANGED = BASE + 24; - - private static NetworkInfo getLegacyNetworkInfo(final NetworkAgentConfig config) { - final NetworkInfo ni = new NetworkInfo(config.legacyType, config.legacySubType, - config.legacyTypeName, config.legacySubTypeName); - ni.setIsAvailable(true); - ni.setDetailedState(NetworkInfo.DetailedState.CONNECTING, null /* reason */, - config.getLegacyExtraInfo()); - return ni; - } - - // Temporary backward compatibility constructor - public NetworkAgent(@NonNull Context context, @NonNull Looper looper, @NonNull String logTag, - @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score, - @NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider) { - this(context, looper, logTag, nc, lp, - new NetworkScore.Builder().setLegacyInt(score).build(), config, provider); - } - - /** - * Create a new network agent. - * @param context a {@link Context} to get system services from. - * @param looper the {@link Looper} on which to invoke the callbacks. - * @param logTag the tag for logs - * @param nc the initial {@link NetworkCapabilities} of this network. Update with - * sendNetworkCapabilities. - * @param lp the initial {@link LinkProperties} of this network. Update with sendLinkProperties. - * @param score the initial score of this network. Update with sendNetworkScore. - * @param config an immutable {@link NetworkAgentConfig} for this agent. - * @param provider the {@link NetworkProvider} managing this agent. - */ - public NetworkAgent(@NonNull Context context, @NonNull Looper looper, @NonNull String logTag, - @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, - @NonNull NetworkScore score, @NonNull NetworkAgentConfig config, - @Nullable NetworkProvider provider) { - this(looper, context, logTag, nc, lp, score, config, - provider == null ? NetworkProvider.ID_NONE : provider.getProviderId(), - getLegacyNetworkInfo(config)); - } - - private static class InitialConfiguration { - public final Context context; - public final NetworkCapabilities capabilities; - public final LinkProperties properties; - public final NetworkScore score; - public final NetworkAgentConfig config; - public final NetworkInfo info; - InitialConfiguration(@NonNull Context context, @NonNull NetworkCapabilities capabilities, - @NonNull LinkProperties properties, @NonNull NetworkScore score, - @NonNull NetworkAgentConfig config, @NonNull NetworkInfo info) { - this.context = context; - this.capabilities = capabilities; - this.properties = properties; - this.score = score; - this.config = config; - this.info = info; - } - } - private volatile InitialConfiguration mInitialConfiguration; - - private NetworkAgent(@NonNull Looper looper, @NonNull Context context, @NonNull String logTag, - @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, - @NonNull NetworkScore score, @NonNull NetworkAgentConfig config, int providerId, - @NonNull NetworkInfo ni) { - mHandler = new NetworkAgentHandler(looper); - LOG_TAG = logTag; - mNetworkInfo = new NetworkInfo(ni); - this.providerId = providerId; - if (ni == null || nc == null || lp == null) { - throw new IllegalArgumentException(); - } - - mInitialConfiguration = new InitialConfiguration(context, - new NetworkCapabilities(nc, NetworkCapabilities.REDACT_NONE), - new LinkProperties(lp), score, config, ni); - } - - private class NetworkAgentHandler extends Handler { - NetworkAgentHandler(Looper looper) { - super(looper); - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case EVENT_AGENT_CONNECTED: { - if (mRegistry != null) { - log("Received new connection while already connected!"); - } else { - if (VDBG) log("NetworkAgent fully connected"); - synchronized (mPreConnectedQueue) { - final INetworkAgentRegistry registry = (INetworkAgentRegistry) msg.obj; - mRegistry = registry; - for (RegistryAction a : mPreConnectedQueue) { - try { - a.execute(registry); - } catch (RemoteException e) { - Log.wtf(LOG_TAG, "Communication error with registry", e); - // Fall through - } - } - mPreConnectedQueue.clear(); - } - } - break; - } - case EVENT_AGENT_DISCONNECTED: { - if (DBG) log("NetworkAgent channel lost"); - // let the client know CS is done with us. - onNetworkUnwanted(); - synchronized (mPreConnectedQueue) { - mRegistry = null; - } - break; - } - case CMD_SUSPECT_BAD: { - log("Unhandled Message " + msg); - break; - } - case CMD_REQUEST_BANDWIDTH_UPDATE: { - long currentTimeMs = System.currentTimeMillis(); - if (VDBG) { - log("CMD_REQUEST_BANDWIDTH_UPDATE request received."); - } - if (currentTimeMs >= (mLastBwRefreshTime + BW_REFRESH_MIN_WIN_MS)) { - mBandwidthUpdateScheduled = false; - if (!mBandwidthUpdatePending.getAndSet(true)) { - onBandwidthUpdateRequested(); - } - } else { - // deliver the request at a later time rather than discard it completely. - if (!mBandwidthUpdateScheduled) { - long waitTime = mLastBwRefreshTime + BW_REFRESH_MIN_WIN_MS - - currentTimeMs + 1; - mBandwidthUpdateScheduled = sendEmptyMessageDelayed( - CMD_REQUEST_BANDWIDTH_UPDATE, waitTime); - } - } - break; - } - case CMD_REPORT_NETWORK_STATUS: { - String redirectUrl = ((Bundle) msg.obj).getString(REDIRECT_URL_KEY); - if (VDBG) { - log("CMD_REPORT_NETWORK_STATUS(" - + (msg.arg1 == VALID_NETWORK ? "VALID, " : "INVALID, ") - + redirectUrl); - } - Uri uri = null; - try { - if (null != redirectUrl) { - uri = Uri.parse(redirectUrl); - } - } catch (Exception e) { - Log.wtf(LOG_TAG, "Surprising URI : " + redirectUrl, e); - } - onValidationStatus(msg.arg1 /* status */, uri); - break; - } - case CMD_SAVE_ACCEPT_UNVALIDATED: { - onSaveAcceptUnvalidated(msg.arg1 != 0); - break; - } - case CMD_START_SOCKET_KEEPALIVE: { - onStartSocketKeepalive(msg.arg1 /* slot */, - Duration.ofSeconds(msg.arg2) /* interval */, - (KeepalivePacketData) msg.obj /* packet */); - break; - } - case CMD_STOP_SOCKET_KEEPALIVE: { - onStopSocketKeepalive(msg.arg1 /* slot */); - break; - } - - case CMD_SET_SIGNAL_STRENGTH_THRESHOLDS: { - onSignalStrengthThresholdsUpdated((int[]) msg.obj); - break; - } - case CMD_PREVENT_AUTOMATIC_RECONNECT: { - onAutomaticReconnectDisabled(); - break; - } - case CMD_ADD_KEEPALIVE_PACKET_FILTER: { - onAddKeepalivePacketFilter(msg.arg1 /* slot */, - (KeepalivePacketData) msg.obj /* packet */); - break; - } - case CMD_REMOVE_KEEPALIVE_PACKET_FILTER: { - onRemoveKeepalivePacketFilter(msg.arg1 /* slot */); - break; - } - case CMD_REGISTER_QOS_CALLBACK: { - onQosCallbackRegistered( - msg.arg1 /* QoS callback id */, - (QosFilter) msg.obj /* QoS filter */); - break; - } - case CMD_UNREGISTER_QOS_CALLBACK: { - onQosCallbackUnregistered( - msg.arg1 /* QoS callback id */); - break; - } - case CMD_NETWORK_CREATED: { - onNetworkCreated(); - break; - } - case CMD_NETWORK_DESTROYED: { - onNetworkDestroyed(); - break; - } - } - } - } - - /** - * Register this network agent with ConnectivityService. - * - * This method can only be called once per network agent. - * - * @return the Network associated with this network agent (which can also be obtained later - * by calling getNetwork() on this agent). - * @throws IllegalStateException thrown by the system server if this network agent is - * already registered. - */ - @NonNull - public Network register() { - if (VDBG) log("Registering NetworkAgent"); - synchronized (mRegisterLock) { - if (mNetwork != null) { - throw new IllegalStateException("Agent already registered"); - } - final ConnectivityManager cm = (ConnectivityManager) mInitialConfiguration.context - .getSystemService(Context.CONNECTIVITY_SERVICE); - mNetwork = cm.registerNetworkAgent(new NetworkAgentBinder(mHandler), - new NetworkInfo(mInitialConfiguration.info), - mInitialConfiguration.properties, mInitialConfiguration.capabilities, - mInitialConfiguration.score, mInitialConfiguration.config, providerId); - mInitialConfiguration = null; // All this memory can now be GC'd - } - return mNetwork; - } - - private static class NetworkAgentBinder extends INetworkAgent.Stub { - private static final String LOG_TAG = NetworkAgentBinder.class.getSimpleName(); - - private final Handler mHandler; - - private NetworkAgentBinder(Handler handler) { - mHandler = handler; - } - - @Override - public void onRegistered(@NonNull INetworkAgentRegistry registry) { - mHandler.sendMessage(mHandler.obtainMessage(EVENT_AGENT_CONNECTED, registry)); - } - - @Override - public void onDisconnected() { - mHandler.sendMessage(mHandler.obtainMessage(EVENT_AGENT_DISCONNECTED)); - } - - @Override - public void onBandwidthUpdateRequested() { - mHandler.sendMessage(mHandler.obtainMessage(CMD_REQUEST_BANDWIDTH_UPDATE)); - } - - @Override - public void onValidationStatusChanged( - int validationStatus, @Nullable String captivePortalUrl) { - // TODO: consider using a parcelable as argument when the interface is structured - Bundle redirectUrlBundle = new Bundle(); - redirectUrlBundle.putString(NetworkAgent.REDIRECT_URL_KEY, captivePortalUrl); - mHandler.sendMessage(mHandler.obtainMessage(CMD_REPORT_NETWORK_STATUS, - validationStatus, 0, redirectUrlBundle)); - } - - @Override - public void onSaveAcceptUnvalidated(boolean acceptUnvalidated) { - mHandler.sendMessage(mHandler.obtainMessage(CMD_SAVE_ACCEPT_UNVALIDATED, - acceptUnvalidated ? 1 : 0, 0)); - } - - @Override - public void onStartNattSocketKeepalive(int slot, int intervalDurationMs, - @NonNull NattKeepalivePacketData packetData) { - mHandler.sendMessage(mHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, - slot, intervalDurationMs, packetData)); - } - - @Override - public void onStartTcpSocketKeepalive(int slot, int intervalDurationMs, - @NonNull TcpKeepalivePacketData packetData) { - mHandler.sendMessage(mHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, - slot, intervalDurationMs, packetData)); - } - - @Override - public void onStopSocketKeepalive(int slot) { - mHandler.sendMessage(mHandler.obtainMessage(CMD_STOP_SOCKET_KEEPALIVE, slot, 0)); - } - - @Override - public void onSignalStrengthThresholdsUpdated(@NonNull int[] thresholds) { - mHandler.sendMessage(mHandler.obtainMessage( - CMD_SET_SIGNAL_STRENGTH_THRESHOLDS, thresholds)); - } - - @Override - public void onPreventAutomaticReconnect() { - mHandler.sendMessage(mHandler.obtainMessage(CMD_PREVENT_AUTOMATIC_RECONNECT)); - } - - @Override - public void onAddNattKeepalivePacketFilter(int slot, - @NonNull NattKeepalivePacketData packetData) { - mHandler.sendMessage(mHandler.obtainMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER, - slot, 0, packetData)); - } - - @Override - public void onAddTcpKeepalivePacketFilter(int slot, - @NonNull TcpKeepalivePacketData packetData) { - mHandler.sendMessage(mHandler.obtainMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER, - slot, 0, packetData)); - } - - @Override - public void onRemoveKeepalivePacketFilter(int slot) { - mHandler.sendMessage(mHandler.obtainMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER, - slot, 0)); - } - - @Override - public void onQosFilterCallbackRegistered(final int qosCallbackId, - final QosFilterParcelable qosFilterParcelable) { - if (qosFilterParcelable.getQosFilter() != null) { - mHandler.sendMessage( - mHandler.obtainMessage(CMD_REGISTER_QOS_CALLBACK, qosCallbackId, 0, - qosFilterParcelable.getQosFilter())); - return; - } - - Log.wtf(LOG_TAG, "onQosFilterCallbackRegistered: qos filter is null."); - } - - @Override - public void onQosCallbackUnregistered(final int qosCallbackId) { - mHandler.sendMessage(mHandler.obtainMessage( - CMD_UNREGISTER_QOS_CALLBACK, qosCallbackId, 0, null)); - } - - @Override - public void onNetworkCreated() { - mHandler.sendMessage(mHandler.obtainMessage(CMD_NETWORK_CREATED)); - } - - @Override - public void onNetworkDestroyed() { - mHandler.sendMessage(mHandler.obtainMessage(CMD_NETWORK_DESTROYED)); - } - } - - /** - * Register this network agent with a testing harness. - * - * The returned Messenger sends messages to the Handler. This allows a test to send - * this object {@code CMD_*} messages as if they came from ConnectivityService, which - * is useful for testing the behavior. - * - * @hide - */ - public INetworkAgent registerForTest(final Network network) { - log("Registering NetworkAgent for test"); - synchronized (mRegisterLock) { - mNetwork = network; - mInitialConfiguration = null; - } - return new NetworkAgentBinder(mHandler); - } - - /** - * Waits for the handler to be idle. - * This is useful for testing, and has smaller scope than an accessor to mHandler. - * TODO : move the implementation in common library with the tests - * @hide - */ - @VisibleForTesting - public boolean waitForIdle(final long timeoutMs) { - final ConditionVariable cv = new ConditionVariable(false); - mHandler.post(cv::open); - return cv.block(timeoutMs); - } - - /** - * @return The Network associated with this agent, or null if it's not registered yet. - */ - @Nullable - public Network getNetwork() { - return mNetwork; - } - - private void queueOrSendMessage(@NonNull RegistryAction action) { - synchronized (mPreConnectedQueue) { - if (mRegistry != null) { - try { - action.execute(mRegistry); - } catch (RemoteException e) { - Log.wtf(LOG_TAG, "Error executing registry action", e); - // Fall through: the channel is asynchronous and does not report errors back - } - } else { - mPreConnectedQueue.add(action); - } - } - } - - /** - * Must be called by the agent when the network's {@link LinkProperties} change. - * @param linkProperties the new LinkProperties. - */ - public final void sendLinkProperties(@NonNull LinkProperties linkProperties) { - Objects.requireNonNull(linkProperties); - final LinkProperties lp = new LinkProperties(linkProperties); - queueOrSendMessage(reg -> reg.sendLinkProperties(lp)); - } - - /** - * Must be called by the agent when the network's underlying networks change. - * - *

    {@code networks} is one of the following: - *

      - *
    • a non-empty array: an array of one or more {@link Network}s, in - * decreasing preference order. For example, if this VPN uses both wifi and mobile (cellular) - * networks to carry app traffic, but prefers or uses wifi more than mobile, wifi should appear - * first in the array.
    • - *
    • an empty array: a zero-element array, meaning that the VPN has no - * underlying network connection, and thus, app traffic will not be sent or received.
    • - *
    • null: (default) signifies that the VPN uses whatever is the system's - * default network. I.e., it doesn't use the {@code bindSocket} or {@code bindDatagramSocket} - * APIs mentioned above to send traffic over specific channels.
    • - *
    - * - * @param underlyingNetworks the new list of underlying networks. - * @see {@link VpnService.Builder#setUnderlyingNetworks(Network[])} - */ - public final void setUnderlyingNetworks( - @SuppressLint("NullableCollection") @Nullable List underlyingNetworks) { - final ArrayList underlyingArray = (underlyingNetworks != null) - ? new ArrayList<>(underlyingNetworks) : null; - queueOrSendMessage(reg -> reg.sendUnderlyingNetworks(underlyingArray)); - } - - /** - * Inform ConnectivityService that this agent has now connected. - * Call {@link #unregister} to disconnect. - */ - public void markConnected() { - mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null /* reason */, - mNetworkInfo.getExtraInfo()); - queueOrSendNetworkInfo(mNetworkInfo); - } - - /** - * Unregister this network agent. - * - * This signals the network has disconnected and ends its lifecycle. After this is called, - * the network is torn down and this agent can no longer be used. - */ - public void unregister() { - // When unregistering an agent nobody should use the extrainfo (or reason) any more. - mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null /* reason */, - null /* extraInfo */); - queueOrSendNetworkInfo(mNetworkInfo); - } - - /** - * Sets the value of the teardown delay. - * - * The teardown delay is the time between when the network disconnects and when the native - * network corresponding to this {@code NetworkAgent} is destroyed. By default, the native - * network is destroyed immediately. If {@code teardownDelayMs} is non-zero, then when this - * network disconnects, the system will instead immediately mark the network as restricted - * and unavailable to unprivileged apps, but will defer destroying the native network until the - * teardown delay timer expires. - * - * The interfaces in use by this network will remain in use until the native network is - * destroyed and cannot be reused until {@link #onNetworkDestroyed()} is called. - * - * This method may be called at any time while the network is connected. It has no effect if - * the network is already disconnected and the teardown delay timer is running. - * - * @param teardownDelayMillis the teardown delay to set, or 0 to disable teardown delay. - */ - public void setTeardownDelayMillis( - @IntRange(from = 0, to = MAX_TEARDOWN_DELAY_MS) int teardownDelayMillis) { - queueOrSendMessage(reg -> reg.sendTeardownDelayMs(teardownDelayMillis)); - } - - /** - * Change the legacy subtype of this network agent. - * - * This is only for backward compatibility and should not be used by non-legacy network agents, - * or agents that did not use to set a subtype. As such, only TYPE_MOBILE type agents can use - * this and others will be thrown an exception if they try. - * - * @deprecated this is for backward compatibility only. - * @param legacySubtype the legacy subtype. - * @hide - */ - @Deprecated - @SystemApi - public void setLegacySubtype(final int legacySubtype, @NonNull final String legacySubtypeName) { - mNetworkInfo.setSubtype(legacySubtype, legacySubtypeName); - queueOrSendNetworkInfo(mNetworkInfo); - } - - /** - * Set the ExtraInfo of this network agent. - * - * This sets the ExtraInfo field inside the NetworkInfo returned by legacy public API and the - * broadcasts about the corresponding Network. - * This is only for backward compatibility and should not be used by non-legacy network agents, - * who will be thrown an exception if they try. The extra info should only be : - *
      - *
    • For cellular agents, the APN name.
    • - *
    • For ethernet agents, the interface name.
    • - *
    - * - * @deprecated this is for backward compatibility only. - * @param extraInfo the ExtraInfo. - * @hide - */ - @Deprecated - public void setLegacyExtraInfo(@Nullable final String extraInfo) { - mNetworkInfo.setExtraInfo(extraInfo); - queueOrSendNetworkInfo(mNetworkInfo); - } - - /** - * Must be called by the agent when it has a new NetworkInfo object. - * @hide TODO: expose something better. - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) - public final void sendNetworkInfo(NetworkInfo networkInfo) { - queueOrSendNetworkInfo(new NetworkInfo(networkInfo)); - } - - private void queueOrSendNetworkInfo(NetworkInfo networkInfo) { - queueOrSendMessage(reg -> reg.sendNetworkInfo(networkInfo)); - } - - /** - * Must be called by the agent when the network's {@link NetworkCapabilities} change. - * @param networkCapabilities the new NetworkCapabilities. - */ - public final void sendNetworkCapabilities(@NonNull NetworkCapabilities networkCapabilities) { - Objects.requireNonNull(networkCapabilities); - mBandwidthUpdatePending.set(false); - mLastBwRefreshTime = System.currentTimeMillis(); - final NetworkCapabilities nc = - new NetworkCapabilities(networkCapabilities, NetworkCapabilities.REDACT_NONE); - queueOrSendMessage(reg -> reg.sendNetworkCapabilities(nc)); - } - - /** - * Must be called by the agent to update the score of this network. - * - * @param score the new score. - */ - public final void sendNetworkScore(@NonNull NetworkScore score) { - Objects.requireNonNull(score); - queueOrSendMessage(reg -> reg.sendScore(score)); - } - - /** - * Must be called by the agent to update the score of this network. - * - * @param score the new score, between 0 and 99. - * deprecated use sendNetworkScore(NetworkScore) TODO : remove in S. - */ - public final void sendNetworkScore(@IntRange(from = 0, to = 99) int score) { - sendNetworkScore(new NetworkScore.Builder().setLegacyInt(score).build()); - } - - /** - * Must be called by the agent to indicate this network was manually selected by the user. - * This should be called before the NetworkInfo is marked CONNECTED so that this - * Network can be given special treatment at that time. If {@code acceptUnvalidated} is - * {@code true}, then the system will switch to this network. If it is {@code false} and the - * network cannot be validated, the system will ask the user whether to switch to this network. - * If the user confirms and selects "don't ask again", then the system will call - * {@link #saveAcceptUnvalidated} to persist the user's choice. Thus, if the transport ever - * calls this method with {@code acceptUnvalidated} set to {@code false}, it must also implement - * {@link #saveAcceptUnvalidated} to respect the user's choice. - * @hide should move to NetworkAgentConfig. - */ - public void explicitlySelected(boolean acceptUnvalidated) { - explicitlySelected(true /* explicitlySelected */, acceptUnvalidated); - } - - /** - * Must be called by the agent to indicate whether the network was manually selected by the - * user. This should be called before the network becomes connected, so it can be given - * special treatment when it does. - * - * If {@code explicitlySelected} is {@code true}, and {@code acceptUnvalidated} is {@code true}, - * then the system will switch to this network. If {@code explicitlySelected} is {@code true} - * and {@code acceptUnvalidated} is {@code false}, and the network cannot be validated, the - * system will ask the user whether to switch to this network. If the user confirms and selects - * "don't ask again", then the system will call {@link #saveAcceptUnvalidated} to persist the - * user's choice. Thus, if the transport ever calls this method with {@code explicitlySelected} - * set to {@code true} and {@code acceptUnvalidated} set to {@code false}, it must also - * implement {@link #saveAcceptUnvalidated} to respect the user's choice. - * - * If {@code explicitlySelected} is {@code false} and {@code acceptUnvalidated} is - * {@code true}, the system will interpret this as the user having accepted partial connectivity - * on this network. Thus, the system will switch to the network and consider it validated even - * if it only provides partial connectivity, but the network is not otherwise treated specially. - * @hide should move to NetworkAgentConfig. - */ - public void explicitlySelected(boolean explicitlySelected, boolean acceptUnvalidated) { - queueOrSendMessage(reg -> reg.sendExplicitlySelected( - explicitlySelected, acceptUnvalidated)); - } - - /** - * Called when ConnectivityService has indicated they no longer want this network. - * The parent factory should (previously) have received indication of the change - * as well, either canceling NetworkRequests or altering their score such that this - * network won't be immediately requested again. - */ - public void onNetworkUnwanted() { - unwanted(); - } - /** @hide TODO delete once subclasses have moved to onNetworkUnwanted. */ - protected void unwanted() { - } - - /** - * Called when ConnectivityService request a bandwidth update. The parent factory - * shall try to overwrite this method and produce a bandwidth update if capable. - * @hide - */ - @SystemApi - public void onBandwidthUpdateRequested() { - pollLceData(); - } - /** @hide TODO delete once subclasses have moved to onBandwidthUpdateRequested. */ - protected void pollLceData() { - } - - /** - * Called when the system determines the usefulness of this network. - * - * The system attempts to validate Internet connectivity on networks that provide the - * {@link NetworkCapabilities#NET_CAPABILITY_INTERNET} capability. - * - * Currently there are two possible values: - * {@code VALIDATION_STATUS_VALID} if Internet connectivity was validated, - * {@code VALIDATION_STATUS_NOT_VALID} if Internet connectivity was not validated. - * - * This is guaranteed to be called again when the network status changes, but the system - * may also call this multiple times even if the status does not change. - * - * @param status one of {@code VALIDATION_STATUS_VALID} or {@code VALIDATION_STATUS_NOT_VALID}. - * @param redirectUri If Internet connectivity is being redirected (e.g., on a captive portal), - * this is the destination the probes are being redirected to, otherwise {@code null}. - */ - public void onValidationStatus(@ValidationStatus int status, @Nullable Uri redirectUri) { - networkStatus(status, null == redirectUri ? "" : redirectUri.toString()); - } - /** @hide TODO delete once subclasses have moved to onValidationStatus */ - protected void networkStatus(int status, String redirectUrl) { - } - - - /** - * Called when the user asks to remember the choice to use this network even if unvalidated. - * The transport is responsible for remembering the choice, and the next time the user connects - * to the network, should explicitlySelected with {@code acceptUnvalidated} set to {@code true}. - * This method will only be called if {@link #explicitlySelected} was called with - * {@code acceptUnvalidated} set to {@code false}. - * @param accept whether the user wants to use the network even if unvalidated. - */ - public void onSaveAcceptUnvalidated(boolean accept) { - saveAcceptUnvalidated(accept); - } - /** @hide TODO delete once subclasses have moved to onSaveAcceptUnvalidated */ - protected void saveAcceptUnvalidated(boolean accept) { - } - - /** - * Called when ConnectivityService has successfully created this NetworkAgent's native network. - */ - public void onNetworkCreated() {} - - - /** - * Called when ConnectivityService has successfully destroy this NetworkAgent's native network. - */ - public void onNetworkDestroyed() {} - - /** - * Requests that the network hardware send the specified packet at the specified interval. - * - * @param slot the hardware slot on which to start the keepalive. - * @param interval the interval between packets, between 10 and 3600. Note that this API - * does not support sub-second precision and will round off the request. - * @param packet the packet to send. - */ - // seconds is from SocketKeepalive.MIN_INTERVAL_SEC to MAX_INTERVAL_SEC, but these should - // not be exposed as constants because they may change in the future (API guideline 4.8) - // and should have getters if exposed at all. Getters can't be used in the annotation, - // so the values unfortunately need to be copied. - public void onStartSocketKeepalive(int slot, @NonNull Duration interval, - @NonNull KeepalivePacketData packet) { - final long intervalSeconds = interval.getSeconds(); - if (intervalSeconds < SocketKeepalive.MIN_INTERVAL_SEC - || intervalSeconds > SocketKeepalive.MAX_INTERVAL_SEC) { - throw new IllegalArgumentException("Interval needs to be comprised between " - + SocketKeepalive.MIN_INTERVAL_SEC + " and " + SocketKeepalive.MAX_INTERVAL_SEC - + " but was " + intervalSeconds); - } - final Message msg = mHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, slot, - (int) intervalSeconds, packet); - startSocketKeepalive(msg); - msg.recycle(); - } - /** @hide TODO delete once subclasses have moved to onStartSocketKeepalive */ - protected void startSocketKeepalive(Message msg) { - onSocketKeepaliveEvent(msg.arg1, SocketKeepalive.ERROR_UNSUPPORTED); - } - - /** - * Requests that the network hardware stop a previously-started keepalive. - * - * @param slot the hardware slot on which to stop the keepalive. - */ - public void onStopSocketKeepalive(int slot) { - Message msg = mHandler.obtainMessage(CMD_STOP_SOCKET_KEEPALIVE, slot, 0, null); - stopSocketKeepalive(msg); - msg.recycle(); - } - /** @hide TODO delete once subclasses have moved to onStopSocketKeepalive */ - protected void stopSocketKeepalive(Message msg) { - onSocketKeepaliveEvent(msg.arg1, SocketKeepalive.ERROR_UNSUPPORTED); - } - - /** - * Must be called by the agent when a socket keepalive event occurs. - * - * @param slot the hardware slot on which the event occurred. - * @param event the event that occurred, as one of the SocketKeepalive.ERROR_* - * or SocketKeepalive.SUCCESS constants. - */ - public final void sendSocketKeepaliveEvent(int slot, - @SocketKeepalive.KeepaliveEvent int event) { - queueOrSendMessage(reg -> reg.sendSocketKeepaliveEvent(slot, event)); - } - /** @hide TODO delete once callers have moved to sendSocketKeepaliveEvent */ - public void onSocketKeepaliveEvent(int slot, int reason) { - sendSocketKeepaliveEvent(slot, reason); - } - - /** - * Called by ConnectivityService to add specific packet filter to network hardware to block - * replies (e.g., TCP ACKs) matching the sent keepalive packets. Implementations that support - * this feature must override this method. - * - * @param slot the hardware slot on which the keepalive should be sent. - * @param packet the packet that is being sent. - */ - public void onAddKeepalivePacketFilter(int slot, @NonNull KeepalivePacketData packet) { - Message msg = mHandler.obtainMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER, slot, 0, packet); - addKeepalivePacketFilter(msg); - msg.recycle(); - } - /** @hide TODO delete once subclasses have moved to onAddKeepalivePacketFilter */ - protected void addKeepalivePacketFilter(Message msg) { - } - - /** - * Called by ConnectivityService to remove a packet filter installed with - * {@link #addKeepalivePacketFilter(Message)}. Implementations that support this feature - * must override this method. - * - * @param slot the hardware slot on which the keepalive is being sent. - */ - public void onRemoveKeepalivePacketFilter(int slot) { - Message msg = mHandler.obtainMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER, slot, 0, null); - removeKeepalivePacketFilter(msg); - msg.recycle(); - } - /** @hide TODO delete once subclasses have moved to onRemoveKeepalivePacketFilter */ - protected void removeKeepalivePacketFilter(Message msg) { - } - - /** - * Called by ConnectivityService to inform this network agent of signal strength thresholds - * that when crossed should trigger a system wakeup and a NetworkCapabilities update. - * - * When the system updates the list of thresholds that should wake up the CPU for a - * given agent it will call this method on the agent. The agent that implement this - * should implement it in hardware so as to ensure the CPU will be woken up on breach. - * Agents are expected to react to a breach by sending an updated NetworkCapabilities - * object with the appropriate signal strength to sendNetworkCapabilities. - * - * The specific units are bearer-dependent. See details on the units and requests in - * {@link NetworkCapabilities.Builder#setSignalStrength}. - * - * @param thresholds the array of thresholds that should trigger wakeups. - */ - public void onSignalStrengthThresholdsUpdated(@NonNull int[] thresholds) { - setSignalStrengthThresholds(thresholds); - } - /** @hide TODO delete once subclasses have moved to onSetSignalStrengthThresholds */ - protected void setSignalStrengthThresholds(int[] thresholds) { - } - - /** - * Called when the user asks to not stay connected to this network because it was found to not - * provide Internet access. Usually followed by call to {@code unwanted}. The transport is - * responsible for making sure the device does not automatically reconnect to the same network - * after the {@code unwanted} call. - */ - public void onAutomaticReconnectDisabled() { - preventAutomaticReconnect(); - } - /** @hide TODO delete once subclasses have moved to onAutomaticReconnectDisabled */ - protected void preventAutomaticReconnect() { - } - - /** - * Called when a qos callback is registered with a filter. - * @param qosCallbackId the id for the callback registered - * @param filter the filter being registered - */ - public void onQosCallbackRegistered(final int qosCallbackId, final @NonNull QosFilter filter) { - } - - /** - * Called when a qos callback is registered with a filter. - *

    - * Any QoS events that are sent with the same callback id after this method is called - * are a no-op. - * - * @param qosCallbackId the id for the callback being unregistered - */ - public void onQosCallbackUnregistered(final int qosCallbackId) { - } - - - /** - * Sends the attributes of Qos Session back to the Application - * - * @param qosCallbackId the callback id that the session belongs to - * @param sessionId the unique session id across all Qos Sessions - * @param attributes the attributes of the Qos Session - */ - public final void sendQosSessionAvailable(final int qosCallbackId, final int sessionId, - @NonNull final QosSessionAttributes attributes) { - Objects.requireNonNull(attributes, "The attributes must be non-null"); - if (attributes instanceof EpsBearerQosSessionAttributes) { - queueOrSendMessage(ra -> ra.sendEpsQosSessionAvailable(qosCallbackId, - new QosSession(sessionId, QosSession.TYPE_EPS_BEARER), - (EpsBearerQosSessionAttributes)attributes)); - } else if (attributes instanceof NrQosSessionAttributes) { - queueOrSendMessage(ra -> ra.sendNrQosSessionAvailable(qosCallbackId, - new QosSession(sessionId, QosSession.TYPE_NR_BEARER), - (NrQosSessionAttributes)attributes)); - } - } - - /** - * Sends event that the Qos Session was lost. - * - * @param qosCallbackId the callback id that the session belongs to - * @param sessionId the unique session id across all Qos Sessions - * @param qosSessionType the session type {@code QosSesson#QosSessionType} - */ - public final void sendQosSessionLost(final int qosCallbackId, - final int sessionId, final int qosSessionType) { - queueOrSendMessage(ra -> ra.sendQosSessionLost(qosCallbackId, - new QosSession(sessionId, qosSessionType))); - } - - /** - * Sends the exception type back to the application. - * - * The NetworkAgent should not send anymore messages with this id. - * - * @param qosCallbackId the callback id this exception belongs to - * @param exceptionType the type of exception - */ - public final void sendQosCallbackError(final int qosCallbackId, - @QosCallbackException.ExceptionType final int exceptionType) { - queueOrSendMessage(ra -> ra.sendQosCallbackError(qosCallbackId, exceptionType)); - } - - /** - * Set the linger duration for this network agent. - * @param duration the delay between the moment the network becomes unneeded and the - * moment the network is disconnected or moved into the background. - * Note that If this duration has greater than millisecond precision, then - * the internal implementation will drop any excess precision. - */ - public void setLingerDuration(@NonNull final Duration duration) { - Objects.requireNonNull(duration); - final long durationMs = duration.toMillis(); - if (durationMs < MIN_LINGER_TIMER_MS || durationMs > Integer.MAX_VALUE) { - throw new IllegalArgumentException("Duration must be within [" - + MIN_LINGER_TIMER_MS + "," + Integer.MAX_VALUE + "]ms"); - } - queueOrSendMessage(ra -> ra.sendLingerDuration((int) durationMs)); - } - - /** @hide */ - protected void log(final String s) { - Log.d(LOG_TAG, "NetworkAgent: " + s); - } -} diff --git a/packages/Connectivity/framework/src/android/net/NetworkAgentConfig.java b/packages/Connectivity/framework/src/android/net/NetworkAgentConfig.java deleted file mode 100644 index ad8396b06ddfa..0000000000000 --- a/packages/Connectivity/framework/src/android/net/NetworkAgentConfig.java +++ /dev/null @@ -1,505 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SystemApi; -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.Objects; - -/** - * Allows a network transport to provide the system with policy and configuration information about - * a particular network when registering a {@link NetworkAgent}. This information cannot change once the agent is registered. - * - * @hide - */ -@SystemApi -public final class NetworkAgentConfig implements Parcelable { - - /** - * If the {@link Network} is a VPN, whether apps are allowed to bypass the - * VPN. This is set by a {@link VpnService} and used by - * {@link ConnectivityManager} when creating a VPN. - * - * @hide - */ - public boolean allowBypass; - - /** - * Set if the network was manually/explicitly connected to by the user either from settings - * or a 3rd party app. For example, turning on cell data is not explicit but tapping on a wifi - * ap in the wifi settings to trigger a connection is explicit. A 3rd party app asking to - * connect to a particular access point is also explicit, though this may change in the future - * as we want apps to use the multinetwork apis. - * TODO : this is a bad name, because it sounds like the user just tapped on the network. - * It's not necessarily the case ; auto-reconnection to WiFi has this true for example. - * @hide - */ - public boolean explicitlySelected; - - /** - * @return whether this network was explicitly selected by the user. - */ - public boolean isExplicitlySelected() { - return explicitlySelected; - } - - /** - * @return whether this VPN connection can be bypassed by the apps. - * - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - public boolean isBypassableVpn() { - return allowBypass; - } - - /** - * Set if the user desires to use this network even if it is unvalidated. This field has meaning - * only if {@link explicitlySelected} is true. If it is, this field must also be set to the - * appropriate value based on previous user choice. - * - * TODO : rename this field to match its accessor - * @hide - */ - public boolean acceptUnvalidated; - - /** - * @return whether the system should accept this network even if it doesn't validate. - */ - public boolean isUnvalidatedConnectivityAcceptable() { - return acceptUnvalidated; - } - - /** - * Whether the user explicitly set that this network should be validated even if presence of - * only partial internet connectivity. - * - * TODO : rename this field to match its accessor - * @hide - */ - public boolean acceptPartialConnectivity; - - /** - * @return whether the system should validate this network even if it only offers partial - * Internet connectivity. - */ - public boolean isPartialConnectivityAcceptable() { - return acceptPartialConnectivity; - } - - /** - * Set to avoid surfacing the "Sign in to network" notification. - * if carrier receivers/apps are registered to handle the carrier-specific provisioning - * procedure, a carrier specific provisioning notification will be placed. - * only one notification should be displayed. This field is set based on - * which notification should be used for provisioning. - * - * @hide - */ - public boolean provisioningNotificationDisabled; - - /** - * - * @return whether the sign in to network notification is enabled by this configuration. - * @hide - */ - public boolean isProvisioningNotificationEnabled() { - return !provisioningNotificationDisabled; - } - - /** - * For mobile networks, this is the subscriber ID (such as IMSI). - * - * @hide - */ - public String subscriberId; - - /** - * @return the subscriber ID, or null if none. - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - @Nullable - public String getSubscriberId() { - return subscriberId; - } - - /** - * Set to skip 464xlat. This means the device will treat the network as IPv6-only and - * will not attempt to detect a NAT64 via RFC 7050 DNS lookups. - * - * @hide - */ - public boolean skip464xlat; - - /** - * @return whether NAT64 prefix detection is enabled. - * @hide - */ - public boolean isNat64DetectionEnabled() { - return !skip464xlat; - } - - /** - * The legacy type of this network agent, or TYPE_NONE if unset. - * @hide - */ - public int legacyType = ConnectivityManager.TYPE_NONE; - - /** - * @return the legacy type - */ - @ConnectivityManager.LegacyNetworkType - public int getLegacyType() { - return legacyType; - } - - /** - * The legacy Sub type of this network agent, or TYPE_NONE if unset. - * @hide - */ - public int legacySubType = ConnectivityManager.TYPE_NONE; - - /** - * Set to true if the PRIVATE_DNS_BROKEN notification has shown for this network. - * Reset this bit when private DNS mode is changed from strict mode to opportunistic/off mode. - * - * This is not parceled, because it would not make sense. - * - * @hide - */ - public transient boolean hasShownBroken; - - /** - * The name of the legacy network type. It's a free-form string used in logging. - * @hide - */ - @NonNull - public String legacyTypeName = ""; - - /** - * @return the name of the legacy network type. It's a free-form string used in logging. - */ - @NonNull - public String getLegacyTypeName() { - return legacyTypeName; - } - - /** - * The name of the legacy Sub network type. It's a free-form string. - * @hide - */ - @NonNull - public String legacySubTypeName = ""; - - /** - * The legacy extra info of the agent. The extra info should only be : - *

      - *
    • For cellular agents, the APN name.
    • - *
    • For ethernet agents, the interface name.
    • - *
    - * @hide - */ - @NonNull - private String mLegacyExtraInfo = ""; - - /** - * The legacy extra info of the agent. - * @hide - */ - @NonNull - public String getLegacyExtraInfo() { - return mLegacyExtraInfo; - } - - /** @hide */ - public NetworkAgentConfig() { - } - - /** @hide */ - public NetworkAgentConfig(@Nullable NetworkAgentConfig nac) { - if (nac != null) { - allowBypass = nac.allowBypass; - explicitlySelected = nac.explicitlySelected; - acceptUnvalidated = nac.acceptUnvalidated; - acceptPartialConnectivity = nac.acceptPartialConnectivity; - subscriberId = nac.subscriberId; - provisioningNotificationDisabled = nac.provisioningNotificationDisabled; - skip464xlat = nac.skip464xlat; - legacyType = nac.legacyType; - legacyTypeName = nac.legacyTypeName; - legacySubType = nac.legacySubType; - legacySubTypeName = nac.legacySubTypeName; - mLegacyExtraInfo = nac.mLegacyExtraInfo; - } - } - - /** - * Builder class to facilitate constructing {@link NetworkAgentConfig} objects. - */ - public static final class Builder { - private final NetworkAgentConfig mConfig = new NetworkAgentConfig(); - - /** - * Sets whether the network was explicitly selected by the user. - * - * @return this builder, to facilitate chaining. - */ - @NonNull - public Builder setExplicitlySelected(final boolean explicitlySelected) { - mConfig.explicitlySelected = explicitlySelected; - return this; - } - - /** - * Sets whether the system should validate this network even if it is found not to offer - * Internet connectivity. - * - * @return this builder, to facilitate chaining. - */ - @NonNull - public Builder setUnvalidatedConnectivityAcceptable( - final boolean unvalidatedConnectivityAcceptable) { - mConfig.acceptUnvalidated = unvalidatedConnectivityAcceptable; - return this; - } - - /** - * Sets whether the system should validate this network even if it is found to only offer - * partial Internet connectivity. - * - * @return this builder, to facilitate chaining. - */ - @NonNull - public Builder setPartialConnectivityAcceptable( - final boolean partialConnectivityAcceptable) { - mConfig.acceptPartialConnectivity = partialConnectivityAcceptable; - return this; - } - - /** - * Sets the subscriber ID for this network. - * - * @return this builder, to facilitate chaining. - * @hide - */ - @NonNull - @SystemApi(client = MODULE_LIBRARIES) - public Builder setSubscriberId(@Nullable String subscriberId) { - mConfig.subscriberId = subscriberId; - return this; - } - - /** - * Enables or disables active detection of NAT64 (e.g., via RFC 7050 DNS lookups). Used to - * save power and reduce idle traffic on networks that are known to be IPv6-only without a - * NAT64. By default, NAT64 detection is enabled. - * - * @return this builder, to facilitate chaining. - */ - @NonNull - public Builder setNat64DetectionEnabled(boolean enabled) { - mConfig.skip464xlat = !enabled; - return this; - } - - /** - * Enables or disables the "Sign in to network" notification. Used if the network transport - * will perform its own carrier-specific provisioning procedure. By default, the - * notification is enabled. - * - * @return this builder, to facilitate chaining. - */ - @NonNull - public Builder setProvisioningNotificationEnabled(boolean enabled) { - mConfig.provisioningNotificationDisabled = !enabled; - return this; - } - - /** - * Sets the legacy type for this network. - * - * @param legacyType the type - * @return this builder, to facilitate chaining. - */ - @NonNull - public Builder setLegacyType(int legacyType) { - mConfig.legacyType = legacyType; - return this; - } - - /** - * Sets the legacy sub-type for this network. - * - * @param legacySubType the type - * @return this builder, to facilitate chaining. - */ - @NonNull - public Builder setLegacySubType(final int legacySubType) { - mConfig.legacySubType = legacySubType; - return this; - } - - /** - * Sets the name of the legacy type of the agent. It's a free-form string used in logging. - * @param legacyTypeName the name - * @return this builder, to facilitate chaining. - */ - @NonNull - public Builder setLegacyTypeName(@NonNull String legacyTypeName) { - mConfig.legacyTypeName = legacyTypeName; - return this; - } - - /** - * Sets the name of the legacy Sub-type of the agent. It's a free-form string. - * @param legacySubTypeName the name - * @return this builder, to facilitate chaining. - */ - @NonNull - public Builder setLegacySubTypeName(@NonNull String legacySubTypeName) { - mConfig.legacySubTypeName = legacySubTypeName; - return this; - } - - /** - * Sets the legacy extra info of the agent. - * @param legacyExtraInfo the legacy extra info. - * @return this builder, to facilitate chaining. - */ - @NonNull - public Builder setLegacyExtraInfo(@NonNull String legacyExtraInfo) { - mConfig.mLegacyExtraInfo = legacyExtraInfo; - return this; - } - - /** - * Sets whether the apps can bypass the VPN connection. - * - * @return this builder, to facilitate chaining. - * @hide - */ - @NonNull - @SystemApi(client = MODULE_LIBRARIES) - public Builder setBypassableVpn(boolean allowBypass) { - mConfig.allowBypass = allowBypass; - return this; - } - - /** - * Returns the constructed {@link NetworkAgentConfig} object. - */ - @NonNull - public NetworkAgentConfig build() { - return mConfig; - } - } - - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - final NetworkAgentConfig that = (NetworkAgentConfig) o; - return allowBypass == that.allowBypass - && explicitlySelected == that.explicitlySelected - && acceptUnvalidated == that.acceptUnvalidated - && acceptPartialConnectivity == that.acceptPartialConnectivity - && provisioningNotificationDisabled == that.provisioningNotificationDisabled - && skip464xlat == that.skip464xlat - && legacyType == that.legacyType - && Objects.equals(subscriberId, that.subscriberId) - && Objects.equals(legacyTypeName, that.legacyTypeName) - && Objects.equals(mLegacyExtraInfo, that.mLegacyExtraInfo); - } - - @Override - public int hashCode() { - return Objects.hash(allowBypass, explicitlySelected, acceptUnvalidated, - acceptPartialConnectivity, provisioningNotificationDisabled, subscriberId, - skip464xlat, legacyType, legacyTypeName, mLegacyExtraInfo); - } - - @Override - public String toString() { - return "NetworkAgentConfig {" - + " allowBypass = " + allowBypass - + ", explicitlySelected = " + explicitlySelected - + ", acceptUnvalidated = " + acceptUnvalidated - + ", acceptPartialConnectivity = " + acceptPartialConnectivity - + ", provisioningNotificationDisabled = " + provisioningNotificationDisabled - + ", subscriberId = '" + subscriberId + '\'' - + ", skip464xlat = " + skip464xlat - + ", legacyType = " + legacyType - + ", hasShownBroken = " + hasShownBroken - + ", legacyTypeName = '" + legacyTypeName + '\'' - + ", legacyExtraInfo = '" + mLegacyExtraInfo + '\'' - + "}"; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(@NonNull Parcel out, int flags) { - out.writeInt(allowBypass ? 1 : 0); - out.writeInt(explicitlySelected ? 1 : 0); - out.writeInt(acceptUnvalidated ? 1 : 0); - out.writeInt(acceptPartialConnectivity ? 1 : 0); - out.writeString(subscriberId); - out.writeInt(provisioningNotificationDisabled ? 1 : 0); - out.writeInt(skip464xlat ? 1 : 0); - out.writeInt(legacyType); - out.writeString(legacyTypeName); - out.writeInt(legacySubType); - out.writeString(legacySubTypeName); - out.writeString(mLegacyExtraInfo); - } - - public static final @NonNull Creator CREATOR = - new Creator() { - @Override - public NetworkAgentConfig createFromParcel(Parcel in) { - NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig(); - networkAgentConfig.allowBypass = in.readInt() != 0; - networkAgentConfig.explicitlySelected = in.readInt() != 0; - networkAgentConfig.acceptUnvalidated = in.readInt() != 0; - networkAgentConfig.acceptPartialConnectivity = in.readInt() != 0; - networkAgentConfig.subscriberId = in.readString(); - networkAgentConfig.provisioningNotificationDisabled = in.readInt() != 0; - networkAgentConfig.skip464xlat = in.readInt() != 0; - networkAgentConfig.legacyType = in.readInt(); - networkAgentConfig.legacyTypeName = in.readString(); - networkAgentConfig.legacySubType = in.readInt(); - networkAgentConfig.legacySubTypeName = in.readString(); - networkAgentConfig.mLegacyExtraInfo = in.readString(); - return networkAgentConfig; - } - - @Override - public NetworkAgentConfig[] newArray(int size) { - return new NetworkAgentConfig[size]; - } - }; -} diff --git a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java deleted file mode 100644 index 4932952434208..0000000000000 --- a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java +++ /dev/null @@ -1,2779 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE; - -import android.annotation.IntDef; -import android.annotation.LongDef; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.RequiresPermission; -import android.annotation.SuppressLint; -import android.annotation.SystemApi; -import android.compat.annotation.UnsupportedAppUsage; -import android.net.ConnectivityManager.NetworkCallback; -import android.net.wifi.WifiNetworkSuggestion; -import android.os.Build; -import android.os.Parcel; -import android.os.Parcelable; -import android.os.Process; -import android.text.TextUtils; -import android.util.ArraySet; -import android.util.Range; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.net.module.util.CollectionUtils; -import com.android.net.module.util.NetworkCapabilitiesUtils; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.Arrays; -import java.util.Objects; -import java.util.Set; -import java.util.StringJoiner; - -/** - * Representation of the capabilities of an active network. Instances are - * typically obtained through - * {@link NetworkCallback#onCapabilitiesChanged(Network, NetworkCapabilities)} - * or {@link ConnectivityManager#getNetworkCapabilities(Network)}. - *

    - * This replaces the old {@link ConnectivityManager#TYPE_MOBILE} method of - * network selection. Rather than indicate a need for Wi-Fi because an - * application needs high bandwidth and risk obsolescence when a new, fast - * network appears (like LTE), the application should specify it needs high - * bandwidth. Similarly if an application needs an unmetered network for a bulk - * transfer it can specify that rather than assuming all cellular based - * connections are metered and all Wi-Fi based connections are not. - */ -public final class NetworkCapabilities implements Parcelable { - private static final String TAG = "NetworkCapabilities"; - - /** - * Mechanism to support redaction of fields in NetworkCapabilities that are guarded by specific - * app permissions. - **/ - /** - * Don't redact any fields since the receiving app holds all the necessary permissions. - * - * @hide - */ - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public static final long REDACT_NONE = 0; - - /** - * Redact any fields that need {@link android.Manifest.permission#ACCESS_FINE_LOCATION} - * permission since the receiving app does not hold this permission or the location toggle - * is off. - * - * @see android.Manifest.permission#ACCESS_FINE_LOCATION - * @hide - */ - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public static final long REDACT_FOR_ACCESS_FINE_LOCATION = 1 << 0; - - /** - * Redact any fields that need {@link android.Manifest.permission#LOCAL_MAC_ADDRESS} - * permission since the receiving app does not hold this permission. - * - * @see android.Manifest.permission#LOCAL_MAC_ADDRESS - * @hide - */ - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public static final long REDACT_FOR_LOCAL_MAC_ADDRESS = 1 << 1; - - /** - * - * Redact any fields that need {@link android.Manifest.permission#NETWORK_SETTINGS} - * permission since the receiving app does not hold this permission. - * - * @see android.Manifest.permission#NETWORK_SETTINGS - * @hide - */ - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public static final long REDACT_FOR_NETWORK_SETTINGS = 1 << 2; - - /** - * Redact all fields in this object that require any relevant permission. - * @hide - */ - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public static final long REDACT_ALL = -1L; - - /** @hide */ - @LongDef(flag = true, prefix = { "REDACT_" }, value = { - REDACT_NONE, - REDACT_FOR_ACCESS_FINE_LOCATION, - REDACT_FOR_LOCAL_MAC_ADDRESS, - REDACT_FOR_NETWORK_SETTINGS, - REDACT_ALL - }) - @Retention(RetentionPolicy.SOURCE) - public @interface RedactionType {} - - // Set to true when private DNS is broken. - private boolean mPrivateDnsBroken; - - /** - * Uid of the app making the request. - */ - private int mRequestorUid; - - /** - * Package name of the app making the request. - */ - private String mRequestorPackageName; - - public NetworkCapabilities() { - clearAll(); - mNetworkCapabilities = DEFAULT_CAPABILITIES; - } - - public NetworkCapabilities(NetworkCapabilities nc) { - this(nc, REDACT_NONE); - } - - /** - * Make a copy of NetworkCapabilities. - * - * @param nc Original NetworkCapabilities - * @param redactions bitmask of redactions that needs to be performed on this new instance of - * {@link NetworkCapabilities}. - * @hide - */ - public NetworkCapabilities(@Nullable NetworkCapabilities nc, @RedactionType long redactions) { - if (nc != null) { - set(nc); - } - if (mTransportInfo != null) { - mTransportInfo = nc.mTransportInfo.makeCopy(redactions); - } - } - - /** - * Completely clears the contents of this object, removing even the capabilities that are set - * by default when the object is constructed. - * @hide - */ - public void clearAll() { - mNetworkCapabilities = mTransportTypes = mForbiddenNetworkCapabilities = 0; - mLinkUpBandwidthKbps = mLinkDownBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED; - mNetworkSpecifier = null; - mTransportInfo = null; - mSignalStrength = SIGNAL_STRENGTH_UNSPECIFIED; - mUids = null; - mAdministratorUids = new int[0]; - mOwnerUid = Process.INVALID_UID; - mSSID = null; - mPrivateDnsBroken = false; - mRequestorUid = Process.INVALID_UID; - mRequestorPackageName = null; - mSubIds = new ArraySet<>(); - } - - /** - * Set all contents of this object to the contents of a NetworkCapabilities. - * - * @param nc Original NetworkCapabilities - * @hide - */ - public void set(@NonNull NetworkCapabilities nc) { - mNetworkCapabilities = nc.mNetworkCapabilities; - mTransportTypes = nc.mTransportTypes; - mLinkUpBandwidthKbps = nc.mLinkUpBandwidthKbps; - mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps; - mNetworkSpecifier = nc.mNetworkSpecifier; - if (nc.getTransportInfo() != null) { - setTransportInfo(nc.getTransportInfo()); - } else { - setTransportInfo(null); - } - mSignalStrength = nc.mSignalStrength; - mUids = (nc.mUids == null) ? null : new ArraySet<>(nc.mUids); - setAdministratorUids(nc.getAdministratorUids()); - mOwnerUid = nc.mOwnerUid; - mForbiddenNetworkCapabilities = nc.mForbiddenNetworkCapabilities; - mSSID = nc.mSSID; - mPrivateDnsBroken = nc.mPrivateDnsBroken; - mRequestorUid = nc.mRequestorUid; - mRequestorPackageName = nc.mRequestorPackageName; - mSubIds = new ArraySet<>(nc.mSubIds); - } - - /** - * Represents the network's capabilities. If any are specified they will be satisfied - * by any Network that matches all of them. - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - private long mNetworkCapabilities; - - /** - * If any capabilities specified here they must not exist in the matching Network. - */ - private long mForbiddenNetworkCapabilities; - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = { "NET_CAPABILITY_" }, value = { - NET_CAPABILITY_MMS, - NET_CAPABILITY_SUPL, - NET_CAPABILITY_DUN, - NET_CAPABILITY_FOTA, - NET_CAPABILITY_IMS, - NET_CAPABILITY_CBS, - NET_CAPABILITY_WIFI_P2P, - NET_CAPABILITY_IA, - NET_CAPABILITY_RCS, - NET_CAPABILITY_XCAP, - NET_CAPABILITY_EIMS, - NET_CAPABILITY_NOT_METERED, - NET_CAPABILITY_INTERNET, - NET_CAPABILITY_NOT_RESTRICTED, - NET_CAPABILITY_TRUSTED, - NET_CAPABILITY_NOT_VPN, - NET_CAPABILITY_VALIDATED, - NET_CAPABILITY_CAPTIVE_PORTAL, - NET_CAPABILITY_NOT_ROAMING, - NET_CAPABILITY_FOREGROUND, - NET_CAPABILITY_NOT_CONGESTED, - NET_CAPABILITY_NOT_SUSPENDED, - NET_CAPABILITY_OEM_PAID, - NET_CAPABILITY_MCX, - NET_CAPABILITY_PARTIAL_CONNECTIVITY, - NET_CAPABILITY_TEMPORARILY_NOT_METERED, - NET_CAPABILITY_OEM_PRIVATE, - NET_CAPABILITY_VEHICLE_INTERNAL, - NET_CAPABILITY_NOT_VCN_MANAGED, - NET_CAPABILITY_ENTERPRISE, - NET_CAPABILITY_VSIM, - NET_CAPABILITY_BIP, - NET_CAPABILITY_HEAD_UNIT, - }) - public @interface NetCapability { } - - /** - * Indicates this is a network that has the ability to reach the - * carrier's MMSC for sending and receiving MMS messages. - */ - public static final int NET_CAPABILITY_MMS = 0; - - /** - * Indicates this is a network that has the ability to reach the carrier's - * SUPL server, used to retrieve GPS information. - */ - public static final int NET_CAPABILITY_SUPL = 1; - - /** - * Indicates this is a network that has the ability to reach the carrier's - * DUN or tethering gateway. - */ - public static final int NET_CAPABILITY_DUN = 2; - - /** - * Indicates this is a network that has the ability to reach the carrier's - * FOTA portal, used for over the air updates. - */ - public static final int NET_CAPABILITY_FOTA = 3; - - /** - * Indicates this is a network that has the ability to reach the carrier's - * IMS servers, used for network registration and signaling. - */ - public static final int NET_CAPABILITY_IMS = 4; - - /** - * Indicates this is a network that has the ability to reach the carrier's - * CBS servers, used for carrier specific services. - */ - public static final int NET_CAPABILITY_CBS = 5; - - /** - * Indicates this is a network that has the ability to reach a Wi-Fi direct - * peer. - */ - public static final int NET_CAPABILITY_WIFI_P2P = 6; - - /** - * Indicates this is a network that has the ability to reach a carrier's - * Initial Attach servers. - */ - public static final int NET_CAPABILITY_IA = 7; - - /** - * Indicates this is a network that has the ability to reach a carrier's - * RCS servers, used for Rich Communication Services. - */ - public static final int NET_CAPABILITY_RCS = 8; - - /** - * Indicates this is a network that has the ability to reach a carrier's - * XCAP servers, used for configuration and control. - */ - public static final int NET_CAPABILITY_XCAP = 9; - - /** - * Indicates this is a network that has the ability to reach a carrier's - * Emergency IMS servers or other services, used for network signaling - * during emergency calls. - */ - public static final int NET_CAPABILITY_EIMS = 10; - - /** - * Indicates that this network is unmetered. - */ - public static final int NET_CAPABILITY_NOT_METERED = 11; - - /** - * Indicates that this network should be able to reach the internet. - */ - public static final int NET_CAPABILITY_INTERNET = 12; - - /** - * Indicates that this network is available for general use. If this is not set - * applications should not attempt to communicate on this network. Note that this - * is simply informative and not enforcement - enforcement is handled via other means. - * Set by default. - */ - public static final int NET_CAPABILITY_NOT_RESTRICTED = 13; - - /** - * Indicates that the user has indicated implicit trust of this network. This - * generally means it's a sim-selected carrier, a plugged in ethernet, a paired - * BT device or a wifi the user asked to connect to. Untrusted networks - * are probably limited to unknown wifi AP. Set by default. - */ - public static final int NET_CAPABILITY_TRUSTED = 14; - - /** - * Indicates that this network is not a VPN. This capability is set by default and should be - * explicitly cleared for VPN networks. - */ - public static final int NET_CAPABILITY_NOT_VPN = 15; - - /** - * Indicates that connectivity on this network was successfully validated. For example, for a - * network with NET_CAPABILITY_INTERNET, it means that Internet connectivity was successfully - * detected. - */ - public static final int NET_CAPABILITY_VALIDATED = 16; - - /** - * Indicates that this network was found to have a captive portal in place last time it was - * probed. - */ - public static final int NET_CAPABILITY_CAPTIVE_PORTAL = 17; - - /** - * Indicates that this network is not roaming. - */ - public static final int NET_CAPABILITY_NOT_ROAMING = 18; - - /** - * Indicates that this network is available for use by apps, and not a network that is being - * kept up in the background to facilitate fast network switching. - */ - public static final int NET_CAPABILITY_FOREGROUND = 19; - - /** - * Indicates that this network is not congested. - *

    - * When a network is congested, applications should defer network traffic - * that can be done at a later time, such as uploading analytics. - */ - public static final int NET_CAPABILITY_NOT_CONGESTED = 20; - - /** - * Indicates that this network is not currently suspended. - *

    - * When a network is suspended, the network's IP addresses and any connections - * established on the network remain valid, but the network is temporarily unable - * to transfer data. This can happen, for example, if a cellular network experiences - * a temporary loss of signal, such as when driving through a tunnel, etc. - * A network with this capability is not suspended, so is expected to be able to - * transfer data. - */ - public static final int NET_CAPABILITY_NOT_SUSPENDED = 21; - - /** - * Indicates that traffic that goes through this network is paid by oem. For example, - * this network can be used by system apps to upload telemetry data. - * @hide - */ - @SystemApi - public static final int NET_CAPABILITY_OEM_PAID = 22; - - /** - * Indicates this is a network that has the ability to reach a carrier's Mission Critical - * servers. - */ - public static final int NET_CAPABILITY_MCX = 23; - - /** - * Indicates that this network was tested to only provide partial connectivity. - * @hide - */ - @SystemApi - public static final int NET_CAPABILITY_PARTIAL_CONNECTIVITY = 24; - - /** - * Indicates that this network is temporarily unmetered. - *

    - * This capability will be set for networks that are generally metered, but are currently - * unmetered, e.g., because the user is in a particular area. This capability can be changed at - * any time. When it is removed, applications are responsible for stopping any data transfer - * that should not occur on a metered network. - * Note that most apps should use {@link #NET_CAPABILITY_NOT_METERED} instead. For more - * information, see https://developer.android.com/about/versions/11/features/5g#meteredness. - */ - public static final int NET_CAPABILITY_TEMPORARILY_NOT_METERED = 25; - - /** - * Indicates that this network is private to the OEM and meant only for OEM use. - * @hide - */ - @SystemApi - public static final int NET_CAPABILITY_OEM_PRIVATE = 26; - - /** - * Indicates this is an internal vehicle network, meant to communicate with other - * automotive systems. - * - * @hide - */ - @SystemApi - public static final int NET_CAPABILITY_VEHICLE_INTERNAL = 27; - - /** - * Indicates that this network is not subsumed by a Virtual Carrier Network (VCN). - *

    - * To provide an experience on a VCN similar to a single traditional carrier network, in - * some cases the system sets this bit is set by default in application's network requests, - * and may choose to remove it at its own discretion when matching the request to a network. - *

    - * Applications that want to know about a Virtual Carrier Network's underlying networks, - * for example to use them for multipath purposes, should remove this bit from their network - * requests ; the system will not add it back once removed. - * @hide - */ - @SystemApi - public static final int NET_CAPABILITY_NOT_VCN_MANAGED = 28; - - /** - * Indicates that this network is intended for enterprise use. - *

    - * 5G URSP rules may indicate that all data should use a connection dedicated for enterprise - * use. If the enterprise capability is requested, all enterprise traffic will be routed over - * the connection with this capability. - */ - public static final int NET_CAPABILITY_ENTERPRISE = 29; - - /** - * Indicates that this network has ability to access the carrier's Virtual Sim service. - * @hide - */ - @SystemApi - public static final int NET_CAPABILITY_VSIM = 30; - - /** - * Indicates that this network has ability to support Bearer Independent Protol. - * @hide - */ - @SystemApi - public static final int NET_CAPABILITY_BIP = 31; - - /** - * Indicates that this network is connected to an automotive head unit. - */ - public static final int NET_CAPABILITY_HEAD_UNIT = 32; - - private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS; - private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_HEAD_UNIT; - - /** - * Network capabilities that are expected to be mutable, i.e., can change while a particular - * network is connected. - */ - private static final long MUTABLE_CAPABILITIES = - // TRUSTED can change when user explicitly connects to an untrusted network in Settings. - // http://b/18206275 - (1 << NET_CAPABILITY_TRUSTED) - | (1 << NET_CAPABILITY_VALIDATED) - | (1 << NET_CAPABILITY_CAPTIVE_PORTAL) - | (1 << NET_CAPABILITY_NOT_ROAMING) - | (1 << NET_CAPABILITY_FOREGROUND) - | (1 << NET_CAPABILITY_NOT_CONGESTED) - | (1 << NET_CAPABILITY_NOT_SUSPENDED) - | (1 << NET_CAPABILITY_PARTIAL_CONNECTIVITY) - | (1 << NET_CAPABILITY_TEMPORARILY_NOT_METERED) - | (1 << NET_CAPABILITY_NOT_VCN_MANAGED) - // The value of NET_CAPABILITY_HEAD_UNIT is 32, which cannot use int to do bit shift, - // otherwise there will be an overflow. Use long to do bit shift instead. - | (1L << NET_CAPABILITY_HEAD_UNIT); - - /** - * Network capabilities that are not allowed in NetworkRequests. This exists because the - * NetworkFactory / NetworkAgent model does not deal well with the situation where a - * capability's presence cannot be known in advance. If such a capability is requested, then we - * can get into a cycle where the NetworkFactory endlessly churns out NetworkAgents that then - * get immediately torn down because they do not have the requested capability. - */ - // Note that as a historical exception, the TRUSTED and NOT_VCN_MANAGED capabilities - // are mutable but requestable. Factories are responsible for not getting - // in an infinite loop about these. - private static final long NON_REQUESTABLE_CAPABILITIES = - MUTABLE_CAPABILITIES - & ~(1 << NET_CAPABILITY_TRUSTED) - & ~(1 << NET_CAPABILITY_NOT_VCN_MANAGED); - - /** - * Capabilities that are set by default when the object is constructed. - */ - private static final long DEFAULT_CAPABILITIES = - (1 << NET_CAPABILITY_NOT_RESTRICTED) - | (1 << NET_CAPABILITY_TRUSTED) - | (1 << NET_CAPABILITY_NOT_VPN); - - /** - * Capabilities that are managed by ConnectivityService. - */ - private static final long CONNECTIVITY_MANAGED_CAPABILITIES = - (1 << NET_CAPABILITY_VALIDATED) - | (1 << NET_CAPABILITY_CAPTIVE_PORTAL) - | (1 << NET_CAPABILITY_FOREGROUND) - | (1 << NET_CAPABILITY_PARTIAL_CONNECTIVITY); - - /** - * Capabilities that are allowed for test networks. This list must be set so that it is safe - * for an unprivileged user to create a network with these capabilities via shell. As such, - * it must never contain capabilities that are generally useful to the system, such as - * INTERNET, IMS, SUPL, etc. - */ - private static final long TEST_NETWORKS_ALLOWED_CAPABILITIES = - (1 << NET_CAPABILITY_NOT_METERED) - | (1 << NET_CAPABILITY_TEMPORARILY_NOT_METERED) - | (1 << NET_CAPABILITY_NOT_RESTRICTED) - | (1 << NET_CAPABILITY_NOT_VPN) - | (1 << NET_CAPABILITY_NOT_ROAMING) - | (1 << NET_CAPABILITY_NOT_CONGESTED) - | (1 << NET_CAPABILITY_NOT_SUSPENDED) - | (1 << NET_CAPABILITY_NOT_VCN_MANAGED); - - /** - * Adds the given capability to this {@code NetworkCapability} instance. - * Note that when searching for a network to satisfy a request, all capabilities - * requested must be satisfied. - * - * @param capability the capability to be added. - * @return This NetworkCapabilities instance, to facilitate chaining. - * @hide - */ - public @NonNull NetworkCapabilities addCapability(@NetCapability int capability) { - // If the given capability was previously added to the list of forbidden capabilities - // then the capability will also be removed from the list of forbidden capabilities. - // TODO: Consider adding forbidden capabilities to the public API and mention this - // in the documentation. - checkValidCapability(capability); - mNetworkCapabilities |= 1L << capability; - // remove from forbidden capability list - mForbiddenNetworkCapabilities &= ~(1L << capability); - return this; - } - - /** - * Adds the given capability to the list of forbidden capabilities of this - * {@code NetworkCapability} instance. Note that when searching for a network to - * satisfy a request, the network must not contain any capability from forbidden capability - * list. - *

    - * If the capability was previously added to the list of required capabilities (for - * example, it was there by default or added using {@link #addCapability(int)} method), then - * it will be removed from the list of required capabilities as well. - * - * @see #addCapability(int) - * @hide - */ - public void addForbiddenCapability(@NetCapability int capability) { - checkValidCapability(capability); - mForbiddenNetworkCapabilities |= 1L << capability; - mNetworkCapabilities &= ~(1L << capability); // remove from requested capabilities - } - - /** - * Removes (if found) the given capability from this {@code NetworkCapability} - * instance that were added via addCapability(int) or setCapabilities(int[], int[]). - * - * @param capability the capability to be removed. - * @return This NetworkCapabilities instance, to facilitate chaining. - * @hide - */ - public @NonNull NetworkCapabilities removeCapability(@NetCapability int capability) { - checkValidCapability(capability); - final long mask = ~(1L << capability); - mNetworkCapabilities &= mask; - return this; - } - - /** - * Removes (if found) the given forbidden capability from this {@code NetworkCapability} - * instance that were added via addForbiddenCapability(int) or setCapabilities(int[], int[]). - * - * @param capability the capability to be removed. - * @return This NetworkCapabilities instance, to facilitate chaining. - * @hide - */ - public @NonNull NetworkCapabilities removeForbiddenCapability(@NetCapability int capability) { - checkValidCapability(capability); - mForbiddenNetworkCapabilities &= ~(1L << capability); - return this; - } - - /** - * Sets (or clears) the given capability on this {@link NetworkCapabilities} - * instance. - * @hide - */ - public @NonNull NetworkCapabilities setCapability(@NetCapability int capability, - boolean value) { - if (value) { - addCapability(capability); - } else { - removeCapability(capability); - } - return this; - } - - /** - * Gets all the capabilities set on this {@code NetworkCapability} instance. - * - * @return an array of capability values for this instance. - */ - public @NonNull @NetCapability int[] getCapabilities() { - return NetworkCapabilitiesUtils.unpackBits(mNetworkCapabilities); - } - - /** - * Gets all the forbidden capabilities set on this {@code NetworkCapability} instance. - * - * @return an array of forbidden capability values for this instance. - * @hide - */ - public @NetCapability int[] getForbiddenCapabilities() { - return NetworkCapabilitiesUtils.unpackBits(mForbiddenNetworkCapabilities); - } - - - /** - * Sets all the capabilities set on this {@code NetworkCapability} instance. - * This overwrites any existing capabilities. - * - * @hide - */ - public void setCapabilities(@NetCapability int[] capabilities, - @NetCapability int[] forbiddenCapabilities) { - mNetworkCapabilities = NetworkCapabilitiesUtils.packBits(capabilities); - mForbiddenNetworkCapabilities = NetworkCapabilitiesUtils.packBits(forbiddenCapabilities); - } - - /** - * @deprecated use {@link #setCapabilities(int[], int[])} - * @hide - */ - @Deprecated - public void setCapabilities(@NetCapability int[] capabilities) { - setCapabilities(capabilities, new int[] {}); - } - - /** - * Tests for the presence of a capability on this instance. - * - * @param capability the capabilities to be tested for. - * @return {@code true} if set on this instance. - */ - public boolean hasCapability(@NetCapability int capability) { - return isValidCapability(capability) - && ((mNetworkCapabilities & (1L << capability)) != 0); - } - - /** @hide */ - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public boolean hasForbiddenCapability(@NetCapability int capability) { - return isValidCapability(capability) - && ((mForbiddenNetworkCapabilities & (1L << capability)) != 0); - } - - /** - * Check if this NetworkCapabilities has system managed capabilities or not. - * @hide - */ - public boolean hasConnectivityManagedCapability() { - return ((mNetworkCapabilities & CONNECTIVITY_MANAGED_CAPABILITIES) != 0); - } - - /** - * Get the name of the given capability that carriers use. - * If the capability does not have a carrier-name, returns null. - * - * @param capability The capability to get the carrier-name of. - * @return The carrier-name of the capability, or null if it doesn't exist. - * @hide - */ - @SystemApi - public static @Nullable String getCapabilityCarrierName(@NetCapability int capability) { - if (capability == NET_CAPABILITY_ENTERPRISE) { - return capabilityNameOf(capability); - } else { - return null; - } - } - - private void combineNetCapabilities(@NonNull NetworkCapabilities nc) { - final long wantedCaps = this.mNetworkCapabilities | nc.mNetworkCapabilities; - final long forbiddenCaps = - this.mForbiddenNetworkCapabilities | nc.mForbiddenNetworkCapabilities; - if ((wantedCaps & forbiddenCaps) != 0) { - throw new IllegalArgumentException( - "Cannot have the same capability in wanted and forbidden lists."); - } - this.mNetworkCapabilities = wantedCaps; - this.mForbiddenNetworkCapabilities = forbiddenCaps; - } - - /** - * Convenience function that returns a human-readable description of the first mutable - * capability we find. Used to present an error message to apps that request mutable - * capabilities. - * - * @hide - */ - public @Nullable String describeFirstNonRequestableCapability() { - final long nonRequestable = (mNetworkCapabilities | mForbiddenNetworkCapabilities) - & NON_REQUESTABLE_CAPABILITIES; - - if (nonRequestable != 0) { - return capabilityNameOf(NetworkCapabilitiesUtils.unpackBits(nonRequestable)[0]); - } - if (mLinkUpBandwidthKbps != 0 || mLinkDownBandwidthKbps != 0) return "link bandwidth"; - if (hasSignalStrength()) return "signalStrength"; - if (isPrivateDnsBroken()) { - return "privateDnsBroken"; - } - return null; - } - - private boolean satisfiedByNetCapabilities(@NonNull NetworkCapabilities nc, - boolean onlyImmutable) { - long requestedCapabilities = mNetworkCapabilities; - long requestedForbiddenCapabilities = mForbiddenNetworkCapabilities; - long providedCapabilities = nc.mNetworkCapabilities; - - if (onlyImmutable) { - requestedCapabilities &= ~MUTABLE_CAPABILITIES; - requestedForbiddenCapabilities &= ~MUTABLE_CAPABILITIES; - } - return ((providedCapabilities & requestedCapabilities) == requestedCapabilities) - && ((requestedForbiddenCapabilities & providedCapabilities) == 0); - } - - /** @hide */ - public boolean equalsNetCapabilities(@NonNull NetworkCapabilities nc) { - return (nc.mNetworkCapabilities == this.mNetworkCapabilities) - && (nc.mForbiddenNetworkCapabilities == this.mForbiddenNetworkCapabilities); - } - - private boolean equalsNetCapabilitiesRequestable(@NonNull NetworkCapabilities that) { - return ((this.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES) - == (that.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES)) - && ((this.mForbiddenNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES) - == (that.mForbiddenNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES)); - } - - /** - * Removes the NET_CAPABILITY_NOT_RESTRICTED capability if inferring the network is restricted. - * - * @hide - */ - public void maybeMarkCapabilitiesRestricted() { - if (NetworkCapabilitiesUtils.inferRestrictedCapability(this)) { - removeCapability(NET_CAPABILITY_NOT_RESTRICTED); - } - } - - /** - * Test networks have strong restrictions on what capabilities they can have. Enforce these - * restrictions. - * @hide - */ - public void restrictCapabilitesForTestNetwork(int creatorUid) { - final long originalCapabilities = mNetworkCapabilities; - final long originalTransportTypes = mTransportTypes; - final NetworkSpecifier originalSpecifier = mNetworkSpecifier; - final int originalSignalStrength = mSignalStrength; - final int originalOwnerUid = getOwnerUid(); - final int[] originalAdministratorUids = getAdministratorUids(); - final TransportInfo originalTransportInfo = getTransportInfo(); - clearAll(); - if (0 != (originalCapabilities & NET_CAPABILITY_NOT_RESTRICTED)) { - // If the test network is not restricted, then it is only allowed to declare some - // specific transports. This is to minimize impact on running apps in case an app - // run from the shell creates a test a network. - mTransportTypes = - (originalTransportTypes & UNRESTRICTED_TEST_NETWORKS_ALLOWED_TRANSPORTS) - | (1 << TRANSPORT_TEST); - } else { - // If the test transport is restricted, then it may declare any transport. - mTransportTypes = (originalTransportTypes | (1 << TRANSPORT_TEST)); - } - mNetworkCapabilities = originalCapabilities & TEST_NETWORKS_ALLOWED_CAPABILITIES; - mNetworkSpecifier = originalSpecifier; - mSignalStrength = originalSignalStrength; - mTransportInfo = originalTransportInfo; - - // Only retain the owner and administrator UIDs if they match the app registering the remote - // caller that registered the network. - if (originalOwnerUid == creatorUid) { - setOwnerUid(creatorUid); - } - if (CollectionUtils.contains(originalAdministratorUids, creatorUid)) { - setAdministratorUids(new int[] {creatorUid}); - } - // There is no need to clear the UIDs, they have already been cleared by clearAll() above. - } - - /** - * Representing the transport type. Apps should generally not care about transport. A - * request for a fast internet connection could be satisfied by a number of different - * transports. If any are specified here it will be satisfied a Network that matches - * any of them. If a caller doesn't care about the transport it should not specify any. - */ - private long mTransportTypes; - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = { "TRANSPORT_" }, value = { - TRANSPORT_CELLULAR, - TRANSPORT_WIFI, - TRANSPORT_BLUETOOTH, - TRANSPORT_ETHERNET, - TRANSPORT_VPN, - TRANSPORT_WIFI_AWARE, - TRANSPORT_LOWPAN, - TRANSPORT_TEST, - TRANSPORT_USB, - }) - public @interface Transport { } - - /** - * Indicates this network uses a Cellular transport. - */ - public static final int TRANSPORT_CELLULAR = 0; - - /** - * Indicates this network uses a Wi-Fi transport. - */ - public static final int TRANSPORT_WIFI = 1; - - /** - * Indicates this network uses a Bluetooth transport. - */ - public static final int TRANSPORT_BLUETOOTH = 2; - - /** - * Indicates this network uses an Ethernet transport. - */ - public static final int TRANSPORT_ETHERNET = 3; - - /** - * Indicates this network uses a VPN transport. - */ - public static final int TRANSPORT_VPN = 4; - - /** - * Indicates this network uses a Wi-Fi Aware transport. - */ - public static final int TRANSPORT_WIFI_AWARE = 5; - - /** - * Indicates this network uses a LoWPAN transport. - */ - public static final int TRANSPORT_LOWPAN = 6; - - /** - * Indicates this network uses a Test-only virtual interface as a transport. - * - * @hide - */ - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public static final int TRANSPORT_TEST = 7; - - /** - * Indicates this network uses a USB transport. - */ - public static final int TRANSPORT_USB = 8; - - /** @hide */ - public static final int MIN_TRANSPORT = TRANSPORT_CELLULAR; - /** @hide */ - public static final int MAX_TRANSPORT = TRANSPORT_USB; - - /** @hide */ - public static boolean isValidTransport(@Transport int transportType) { - return (MIN_TRANSPORT <= transportType) && (transportType <= MAX_TRANSPORT); - } - - private static final String[] TRANSPORT_NAMES = { - "CELLULAR", - "WIFI", - "BLUETOOTH", - "ETHERNET", - "VPN", - "WIFI_AWARE", - "LOWPAN", - "TEST", - "USB" - }; - - /** - * Allowed transports on an unrestricted test network (in addition to TRANSPORT_TEST). - */ - private static final int UNRESTRICTED_TEST_NETWORKS_ALLOWED_TRANSPORTS = - 1 << TRANSPORT_TEST - // Test ethernet networks can be created with EthernetManager#setIncludeTestInterfaces - | 1 << TRANSPORT_ETHERNET - // Test VPN networks can be created but their UID ranges must be empty. - | 1 << TRANSPORT_VPN; - - /** - * Adds the given transport type to this {@code NetworkCapability} instance. - * Multiple transports may be applied. Note that when searching - * for a network to satisfy a request, any listed in the request will satisfy the request. - * For example {@code TRANSPORT_WIFI} and {@code TRANSPORT_ETHERNET} added to a - * {@code NetworkCapabilities} would cause either a Wi-Fi network or an Ethernet network - * to be selected. This is logically different than - * {@code NetworkCapabilities.NET_CAPABILITY_*} listed above. - * - * @param transportType the transport type to be added. - * @return This NetworkCapabilities instance, to facilitate chaining. - * @hide - */ - public @NonNull NetworkCapabilities addTransportType(@Transport int transportType) { - checkValidTransportType(transportType); - mTransportTypes |= 1 << transportType; - setNetworkSpecifier(mNetworkSpecifier); // used for exception checking - return this; - } - - /** - * Removes (if found) the given transport from this {@code NetworkCapability} instance. - * - * @param transportType the transport type to be removed. - * @return This NetworkCapabilities instance, to facilitate chaining. - * @hide - */ - public @NonNull NetworkCapabilities removeTransportType(@Transport int transportType) { - checkValidTransportType(transportType); - mTransportTypes &= ~(1 << transportType); - setNetworkSpecifier(mNetworkSpecifier); // used for exception checking - return this; - } - - /** - * Sets (or clears) the given transport on this {@link NetworkCapabilities} - * instance. - * - * @hide - */ - public @NonNull NetworkCapabilities setTransportType(@Transport int transportType, - boolean value) { - if (value) { - addTransportType(transportType); - } else { - removeTransportType(transportType); - } - return this; - } - - /** - * Gets all the transports set on this {@code NetworkCapability} instance. - * - * @return an array of transport type values for this instance. - * @hide - */ - @SystemApi - @NonNull public @Transport int[] getTransportTypes() { - return NetworkCapabilitiesUtils.unpackBits(mTransportTypes); - } - - /** - * Sets all the transports set on this {@code NetworkCapability} instance. - * This overwrites any existing transports. - * - * @hide - */ - public void setTransportTypes(@Transport int[] transportTypes) { - mTransportTypes = NetworkCapabilitiesUtils.packBits(transportTypes); - } - - /** - * Tests for the presence of a transport on this instance. - * - * @param transportType the transport type to be tested for. - * @return {@code true} if set on this instance. - */ - public boolean hasTransport(@Transport int transportType) { - return isValidTransport(transportType) && ((mTransportTypes & (1 << transportType)) != 0); - } - - private void combineTransportTypes(NetworkCapabilities nc) { - this.mTransportTypes |= nc.mTransportTypes; - } - - private boolean satisfiedByTransportTypes(NetworkCapabilities nc) { - return ((this.mTransportTypes == 0) - || ((this.mTransportTypes & nc.mTransportTypes) != 0)); - } - - /** @hide */ - public boolean equalsTransportTypes(NetworkCapabilities nc) { - return (nc.mTransportTypes == this.mTransportTypes); - } - - /** - * UID of the app that owns this network, or Process#INVALID_UID if none/unknown. - * - *

    This field keeps track of the UID of the app that created this network and is in charge of - * its lifecycle. This could be the UID of apps such as the Wifi network suggestor, the running - * VPN, or Carrier Service app managing a cellular data connection. - * - *

    For NetworkCapability instances being sent from ConnectivityService, this value MUST be - * reset to Process.INVALID_UID unless all the following conditions are met: - * - *

    The caller is the network owner, AND one of the following sets of requirements is met: - * - *

      - *
    1. The described Network is a VPN - *
    - * - *

    OR: - * - *

      - *
    1. The calling app is the network owner - *
    2. The calling app has the ACCESS_FINE_LOCATION permission granted - *
    3. The user's location toggle is on - *
    - * - * This is because the owner UID is location-sensitive. The apps that request a network could - * know where the device is if they can tell for sure the system has connected to the network - * they requested. - * - *

    This is populated by the network agents and for the NetworkCapabilities instance sent by - * an app to the System Server, the value MUST be reset to Process.INVALID_UID by the system - * server. - */ - private int mOwnerUid = Process.INVALID_UID; - - /** - * Set the UID of the owner app. - * @hide - */ - public @NonNull NetworkCapabilities setOwnerUid(final int uid) { - mOwnerUid = uid; - return this; - } - - /** - * Retrieves the UID of the app that owns this network. - * - *

    For user privacy reasons, this field will only be populated if the following conditions - * are met: - * - *

    The caller is the network owner, AND one of the following sets of requirements is met: - * - *

      - *
    1. The described Network is a VPN - *
    - * - *

    OR: - * - *

      - *
    1. The calling app is the network owner - *
    2. The calling app has the ACCESS_FINE_LOCATION permission granted - *
    3. The user's location toggle is on - *
    - * - * Instances of NetworkCapabilities sent to apps without the appropriate permissions will have - * this field cleared out. - * - *

    - * This field will only be populated for VPN and wifi network suggestor apps (i.e using - * {@link WifiNetworkSuggestion}), and only for the network they own. - * In the case of wifi network suggestors apps, this field is also location sensitive, so the - * app needs to hold {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission. If the - * app targets SDK version greater than or equal to {@link Build.VERSION_CODES#S}, then they - * also need to use {@link NetworkCallback#FLAG_INCLUDE_LOCATION_INFO} to get the info in their - * callback. If the apps targets SDK version equal to {{@link Build.VERSION_CODES#R}, this field - * will always be included. The app will be blamed for location access if this field is - * included. - *

    - */ - public int getOwnerUid() { - return mOwnerUid; - } - - private boolean equalsOwnerUid(@NonNull final NetworkCapabilities nc) { - return mOwnerUid == nc.mOwnerUid; - } - - /** - * UIDs of packages that are administrators of this network, or empty if none. - * - *

    This field tracks the UIDs of packages that have permission to manage this network. - * - *

    Network owners will also be listed as administrators. - * - *

    For NetworkCapability instances being sent from the System Server, this value MUST be - * empty unless the destination is 1) the System Server, or 2) Telephony. In either case, the - * receiving entity must have the ACCESS_FINE_LOCATION permission and target R+. - * - *

    When received from an app in a NetworkRequest this is always cleared out by the system - * server. This field is never used for matching NetworkRequests to NetworkAgents. - */ - @NonNull private int[] mAdministratorUids = new int[0]; - - /** - * Sets the int[] of UIDs that are administrators of this network. - * - *

    UIDs included in administratorUids gain administrator privileges over this Network. - * Examples of UIDs that should be included in administratorUids are: - * - *

      - *
    • Carrier apps with privileges for the relevant subscription - *
    • Active VPN apps - *
    • Other application groups with a particular Network-related role - *
    - * - *

    In general, user-supplied networks (such as WiFi networks) do not have an administrator. - * - *

    An app is granted owner privileges over Networks that it supplies. The owner UID MUST - * always be included in administratorUids. - * - *

    The administrator UIDs are set by network agents. - * - * @param administratorUids the UIDs to be set as administrators of this Network. - * @throws IllegalArgumentException if duplicate UIDs are contained in administratorUids - * @see #mAdministratorUids - * @hide - */ - @NonNull - public NetworkCapabilities setAdministratorUids(@NonNull final int[] administratorUids) { - mAdministratorUids = Arrays.copyOf(administratorUids, administratorUids.length); - Arrays.sort(mAdministratorUids); - for (int i = 0; i < mAdministratorUids.length - 1; i++) { - if (mAdministratorUids[i] >= mAdministratorUids[i + 1]) { - throw new IllegalArgumentException("All administrator UIDs must be unique"); - } - } - return this; - } - - /** - * Retrieves the UIDs that are administrators of this Network. - * - *

    This is only populated in NetworkCapabilities objects that come from network agents for - * networks that are managed by specific apps on the system, such as carrier privileged apps or - * wifi suggestion apps. This will include the network owner. - * - * @return the int[] of UIDs that are administrators of this Network - * @see #mAdministratorUids - * @hide - */ - @NonNull - @SystemApi - public int[] getAdministratorUids() { - return Arrays.copyOf(mAdministratorUids, mAdministratorUids.length); - } - - /** - * Tests if the set of administrator UIDs of this network is the same as that of the passed one. - * - *

    The administrator UIDs must be in sorted order. - * - *

    nc is assumed non-null. Else, NPE. - * - * @hide - */ - @VisibleForTesting(visibility = PRIVATE) - public boolean equalsAdministratorUids(@NonNull final NetworkCapabilities nc) { - return Arrays.equals(mAdministratorUids, nc.mAdministratorUids); - } - - /** - * Combine the administrator UIDs of the capabilities. - * - *

    This is only legal if either of the administrators lists are empty, or if they are equal. - * Combining administrator UIDs is only possible for combining non-overlapping sets of UIDs. - * - *

    If both administrator lists are non-empty but not equal, they conflict with each other. In - * this case, it would not make sense to add them together. - */ - private void combineAdministratorUids(@NonNull final NetworkCapabilities nc) { - if (nc.mAdministratorUids.length == 0) return; - if (mAdministratorUids.length == 0) { - mAdministratorUids = Arrays.copyOf(nc.mAdministratorUids, nc.mAdministratorUids.length); - return; - } - if (!equalsAdministratorUids(nc)) { - throw new IllegalStateException("Can't combine two different administrator UID lists"); - } - } - - /** - * Value indicating that link bandwidth is unspecified. - * @hide - */ - public static final int LINK_BANDWIDTH_UNSPECIFIED = 0; - - /** - * Passive link bandwidth. This is a rough guide of the expected peak bandwidth - * for the first hop on the given transport. It is not measured, but may take into account - * link parameters (Radio technology, allocated channels, etc). - */ - private int mLinkUpBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED; - private int mLinkDownBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED; - - /** - * Sets the upstream bandwidth for this network in Kbps. This always only refers to - * the estimated first hop transport bandwidth. - *

    - * {@see Builder#setLinkUpstreamBandwidthKbps} - * - * @param upKbps the estimated first hop upstream (device to network) bandwidth. - * @hide - */ - public @NonNull NetworkCapabilities setLinkUpstreamBandwidthKbps(int upKbps) { - mLinkUpBandwidthKbps = upKbps; - return this; - } - - /** - * Retrieves the upstream bandwidth for this network in Kbps. This always only refers to - * the estimated first hop transport bandwidth. - * - * @return The estimated first hop upstream (device to network) bandwidth. - */ - public int getLinkUpstreamBandwidthKbps() { - return mLinkUpBandwidthKbps; - } - - /** - * Sets the downstream bandwidth for this network in Kbps. This always only refers to - * the estimated first hop transport bandwidth. - *

    - * {@see Builder#setLinkUpstreamBandwidthKbps} - * - * @param downKbps the estimated first hop downstream (network to device) bandwidth. - * @hide - */ - public @NonNull NetworkCapabilities setLinkDownstreamBandwidthKbps(int downKbps) { - mLinkDownBandwidthKbps = downKbps; - return this; - } - - /** - * Retrieves the downstream bandwidth for this network in Kbps. This always only refers to - * the estimated first hop transport bandwidth. - * - * @return The estimated first hop downstream (network to device) bandwidth. - */ - public int getLinkDownstreamBandwidthKbps() { - return mLinkDownBandwidthKbps; - } - - private void combineLinkBandwidths(NetworkCapabilities nc) { - this.mLinkUpBandwidthKbps = - Math.max(this.mLinkUpBandwidthKbps, nc.mLinkUpBandwidthKbps); - this.mLinkDownBandwidthKbps = - Math.max(this.mLinkDownBandwidthKbps, nc.mLinkDownBandwidthKbps); - } - private boolean satisfiedByLinkBandwidths(NetworkCapabilities nc) { - return !(this.mLinkUpBandwidthKbps > nc.mLinkUpBandwidthKbps - || this.mLinkDownBandwidthKbps > nc.mLinkDownBandwidthKbps); - } - private boolean equalsLinkBandwidths(NetworkCapabilities nc) { - return (this.mLinkUpBandwidthKbps == nc.mLinkUpBandwidthKbps - && this.mLinkDownBandwidthKbps == nc.mLinkDownBandwidthKbps); - } - /** @hide */ - public static int minBandwidth(int a, int b) { - if (a == LINK_BANDWIDTH_UNSPECIFIED) { - return b; - } else if (b == LINK_BANDWIDTH_UNSPECIFIED) { - return a; - } else { - return Math.min(a, b); - } - } - /** @hide */ - public static int maxBandwidth(int a, int b) { - return Math.max(a, b); - } - - private NetworkSpecifier mNetworkSpecifier = null; - private TransportInfo mTransportInfo = null; - - /** - * Sets the optional bearer specific network specifier. - * This has no meaning if a single transport is also not specified, so calling - * this without a single transport set will generate an exception, as will - * subsequently adding or removing transports after this is set. - *

    - * - * @param networkSpecifier A concrete, parcelable framework class that extends - * NetworkSpecifier. - * @return This NetworkCapabilities instance, to facilitate chaining. - * @hide - */ - public @NonNull NetworkCapabilities setNetworkSpecifier( - @NonNull NetworkSpecifier networkSpecifier) { - if (networkSpecifier != null && Long.bitCount(mTransportTypes) != 1) { - throw new IllegalStateException("Must have a single transport specified to use " + - "setNetworkSpecifier"); - } - - mNetworkSpecifier = networkSpecifier; - - return this; - } - - /** - * Sets the optional transport specific information. - * - * @param transportInfo A concrete, parcelable framework class that extends - * {@link TransportInfo}. - * @return This NetworkCapabilities instance, to facilitate chaining. - * @hide - */ - public @NonNull NetworkCapabilities setTransportInfo(@NonNull TransportInfo transportInfo) { - mTransportInfo = transportInfo; - return this; - } - - /** - * Gets the optional bearer specific network specifier. May be {@code null} if not set. - * - * @return The optional {@link NetworkSpecifier} specifying the bearer specific network - * specifier or {@code null}. - */ - public @Nullable NetworkSpecifier getNetworkSpecifier() { - return mNetworkSpecifier; - } - - /** - * Returns a transport-specific information container. The application may cast this - * container to a concrete sub-class based on its knowledge of the network request. The - * application should be able to deal with a {@code null} return value or an invalid case, - * e.g. use {@code instanceof} operator to verify expected type. - * - * @return A concrete implementation of the {@link TransportInfo} class or null if not - * available for the network. - */ - @Nullable public TransportInfo getTransportInfo() { - return mTransportInfo; - } - - private void combineSpecifiers(NetworkCapabilities nc) { - if (mNetworkSpecifier != null && !mNetworkSpecifier.equals(nc.mNetworkSpecifier)) { - throw new IllegalStateException("Can't combine two networkSpecifiers"); - } - setNetworkSpecifier(nc.mNetworkSpecifier); - } - - private boolean satisfiedBySpecifier(NetworkCapabilities nc) { - return mNetworkSpecifier == null || mNetworkSpecifier.canBeSatisfiedBy(nc.mNetworkSpecifier) - || nc.mNetworkSpecifier instanceof MatchAllNetworkSpecifier; - } - - private boolean equalsSpecifier(NetworkCapabilities nc) { - return Objects.equals(mNetworkSpecifier, nc.mNetworkSpecifier); - } - - private void combineTransportInfos(NetworkCapabilities nc) { - if (mTransportInfo != null && !mTransportInfo.equals(nc.mTransportInfo)) { - throw new IllegalStateException("Can't combine two TransportInfos"); - } - setTransportInfo(nc.mTransportInfo); - } - - private boolean equalsTransportInfo(NetworkCapabilities nc) { - return Objects.equals(mTransportInfo, nc.mTransportInfo); - } - - /** - * Magic value that indicates no signal strength provided. A request specifying this value is - * always satisfied. - */ - public static final int SIGNAL_STRENGTH_UNSPECIFIED = Integer.MIN_VALUE; - - /** - * Signal strength. This is a signed integer, and higher values indicate better signal. - * The exact units are bearer-dependent. For example, Wi-Fi uses RSSI. - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) - private int mSignalStrength = SIGNAL_STRENGTH_UNSPECIFIED; - - /** - * Sets the signal strength. This is a signed integer, with higher values indicating a stronger - * signal. The exact units are bearer-dependent. For example, Wi-Fi uses the same RSSI units - * reported by wifi code. - *

    - * Note that when used to register a network callback, this specifies the minimum acceptable - * signal strength. When received as the state of an existing network it specifies the current - * value. A value of code SIGNAL_STRENGTH_UNSPECIFIED} means no value when received and has no - * effect when requesting a callback. - * - * @param signalStrength the bearer-specific signal strength. - * @hide - */ - public @NonNull NetworkCapabilities setSignalStrength(int signalStrength) { - mSignalStrength = signalStrength; - return this; - } - - /** - * Returns {@code true} if this object specifies a signal strength. - * - * @hide - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public boolean hasSignalStrength() { - return mSignalStrength > SIGNAL_STRENGTH_UNSPECIFIED; - } - - /** - * Retrieves the signal strength. - * - * @return The bearer-specific signal strength. - */ - public int getSignalStrength() { - return mSignalStrength; - } - - private void combineSignalStrength(NetworkCapabilities nc) { - this.mSignalStrength = Math.max(this.mSignalStrength, nc.mSignalStrength); - } - - private boolean satisfiedBySignalStrength(NetworkCapabilities nc) { - return this.mSignalStrength <= nc.mSignalStrength; - } - - private boolean equalsSignalStrength(NetworkCapabilities nc) { - return this.mSignalStrength == nc.mSignalStrength; - } - - /** - * List of UIDs this network applies to. No restriction if null. - *

    - * For networks, mUids represent the list of network this applies to, and null means this - * network applies to all UIDs. - * For requests, mUids is the list of UIDs this network MUST apply to to match ; ALL UIDs - * must be included in a network so that they match. As an exception to the general rule, - * a null mUids field for requests mean "no requirements" rather than what the general rule - * would suggest ("must apply to all UIDs") : this is because this has shown to be what users - * of this API expect in practice. A network that must match all UIDs can still be - * expressed with a set ranging the entire set of possible UIDs. - *

    - * mUids is typically (and at this time, only) used by VPN. This network is only available to - * the UIDs in this list, and it is their default network. Apps in this list that wish to - * bypass the VPN can do so iff the VPN app allows them to or if they are privileged. If this - * member is null, then the network is not restricted by app UID. If it's an empty list, then - * it means nobody can use it. - * As a special exception, the app managing this network (as identified by its UID stored in - * mOwnerUid) can always see this network. This is embodied by a special check in - * satisfiedByUids. That still does not mean the network necessarily applies - * to the app that manages it as determined by #appliesToUid. - *

    - * Please note that in principle a single app can be associated with multiple UIDs because - * each app will have a different UID when it's run as a different (macro-)user. A single - * macro user can only have a single active VPN app at any given time however. - *

    - * Also please be aware this class does not try to enforce any normalization on this. Callers - * can only alter the UIDs by setting them wholesale : this class does not provide any utility - * to add or remove individual UIDs or ranges. If callers have any normalization needs on - * their own (like requiring sortedness or no overlap) they need to enforce it - * themselves. Some of the internal methods also assume this is normalized as in no adjacent - * or overlapping ranges are present. - * - * @hide - */ - private ArraySet mUids = null; - - /** - * Convenience method to set the UIDs this network applies to to a single UID. - * @hide - */ - public @NonNull NetworkCapabilities setSingleUid(int uid) { - mUids = new ArraySet<>(1); - mUids.add(new UidRange(uid, uid)); - return this; - } - - /** - * Set the list of UIDs this network applies to. - * This makes a copy of the set so that callers can't modify it after the call. - * @hide - */ - public @NonNull NetworkCapabilities setUids(@Nullable Set> uids) { - mUids = UidRange.fromIntRanges(uids); - return this; - } - - /** - * Get the list of UIDs this network applies to. - * This returns a copy of the set so that callers can't modify the original object. - * - * @return the list of UIDs this network applies to. If {@code null}, then the network applies - * to all UIDs. - * @hide - */ - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - @SuppressLint("NullableCollection") - public @Nullable Set> getUids() { - return UidRange.toIntRanges(mUids); - } - - /** - * Get the list of UIDs this network applies to. - * This returns a copy of the set so that callers can't modify the original object. - * @hide - */ - public @Nullable Set getUidRanges() { - if (mUids == null) return null; - - return new ArraySet<>(mUids); - } - - /** - * Test whether this network applies to this UID. - * @hide - */ - public boolean appliesToUid(int uid) { - if (null == mUids) return true; - for (UidRange range : mUids) { - if (range.contains(uid)) { - return true; - } - } - return false; - } - - /** - * Tests if the set of UIDs that this network applies to is the same as the passed network. - *

    - * This test only checks whether equal range objects are in both sets. It will - * return false if the ranges are not exactly the same, even if the covered UIDs - * are for an equivalent result. - *

    - * Note that this method is not very optimized, which is fine as long as it's not used very - * often. - *

    - * nc is assumed nonnull. - * - * @hide - */ - @VisibleForTesting - public boolean equalsUids(@NonNull NetworkCapabilities nc) { - Set comparedUids = nc.mUids; - if (null == comparedUids) return null == mUids; - if (null == mUids) return false; - // Make a copy so it can be mutated to check that all ranges in mUids - // also are in uids. - final Set uids = new ArraySet<>(mUids); - for (UidRange range : comparedUids) { - if (!uids.contains(range)) { - return false; - } - uids.remove(range); - } - return uids.isEmpty(); - } - - /** - * Test whether the passed NetworkCapabilities satisfies the UIDs this capabilities require. - * - * This method is called on the NetworkCapabilities embedded in a request with the - * capabilities of an available network. It checks whether all the UIDs from this listen - * (representing the UIDs that must have access to the network) are satisfied by the UIDs - * in the passed nc (representing the UIDs that this network is available to). - *

    - * As a special exception, the UID that created the passed network (as represented by its - * mOwnerUid field) always satisfies a NetworkRequest requiring it (of LISTEN - * or REQUEST types alike), even if the network does not apply to it. That is so a VPN app - * can see its own network when it listens for it. - *

    - * nc is assumed nonnull. Else, NPE. - * @see #appliesToUid - * @hide - */ - public boolean satisfiedByUids(@NonNull NetworkCapabilities nc) { - if (null == nc.mUids || null == mUids) return true; // The network satisfies everything. - for (UidRange requiredRange : mUids) { - if (requiredRange.contains(nc.mOwnerUid)) return true; - if (!nc.appliesToUidRange(requiredRange)) { - return false; - } - } - return true; - } - - /** - * Returns whether this network applies to the passed ranges. - * This assumes that to apply, the passed range has to be entirely contained - * within one of the ranges this network applies to. If the ranges are not normalized, - * this method may return false even though all required UIDs are covered because no - * single range contained them all. - * @hide - */ - @VisibleForTesting - public boolean appliesToUidRange(@Nullable UidRange requiredRange) { - if (null == mUids) return true; - for (UidRange uidRange : mUids) { - if (uidRange.containsRange(requiredRange)) { - return true; - } - } - return false; - } - - /** - * Combine the UIDs this network currently applies to with the UIDs the passed - * NetworkCapabilities apply to. - * nc is assumed nonnull. - */ - private void combineUids(@NonNull NetworkCapabilities nc) { - if (null == nc.mUids || null == mUids) { - mUids = null; - return; - } - mUids.addAll(nc.mUids); - } - - - /** - * The SSID of the network, or null if not applicable or unknown. - *

    - * This is filled in by wifi code. - * @hide - */ - private String mSSID; - - /** - * Sets the SSID of this network. - * @hide - */ - public @NonNull NetworkCapabilities setSSID(@Nullable String ssid) { - mSSID = ssid; - return this; - } - - /** - * Gets the SSID of this network, or null if none or unknown. - * @hide - */ - @SystemApi - public @Nullable String getSsid() { - return mSSID; - } - - /** - * Tests if the SSID of this network is the same as the SSID of the passed network. - * @hide - */ - public boolean equalsSSID(@NonNull NetworkCapabilities nc) { - return Objects.equals(mSSID, nc.mSSID); - } - - /** - * Check if the SSID requirements of this object are matched by the passed object. - * @hide - */ - public boolean satisfiedBySSID(@NonNull NetworkCapabilities nc) { - return mSSID == null || mSSID.equals(nc.mSSID); - } - - /** - * Combine SSIDs of the capabilities. - *

    - * This is only legal if either the SSID of this object is null, or both SSIDs are - * equal. - * @hide - */ - private void combineSSIDs(@NonNull NetworkCapabilities nc) { - if (mSSID != null && !mSSID.equals(nc.mSSID)) { - throw new IllegalStateException("Can't combine two SSIDs"); - } - setSSID(nc.mSSID); - } - - /** - * Combine a set of Capabilities to this one. Useful for coming up with the complete set. - *

    - * Note that this method may break an invariant of having a particular capability in either - * wanted or forbidden lists but never in both. Requests that have the same capability in - * both lists will never be satisfied. - * @hide - */ - public void combineCapabilities(@NonNull NetworkCapabilities nc) { - combineNetCapabilities(nc); - combineTransportTypes(nc); - combineLinkBandwidths(nc); - combineSpecifiers(nc); - combineTransportInfos(nc); - combineSignalStrength(nc); - combineUids(nc); - combineSSIDs(nc); - combineRequestor(nc); - combineAdministratorUids(nc); - combineSubscriptionIds(nc); - } - - /** - * Check if our requirements are satisfied by the given {@code NetworkCapabilities}. - * - * @param nc the {@code NetworkCapabilities} that may or may not satisfy our requirements. - * @param onlyImmutable if {@code true}, do not consider mutable requirements such as link - * bandwidth, signal strength, or validation / captive portal status. - * - * @hide - */ - private boolean satisfiedByNetworkCapabilities(NetworkCapabilities nc, boolean onlyImmutable) { - return (nc != null - && satisfiedByNetCapabilities(nc, onlyImmutable) - && satisfiedByTransportTypes(nc) - && (onlyImmutable || satisfiedByLinkBandwidths(nc)) - && satisfiedBySpecifier(nc) - && (onlyImmutable || satisfiedBySignalStrength(nc)) - && (onlyImmutable || satisfiedByUids(nc)) - && (onlyImmutable || satisfiedBySSID(nc)) - && (onlyImmutable || satisfiedByRequestor(nc)) - && (onlyImmutable || satisfiedBySubscriptionIds(nc))); - } - - /** - * Check if our requirements are satisfied by the given {@code NetworkCapabilities}. - * - * @param nc the {@code NetworkCapabilities} that may or may not satisfy our requirements. - * - * @hide - */ - @SystemApi - public boolean satisfiedByNetworkCapabilities(@Nullable NetworkCapabilities nc) { - return satisfiedByNetworkCapabilities(nc, false); - } - - /** - * Check if our immutable requirements are satisfied by the given {@code NetworkCapabilities}. - * - * @param nc the {@code NetworkCapabilities} that may or may not satisfy our requirements. - * - * @hide - */ - public boolean satisfiedByImmutableNetworkCapabilities(@Nullable NetworkCapabilities nc) { - return satisfiedByNetworkCapabilities(nc, true); - } - - /** - * Checks that our immutable capabilities are the same as those of the given - * {@code NetworkCapabilities} and return a String describing any difference. - * The returned String is empty if there is no difference. - * - * @hide - */ - public String describeImmutableDifferences(@Nullable NetworkCapabilities that) { - if (that == null) { - return "other NetworkCapabilities was null"; - } - - StringJoiner joiner = new StringJoiner(", "); - - // Ignore NOT_METERED being added or removed as it is effectively dynamic. http://b/63326103 - // TODO: properly support NOT_METERED as a mutable and requestable capability. - final long mask = ~MUTABLE_CAPABILITIES & ~(1 << NET_CAPABILITY_NOT_METERED); - long oldImmutableCapabilities = this.mNetworkCapabilities & mask; - long newImmutableCapabilities = that.mNetworkCapabilities & mask; - if (oldImmutableCapabilities != newImmutableCapabilities) { - String before = capabilityNamesOf(NetworkCapabilitiesUtils.unpackBits( - oldImmutableCapabilities)); - String after = capabilityNamesOf(NetworkCapabilitiesUtils.unpackBits( - newImmutableCapabilities)); - joiner.add(String.format("immutable capabilities changed: %s -> %s", before, after)); - } - - if (!equalsSpecifier(that)) { - NetworkSpecifier before = this.getNetworkSpecifier(); - NetworkSpecifier after = that.getNetworkSpecifier(); - joiner.add(String.format("specifier changed: %s -> %s", before, after)); - } - - if (!equalsTransportTypes(that)) { - String before = transportNamesOf(this.getTransportTypes()); - String after = transportNamesOf(that.getTransportTypes()); - joiner.add(String.format("transports changed: %s -> %s", before, after)); - } - - return joiner.toString(); - } - - /** - * Checks that our requestable capabilities are the same as those of the given - * {@code NetworkCapabilities}. - * - * @hide - */ - public boolean equalRequestableCapabilities(@Nullable NetworkCapabilities nc) { - if (nc == null) return false; - return (equalsNetCapabilitiesRequestable(nc) - && equalsTransportTypes(nc) - && equalsSpecifier(nc)); - } - - @Override - public boolean equals(@Nullable Object obj) { - if (obj == null || (obj instanceof NetworkCapabilities == false)) return false; - NetworkCapabilities that = (NetworkCapabilities) obj; - return equalsNetCapabilities(that) - && equalsTransportTypes(that) - && equalsLinkBandwidths(that) - && equalsSignalStrength(that) - && equalsSpecifier(that) - && equalsTransportInfo(that) - && equalsUids(that) - && equalsSSID(that) - && equalsOwnerUid(that) - && equalsPrivateDnsBroken(that) - && equalsRequestor(that) - && equalsAdministratorUids(that) - && equalsSubscriptionIds(that); - } - - @Override - public int hashCode() { - return (int) (mNetworkCapabilities & 0xFFFFFFFF) - + ((int) (mNetworkCapabilities >> 32) * 3) - + ((int) (mForbiddenNetworkCapabilities & 0xFFFFFFFF) * 5) - + ((int) (mForbiddenNetworkCapabilities >> 32) * 7) - + ((int) (mTransportTypes & 0xFFFFFFFF) * 11) - + ((int) (mTransportTypes >> 32) * 13) - + mLinkUpBandwidthKbps * 17 - + mLinkDownBandwidthKbps * 19 - + Objects.hashCode(mNetworkSpecifier) * 23 - + mSignalStrength * 29 - + mOwnerUid * 31 - + Objects.hashCode(mUids) * 37 - + Objects.hashCode(mSSID) * 41 - + Objects.hashCode(mTransportInfo) * 43 - + Objects.hashCode(mPrivateDnsBroken) * 47 - + Objects.hashCode(mRequestorUid) * 53 - + Objects.hashCode(mRequestorPackageName) * 59 - + Arrays.hashCode(mAdministratorUids) * 61 - + Objects.hashCode(mSubIds) * 67; - } - - @Override - public int describeContents() { - return 0; - } - - private void writeParcelableArraySet(Parcel in, - @Nullable ArraySet val, int flags) { - final int size = (val != null) ? val.size() : -1; - in.writeInt(size); - for (int i = 0; i < size; i++) { - in.writeParcelable(val.valueAt(i), flags); - } - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(mNetworkCapabilities); - dest.writeLong(mForbiddenNetworkCapabilities); - dest.writeLong(mTransportTypes); - dest.writeInt(mLinkUpBandwidthKbps); - dest.writeInt(mLinkDownBandwidthKbps); - dest.writeParcelable((Parcelable) mNetworkSpecifier, flags); - dest.writeParcelable((Parcelable) mTransportInfo, flags); - dest.writeInt(mSignalStrength); - writeParcelableArraySet(dest, mUids, flags); - dest.writeString(mSSID); - dest.writeBoolean(mPrivateDnsBroken); - dest.writeIntArray(getAdministratorUids()); - dest.writeInt(mOwnerUid); - dest.writeInt(mRequestorUid); - dest.writeString(mRequestorPackageName); - dest.writeIntArray(CollectionUtils.toIntArray(mSubIds)); - } - - public static final @android.annotation.NonNull Creator CREATOR = - new Creator() { - @Override - public NetworkCapabilities createFromParcel(Parcel in) { - NetworkCapabilities netCap = new NetworkCapabilities(); - - netCap.mNetworkCapabilities = in.readLong(); - netCap.mForbiddenNetworkCapabilities = in.readLong(); - netCap.mTransportTypes = in.readLong(); - netCap.mLinkUpBandwidthKbps = in.readInt(); - netCap.mLinkDownBandwidthKbps = in.readInt(); - netCap.mNetworkSpecifier = in.readParcelable(null); - netCap.mTransportInfo = in.readParcelable(null); - netCap.mSignalStrength = in.readInt(); - netCap.mUids = readParcelableArraySet(in, null /* ClassLoader, null for default */); - netCap.mSSID = in.readString(); - netCap.mPrivateDnsBroken = in.readBoolean(); - netCap.setAdministratorUids(in.createIntArray()); - netCap.mOwnerUid = in.readInt(); - netCap.mRequestorUid = in.readInt(); - netCap.mRequestorPackageName = in.readString(); - netCap.mSubIds = new ArraySet<>(); - final int[] subIdInts = Objects.requireNonNull(in.createIntArray()); - for (int i = 0; i < subIdInts.length; i++) { - netCap.mSubIds.add(subIdInts[i]); - } - return netCap; - } - @Override - public NetworkCapabilities[] newArray(int size) { - return new NetworkCapabilities[size]; - } - - private @Nullable ArraySet readParcelableArraySet(Parcel in, - @Nullable ClassLoader loader) { - final int size = in.readInt(); - if (size < 0) { - return null; - } - final ArraySet result = new ArraySet<>(size); - for (int i = 0; i < size; i++) { - final T value = in.readParcelable(loader); - result.add(value); - } - return result; - } - }; - - @Override - public @NonNull String toString() { - final StringBuilder sb = new StringBuilder("["); - if (0 != mTransportTypes) { - sb.append(" Transports: "); - appendStringRepresentationOfBitMaskToStringBuilder(sb, mTransportTypes, - NetworkCapabilities::transportNameOf, "|"); - } - if (0 != mNetworkCapabilities) { - sb.append(" Capabilities: "); - appendStringRepresentationOfBitMaskToStringBuilder(sb, mNetworkCapabilities, - NetworkCapabilities::capabilityNameOf, "&"); - } - if (0 != mForbiddenNetworkCapabilities) { - sb.append(" Forbidden: "); - appendStringRepresentationOfBitMaskToStringBuilder(sb, mForbiddenNetworkCapabilities, - NetworkCapabilities::capabilityNameOf, "&"); - } - if (mLinkUpBandwidthKbps > 0) { - sb.append(" LinkUpBandwidth>=").append(mLinkUpBandwidthKbps).append("Kbps"); - } - if (mLinkDownBandwidthKbps > 0) { - sb.append(" LinkDnBandwidth>=").append(mLinkDownBandwidthKbps).append("Kbps"); - } - if (mNetworkSpecifier != null) { - sb.append(" Specifier: <").append(mNetworkSpecifier).append(">"); - } - if (mTransportInfo != null) { - sb.append(" TransportInfo: <").append(mTransportInfo).append(">"); - } - if (hasSignalStrength()) { - sb.append(" SignalStrength: ").append(mSignalStrength); - } - - if (null != mUids) { - if ((1 == mUids.size()) && (mUids.valueAt(0).count() == 1)) { - sb.append(" Uid: ").append(mUids.valueAt(0).start); - } else { - sb.append(" Uids: <").append(mUids).append(">"); - } - } - if (mOwnerUid != Process.INVALID_UID) { - sb.append(" OwnerUid: ").append(mOwnerUid); - } - - if (mAdministratorUids != null && mAdministratorUids.length != 0) { - sb.append(" AdminUids: ").append(Arrays.toString(mAdministratorUids)); - } - - if (mRequestorUid != Process.INVALID_UID) { - sb.append(" RequestorUid: ").append(mRequestorUid); - } - - if (mRequestorPackageName != null) { - sb.append(" RequestorPkg: ").append(mRequestorPackageName); - } - - if (null != mSSID) { - sb.append(" SSID: ").append(mSSID); - } - - if (mPrivateDnsBroken) { - sb.append(" PrivateDnsBroken"); - } - - if (!mSubIds.isEmpty()) { - sb.append(" SubscriptionIds: ").append(mSubIds); - } - - sb.append("]"); - return sb.toString(); - } - - - private interface NameOf { - String nameOf(int value); - } - - /** - * @hide - */ - public static void appendStringRepresentationOfBitMaskToStringBuilder(@NonNull StringBuilder sb, - long bitMask, @NonNull NameOf nameFetcher, @NonNull String separator) { - int bitPos = 0; - boolean firstElementAdded = false; - while (bitMask != 0) { - if ((bitMask & 1) != 0) { - if (firstElementAdded) { - sb.append(separator); - } else { - firstElementAdded = true; - } - sb.append(nameFetcher.nameOf(bitPos)); - } - bitMask >>= 1; - ++bitPos; - } - } - - /** - * @hide - */ - public static @NonNull String capabilityNamesOf(@Nullable @NetCapability int[] capabilities) { - StringJoiner joiner = new StringJoiner("|"); - if (capabilities != null) { - for (int c : capabilities) { - joiner.add(capabilityNameOf(c)); - } - } - return joiner.toString(); - } - - /** - * @hide - */ - public static @NonNull String capabilityNameOf(@NetCapability int capability) { - switch (capability) { - case NET_CAPABILITY_MMS: return "MMS"; - case NET_CAPABILITY_SUPL: return "SUPL"; - case NET_CAPABILITY_DUN: return "DUN"; - case NET_CAPABILITY_FOTA: return "FOTA"; - case NET_CAPABILITY_IMS: return "IMS"; - case NET_CAPABILITY_CBS: return "CBS"; - case NET_CAPABILITY_WIFI_P2P: return "WIFI_P2P"; - case NET_CAPABILITY_IA: return "IA"; - case NET_CAPABILITY_RCS: return "RCS"; - case NET_CAPABILITY_XCAP: return "XCAP"; - case NET_CAPABILITY_EIMS: return "EIMS"; - case NET_CAPABILITY_NOT_METERED: return "NOT_METERED"; - case NET_CAPABILITY_INTERNET: return "INTERNET"; - case NET_CAPABILITY_NOT_RESTRICTED: return "NOT_RESTRICTED"; - case NET_CAPABILITY_TRUSTED: return "TRUSTED"; - case NET_CAPABILITY_NOT_VPN: return "NOT_VPN"; - case NET_CAPABILITY_VALIDATED: return "VALIDATED"; - case NET_CAPABILITY_CAPTIVE_PORTAL: return "CAPTIVE_PORTAL"; - case NET_CAPABILITY_NOT_ROAMING: return "NOT_ROAMING"; - case NET_CAPABILITY_FOREGROUND: return "FOREGROUND"; - case NET_CAPABILITY_NOT_CONGESTED: return "NOT_CONGESTED"; - case NET_CAPABILITY_NOT_SUSPENDED: return "NOT_SUSPENDED"; - case NET_CAPABILITY_OEM_PAID: return "OEM_PAID"; - case NET_CAPABILITY_MCX: return "MCX"; - case NET_CAPABILITY_PARTIAL_CONNECTIVITY: return "PARTIAL_CONNECTIVITY"; - case NET_CAPABILITY_TEMPORARILY_NOT_METERED: return "TEMPORARILY_NOT_METERED"; - case NET_CAPABILITY_OEM_PRIVATE: return "OEM_PRIVATE"; - case NET_CAPABILITY_VEHICLE_INTERNAL: return "VEHICLE_INTERNAL"; - case NET_CAPABILITY_NOT_VCN_MANAGED: return "NOT_VCN_MANAGED"; - case NET_CAPABILITY_ENTERPRISE: return "ENTERPRISE"; - case NET_CAPABILITY_VSIM: return "VSIM"; - case NET_CAPABILITY_BIP: return "BIP"; - case NET_CAPABILITY_HEAD_UNIT: return "HEAD_UNIT"; - default: return Integer.toString(capability); - } - } - - /** - * @hide - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public static @NonNull String transportNamesOf(@Nullable @Transport int[] types) { - StringJoiner joiner = new StringJoiner("|"); - if (types != null) { - for (int t : types) { - joiner.add(transportNameOf(t)); - } - } - return joiner.toString(); - } - - /** - * @hide - */ - public static @NonNull String transportNameOf(@Transport int transport) { - if (!isValidTransport(transport)) { - return "UNKNOWN"; - } - return TRANSPORT_NAMES[transport]; - } - - private static void checkValidTransportType(@Transport int transport) { - if (!isValidTransport(transport)) { - throw new IllegalArgumentException("Invalid TransportType " + transport); - } - } - - private static boolean isValidCapability(@NetworkCapabilities.NetCapability int capability) { - return capability >= MIN_NET_CAPABILITY && capability <= MAX_NET_CAPABILITY; - } - - private static void checkValidCapability(@NetworkCapabilities.NetCapability int capability) { - if (!isValidCapability(capability)) { - throw new IllegalArgumentException("NetworkCapability " + capability + "out of range"); - } - } - - /** - * Check if this {@code NetworkCapability} instance is metered. - * - * @return {@code true} if {@code NET_CAPABILITY_NOT_METERED} is not set on this instance. - * @hide - */ - public boolean isMetered() { - return !hasCapability(NET_CAPABILITY_NOT_METERED); - } - - /** - * Check if private dns is broken. - * - * @return {@code true} if private DNS is broken on this network. - * @hide - */ - @SystemApi - public boolean isPrivateDnsBroken() { - return mPrivateDnsBroken; - } - - /** - * Set mPrivateDnsBroken to true when private dns is broken. - * - * @param broken the status of private DNS to be set. - * @hide - */ - public void setPrivateDnsBroken(boolean broken) { - mPrivateDnsBroken = broken; - } - - private boolean equalsPrivateDnsBroken(NetworkCapabilities nc) { - return mPrivateDnsBroken == nc.mPrivateDnsBroken; - } - - /** - * Set the UID of the app making the request. - * - * For instances of NetworkCapabilities representing a request, sets the - * UID of the app making the request. For a network created by the system, - * sets the UID of the only app whose requests can match this network. - * This can be set to {@link Process#INVALID_UID} if there is no such app, - * or if this instance of NetworkCapabilities is about to be sent to a - * party that should not learn about this. - * - * @param uid UID of the app. - * @hide - */ - public @NonNull NetworkCapabilities setRequestorUid(int uid) { - mRequestorUid = uid; - return this; - } - - /** - * Returns the UID of the app making the request. - * - * For a NetworkRequest being made by an app, contains the app's UID. For a network - * created by the system, contains the UID of the only app whose requests can match - * this network, or {@link Process#INVALID_UID} if none or if the - * caller does not have permission to learn about this. - * - * @return the uid of the app making the request. - * @hide - */ - public int getRequestorUid() { - return mRequestorUid; - } - - /** - * Set the package name of the app making the request. - * - * For instances of NetworkCapabilities representing a request, sets the - * package name of the app making the request. For a network created by the system, - * sets the package name of the only app whose requests can match this network. - * This can be set to null if there is no such app, or if this instance of - * NetworkCapabilities is about to be sent to a party that should not learn about this. - * - * @param packageName package name of the app. - * @hide - */ - public @NonNull NetworkCapabilities setRequestorPackageName(@NonNull String packageName) { - mRequestorPackageName = packageName; - return this; - } - - /** - * Returns the package name of the app making the request. - * - * For a NetworkRequest being made by an app, contains the app's package name. For a - * network created by the system, contains the package name of the only app whose - * requests can match this network, or null if none or if the caller does not have - * permission to learn about this. - * - * @return the package name of the app making the request. - * @hide - */ - @Nullable - public String getRequestorPackageName() { - return mRequestorPackageName; - } - - /** - * Set the uid and package name of the app causing this network to exist. - * - * {@see #setRequestorUid} and {@link #setRequestorPackageName} - * - * @param uid UID of the app. - * @param packageName package name of the app. - * @hide - */ - public @NonNull NetworkCapabilities setRequestorUidAndPackageName( - int uid, @NonNull String packageName) { - return setRequestorUid(uid).setRequestorPackageName(packageName); - } - - /** - * Test whether the passed NetworkCapabilities satisfies the requestor restrictions of this - * capabilities. - * - * This method is called on the NetworkCapabilities embedded in a request with the - * capabilities of an available network. If the available network, sets a specific - * requestor (by uid and optionally package name), then this will only match a request from the - * same app. If either of the capabilities have an unset uid or package name, then it matches - * everything. - *

    - * nc is assumed nonnull. Else, NPE. - */ - private boolean satisfiedByRequestor(NetworkCapabilities nc) { - // No uid set, matches everything. - if (mRequestorUid == Process.INVALID_UID || nc.mRequestorUid == Process.INVALID_UID) { - return true; - } - // uids don't match. - if (mRequestorUid != nc.mRequestorUid) return false; - // No package names set, matches everything - if (null == nc.mRequestorPackageName || null == mRequestorPackageName) return true; - // check for package name match. - return TextUtils.equals(mRequestorPackageName, nc.mRequestorPackageName); - } - - /** - * Combine requestor info of the capabilities. - *

    - * This is only legal if either the requestor info of this object is reset, or both info are - * equal. - * nc is assumed nonnull. - */ - private void combineRequestor(@NonNull NetworkCapabilities nc) { - if (mRequestorUid != Process.INVALID_UID && mRequestorUid != nc.mOwnerUid) { - throw new IllegalStateException("Can't combine two uids"); - } - if (mRequestorPackageName != null - && !mRequestorPackageName.equals(nc.mRequestorPackageName)) { - throw new IllegalStateException("Can't combine two package names"); - } - setRequestorUid(nc.mRequestorUid); - setRequestorPackageName(nc.mRequestorPackageName); - } - - private boolean equalsRequestor(NetworkCapabilities nc) { - return mRequestorUid == nc.mRequestorUid - && TextUtils.equals(mRequestorPackageName, nc.mRequestorPackageName); - } - - /** - * Set of the subscription IDs that identifies the network or request, empty if none. - */ - @NonNull - private ArraySet mSubIds = new ArraySet<>(); - - /** - * Sets the subscription ID set that associated to this network or request. - * - * @hide - */ - @NonNull - public NetworkCapabilities setSubscriptionIds(@NonNull Set subIds) { - mSubIds = new ArraySet(Objects.requireNonNull(subIds)); - return this; - } - - /** - * Gets the subscription ID set that associated to this network or request. - * - *

    Instances of NetworkCapabilities will only have this field populated by the system if the - * receiver holds the NETWORK_FACTORY permission. In all other cases, it will be the empty set. - * - * @return - * @hide - */ - @NonNull - @SystemApi - public Set getSubscriptionIds() { - return new ArraySet<>(mSubIds); - } - - /** - * Tests if the subscription ID set of this network is the same as that of the passed one. - */ - private boolean equalsSubscriptionIds(@NonNull NetworkCapabilities nc) { - return Objects.equals(mSubIds, nc.mSubIds); - } - - /** - * Check if the subscription ID set requirements of this object are matched by the passed one. - * If specified in the request, the passed one need to have at least one subId and at least - * one of them needs to be in the request set. - */ - private boolean satisfiedBySubscriptionIds(@NonNull NetworkCapabilities nc) { - if (mSubIds.isEmpty()) return true; - if (nc.mSubIds.isEmpty()) return false; - for (final Integer subId : nc.mSubIds) { - if (mSubIds.contains(subId)) return true; - } - return false; - } - - /** - * Combine subscription ID set of the capabilities. - * - *

    This is only legal if the subscription Ids are equal. - * - *

    If both subscription IDs are not equal, they belong to different subscription - * (or no subscription). In this case, it would not make sense to add them together. - */ - private void combineSubscriptionIds(@NonNull NetworkCapabilities nc) { - if (!Objects.equals(mSubIds, nc.mSubIds)) { - throw new IllegalStateException("Can't combine two subscription ID sets"); - } - } - - /** - * Returns a bitmask of all the applicable redactions (based on the permissions held by the - * receiving app) to be performed on this object. - * - * @return bitmask of redactions applicable on this instance. - * @hide - */ - public @RedactionType long getApplicableRedactions() { - // Currently, there are no fields redacted in NetworkCapabilities itself, so we just - // passthrough the redactions required by the embedded TransportInfo. If this changes - // in the future, modify this method. - if (mTransportInfo == null) { - return NetworkCapabilities.REDACT_NONE; - } - return mTransportInfo.getApplicableRedactions(); - } - - private NetworkCapabilities removeDefaultCapabilites() { - mNetworkCapabilities &= ~DEFAULT_CAPABILITIES; - return this; - } - - /** - * Builder class for NetworkCapabilities. - * - * This class is mainly for for {@link NetworkAgent} instances to use. Many fields in - * the built class require holding a signature permission to use - mostly - * {@link android.Manifest.permission.NETWORK_FACTORY}, but refer to the specific - * description of each setter. As this class lives entirely in app space it does not - * enforce these restrictions itself but the system server clears out the relevant - * fields when receiving a NetworkCapabilities object from a caller without the - * appropriate permission. - * - * Apps don't use this builder directly. Instead, they use {@link NetworkRequest} via - * its builder object. - * - * @hide - */ - @SystemApi - public static final class Builder { - private final NetworkCapabilities mCaps; - - /** - * Creates a new Builder to construct NetworkCapabilities objects. - */ - public Builder() { - mCaps = new NetworkCapabilities(); - } - - /** - * Creates a new Builder of NetworkCapabilities from an existing instance. - */ - public Builder(@NonNull final NetworkCapabilities nc) { - Objects.requireNonNull(nc); - mCaps = new NetworkCapabilities(nc); - } - - /** - * Creates a new Builder without the default capabilities. - */ - @NonNull - public static Builder withoutDefaultCapabilities() { - final NetworkCapabilities nc = new NetworkCapabilities(); - nc.removeDefaultCapabilites(); - return new Builder(nc); - } - - /** - * Adds the given transport type. - * - * Multiple transports may be added. Note that when searching for a network to satisfy a - * request, satisfying any of the transports listed in the request will satisfy the request. - * For example {@code TRANSPORT_WIFI} and {@code TRANSPORT_ETHERNET} added to a - * {@code NetworkCapabilities} would cause either a Wi-Fi network or an Ethernet network - * to be selected. This is logically different than - * {@code NetworkCapabilities.NET_CAPABILITY_*}. Also note that multiple networks with the - * same transport type may be active concurrently. - * - * @param transportType the transport type to be added or removed. - * @return this builder - */ - @NonNull - public Builder addTransportType(@Transport int transportType) { - checkValidTransportType(transportType); - mCaps.addTransportType(transportType); - return this; - } - - /** - * Removes the given transport type. - * - * {@see #addTransportType}. - * - * @param transportType the transport type to be added or removed. - * @return this builder - */ - @NonNull - public Builder removeTransportType(@Transport int transportType) { - checkValidTransportType(transportType); - mCaps.removeTransportType(transportType); - return this; - } - - /** - * Adds the given capability. - * - * @param capability the capability - * @return this builder - */ - @NonNull - public Builder addCapability(@NetCapability final int capability) { - mCaps.setCapability(capability, true); - return this; - } - - /** - * Removes the given capability. - * - * @param capability the capability - * @return this builder - */ - @NonNull - public Builder removeCapability(@NetCapability final int capability) { - mCaps.setCapability(capability, false); - return this; - } - - /** - * Sets the owner UID. - * - * The default value is {@link Process#INVALID_UID}. Pass this value to reset. - * - * Note: for security the system will clear out this field when received from a - * non-privileged source. - * - * @param ownerUid the owner UID - * @return this builder - */ - @NonNull - @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) - public Builder setOwnerUid(final int ownerUid) { - mCaps.setOwnerUid(ownerUid); - return this; - } - - /** - * Sets the list of UIDs that are administrators of this network. - * - *

    UIDs included in administratorUids gain administrator privileges over this - * Network. Examples of UIDs that should be included in administratorUids are: - *

      - *
    • Carrier apps with privileges for the relevant subscription - *
    • Active VPN apps - *
    • Other application groups with a particular Network-related role - *
    - * - *

    In general, user-supplied networks (such as WiFi networks) do not have - * administrators. - * - *

    An app is granted owner privileges over Networks that it supplies. The owner - * UID MUST always be included in administratorUids. - * - * The default value is the empty array. Pass an empty array to reset. - * - * Note: for security the system will clear out this field when received from a - * non-privileged source, such as an app using reflection to call this or - * mutate the member in the built object. - * - * @param administratorUids the UIDs to be set as administrators of this Network. - * @return this builder - */ - @NonNull - @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) - public Builder setAdministratorUids(@NonNull final int[] administratorUids) { - Objects.requireNonNull(administratorUids); - mCaps.setAdministratorUids(administratorUids); - return this; - } - - /** - * Sets the upstream bandwidth of the link. - * - * Sets the upstream bandwidth for this network in Kbps. This always only refers to - * the estimated first hop transport bandwidth. - *

    - * Note that when used to request a network, this specifies the minimum acceptable. - * When received as the state of an existing network this specifies the typical - * first hop bandwidth expected. This is never measured, but rather is inferred - * from technology type and other link parameters. It could be used to differentiate - * between very slow 1xRTT cellular links and other faster networks or even between - * 802.11b vs 802.11AC wifi technologies. It should not be used to differentiate between - * fast backhauls and slow backhauls. - * - * @param upKbps the estimated first hop upstream (device to network) bandwidth. - * @return this builder - */ - @NonNull - public Builder setLinkUpstreamBandwidthKbps(final int upKbps) { - mCaps.setLinkUpstreamBandwidthKbps(upKbps); - return this; - } - - /** - * Sets the downstream bandwidth for this network in Kbps. This always only refers to - * the estimated first hop transport bandwidth. - *

    - * Note that when used to request a network, this specifies the minimum acceptable. - * When received as the state of an existing network this specifies the typical - * first hop bandwidth expected. This is never measured, but rather is inferred - * from technology type and other link parameters. It could be used to differentiate - * between very slow 1xRTT cellular links and other faster networks or even between - * 802.11b vs 802.11AC wifi technologies. It should not be used to differentiate between - * fast backhauls and slow backhauls. - * - * @param downKbps the estimated first hop downstream (network to device) bandwidth. - * @return this builder - */ - @NonNull - public Builder setLinkDownstreamBandwidthKbps(final int downKbps) { - mCaps.setLinkDownstreamBandwidthKbps(downKbps); - return this; - } - - /** - * Sets the optional bearer specific network specifier. - * This has no meaning if a single transport is also not specified, so calling - * this without a single transport set will generate an exception, as will - * subsequently adding or removing transports after this is set. - *

    - * - * @param specifier a concrete, parcelable framework class that extends NetworkSpecifier, - * or null to clear it. - * @return this builder - */ - @NonNull - public Builder setNetworkSpecifier(@Nullable final NetworkSpecifier specifier) { - mCaps.setNetworkSpecifier(specifier); - return this; - } - - /** - * Sets the optional transport specific information. - * - * @param info A concrete, parcelable framework class that extends {@link TransportInfo}, - * or null to clear it. - * @return this builder - */ - @NonNull - public Builder setTransportInfo(@Nullable final TransportInfo info) { - mCaps.setTransportInfo(info); - return this; - } - - /** - * Sets the signal strength. This is a signed integer, with higher values indicating a - * stronger signal. The exact units are bearer-dependent. For example, Wi-Fi uses the - * same RSSI units reported by wifi code. - *

    - * Note that when used to register a network callback, this specifies the minimum - * acceptable signal strength. When received as the state of an existing network it - * specifies the current value. A value of code SIGNAL_STRENGTH_UNSPECIFIED} means - * no value when received and has no effect when requesting a callback. - * - * Note: for security the system will throw if it receives a NetworkRequest where - * the underlying NetworkCapabilities has this member set from a source that does - * not hold the {@link android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP} - * permission. Apps with this permission can use this indirectly through - * {@link android.net.NetworkRequest}. - * - * @param signalStrength the bearer-specific signal strength. - * @return this builder - */ - @NonNull - @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) - public Builder setSignalStrength(final int signalStrength) { - mCaps.setSignalStrength(signalStrength); - return this; - } - - /** - * Sets the SSID of this network. - * - * Note: for security the system will clear out this field when received from a - * non-privileged source, like an app using reflection to set this. - * - * @param ssid the SSID, or null to clear it. - * @return this builder - */ - @NonNull - @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) - public Builder setSsid(@Nullable final String ssid) { - mCaps.setSSID(ssid); - return this; - } - - /** - * Set the uid of the app causing this network to exist. - * - * Note: for security the system will clear out this field when received from a - * non-privileged source. - * - * @param uid UID of the app. - * @return this builder - */ - @NonNull - @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) - public Builder setRequestorUid(final int uid) { - mCaps.setRequestorUid(uid); - return this; - } - - /** - * Set the package name of the app causing this network to exist. - * - * Note: for security the system will clear out this field when received from a - * non-privileged source. - * - * @param packageName package name of the app, or null to clear it. - * @return this builder - */ - @NonNull - @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) - public Builder setRequestorPackageName(@Nullable final String packageName) { - mCaps.setRequestorPackageName(packageName); - return this; - } - - /** - * Set the subscription ID set. - * - *

    SubIds are populated in NetworkCapability instances from the system only for callers - * that hold the NETWORK_FACTORY permission. Similarly, the system will reject any - * NetworkRequests filed with a non-empty set of subIds unless the caller holds the - * NETWORK_FACTORY permission. - * - * @param subIds a set that represent the subscription IDs. Empty if clean up. - * @return this builder. - * @hide - */ - @NonNull - @SystemApi - public Builder setSubscriptionIds(@NonNull final Set subIds) { - mCaps.setSubscriptionIds(subIds); - return this; - } - - /** - * Set the list of UIDs this network applies to. - * - * @param uids the list of UIDs this network applies to, or {@code null} if this network - * applies to all UIDs. - * @return this builder - * @hide - */ - @NonNull - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public Builder setUids(@Nullable Set> uids) { - mCaps.setUids(uids); - return this; - } - - /** - * Builds the instance of the capabilities. - * - * @return the built instance of NetworkCapabilities. - */ - @NonNull - public NetworkCapabilities build() { - if (mCaps.getOwnerUid() != Process.INVALID_UID) { - if (!CollectionUtils.contains(mCaps.getAdministratorUids(), mCaps.getOwnerUid())) { - throw new IllegalStateException("The owner UID must be included in " - + " administrator UIDs."); - } - } - return new NetworkCapabilities(mCaps); - } - } -} diff --git a/packages/Connectivity/framework/src/android/net/NetworkConfig.java b/packages/Connectivity/framework/src/android/net/NetworkConfig.java deleted file mode 100644 index 32a2cda00370a..0000000000000 --- a/packages/Connectivity/framework/src/android/net/NetworkConfig.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import java.util.Locale; - -/** - * Describes the buildtime configuration of a network. - * Holds settings read from resources. - * @hide - */ -public class NetworkConfig { - /** - * Human readable string - */ - public String name; - - /** - * Type from ConnectivityManager - */ - public int type; - - /** - * the radio number from radio attributes config - */ - public int radio; - - /** - * higher number == higher priority when turning off connections - */ - public int priority; - - /** - * indicates the boot time dependencyMet setting - */ - public boolean dependencyMet; - - /** - * indicates the default restoral timer in seconds - * if the network is used as a special network feature - * -1 indicates no restoration of default - */ - public int restoreTime; - - /** - * input string from config.xml resource. Uses the form: - * [Connection name],[ConnectivityManager connection type], - * [associated radio-type],[priority],[dependencyMet] - */ - public NetworkConfig(String init) { - String fragments[] = init.split(","); - name = fragments[0].trim().toLowerCase(Locale.ROOT); - type = Integer.parseInt(fragments[1]); - radio = Integer.parseInt(fragments[2]); - priority = Integer.parseInt(fragments[3]); - restoreTime = Integer.parseInt(fragments[4]); - dependencyMet = Boolean.parseBoolean(fragments[5]); - } - - /** - * Indicates if this network is supposed to be default-routable - */ - public boolean isDefault() { - return (type == radio); - } -} diff --git a/packages/Connectivity/framework/src/android/net/NetworkInfo.java b/packages/Connectivity/framework/src/android/net/NetworkInfo.java deleted file mode 100644 index bb23494593319..0000000000000 --- a/packages/Connectivity/framework/src/android/net/NetworkInfo.java +++ /dev/null @@ -1,625 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.compat.annotation.UnsupportedAppUsage; -import android.os.Parcel; -import android.os.Parcelable; -import android.text.TextUtils; - -import com.android.internal.annotations.VisibleForTesting; - -import java.util.EnumMap; - -/** - * Describes the status of a network interface. - *

    Use {@link ConnectivityManager#getActiveNetworkInfo()} to get an instance that represents - * the current network connection. - * - * @deprecated Callers should instead use the {@link ConnectivityManager.NetworkCallback} API to - * learn about connectivity changes, or switch to use - * {@link ConnectivityManager#getNetworkCapabilities} or - * {@link ConnectivityManager#getLinkProperties} to get information synchronously. Keep - * in mind that while callbacks are guaranteed to be called for every event in order, - * synchronous calls have no such constraints, and as such it is unadvisable to use the - * synchronous methods inside the callbacks as they will often not offer a view of - * networking that is consistent (that is: they may return a past or a future state with - * respect to the event being processed by the callback). Instead, callers are advised - * to only use the arguments of the callbacks, possibly memorizing the specific bits of - * information they need to keep from one callback to another. - */ -@Deprecated -public class NetworkInfo implements Parcelable { - - /** - * Coarse-grained network state. This is probably what most applications should - * use, rather than {@link android.net.NetworkInfo.DetailedState DetailedState}. - * The mapping between the two is as follows: - *

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Detailed stateCoarse-grained state
    IDLEDISCONNECTED
    SCANNINGDISCONNECTED
    CONNECTINGCONNECTING
    AUTHENTICATINGCONNECTING
    OBTAINING_IPADDRCONNECTING
    VERIFYING_POOR_LINKCONNECTING
    CAPTIVE_PORTAL_CHECKCONNECTING
    CONNECTEDCONNECTED
    SUSPENDEDSUSPENDED
    DISCONNECTINGDISCONNECTING
    DISCONNECTEDDISCONNECTED
    FAILEDDISCONNECTED
    BLOCKEDDISCONNECTED
    - * - * @deprecated See {@link NetworkInfo}. - */ - @Deprecated - public enum State { - CONNECTING, CONNECTED, SUSPENDED, DISCONNECTING, DISCONNECTED, UNKNOWN - } - - /** - * The fine-grained state of a network connection. This level of detail - * is probably of interest to few applications. Most should use - * {@link android.net.NetworkInfo.State State} instead. - * - * @deprecated See {@link NetworkInfo}. - */ - @Deprecated - public enum DetailedState { - /** Ready to start data connection setup. */ - IDLE, - /** Searching for an available access point. */ - SCANNING, - /** Currently setting up data connection. */ - CONNECTING, - /** Network link established, performing authentication. */ - AUTHENTICATING, - /** Awaiting response from DHCP server in order to assign IP address information. */ - OBTAINING_IPADDR, - /** IP traffic should be available. */ - CONNECTED, - /** IP traffic is suspended */ - SUSPENDED, - /** Currently tearing down data connection. */ - DISCONNECTING, - /** IP traffic not available. */ - DISCONNECTED, - /** Attempt to connect failed. */ - FAILED, - /** Access to this network is blocked. */ - BLOCKED, - /** Link has poor connectivity. */ - VERIFYING_POOR_LINK, - /** Checking if network is a captive portal */ - CAPTIVE_PORTAL_CHECK - } - - /** - * This is the map described in the Javadoc comment above. The positions - * of the elements of the array must correspond to the ordinal values - * of DetailedState. - */ - private static final EnumMap stateMap = - new EnumMap(DetailedState.class); - - static { - stateMap.put(DetailedState.IDLE, State.DISCONNECTED); - stateMap.put(DetailedState.SCANNING, State.DISCONNECTED); - stateMap.put(DetailedState.CONNECTING, State.CONNECTING); - stateMap.put(DetailedState.AUTHENTICATING, State.CONNECTING); - stateMap.put(DetailedState.OBTAINING_IPADDR, State.CONNECTING); - stateMap.put(DetailedState.VERIFYING_POOR_LINK, State.CONNECTING); - stateMap.put(DetailedState.CAPTIVE_PORTAL_CHECK, State.CONNECTING); - stateMap.put(DetailedState.CONNECTED, State.CONNECTED); - stateMap.put(DetailedState.SUSPENDED, State.SUSPENDED); - stateMap.put(DetailedState.DISCONNECTING, State.DISCONNECTING); - stateMap.put(DetailedState.DISCONNECTED, State.DISCONNECTED); - stateMap.put(DetailedState.FAILED, State.DISCONNECTED); - stateMap.put(DetailedState.BLOCKED, State.DISCONNECTED); - } - - private int mNetworkType; - private int mSubtype; - private String mTypeName; - private String mSubtypeName; - @NonNull - private State mState; - @NonNull - private DetailedState mDetailedState; - private String mReason; - private String mExtraInfo; - private boolean mIsFailover; - private boolean mIsAvailable; - private boolean mIsRoaming; - - /** - * Create a new instance of NetworkInfo. - * - * This may be useful for apps to write unit tests. - * - * @param type the legacy type of the network, as one of the ConnectivityManager.TYPE_* - * constants. - * @param subtype the subtype if applicable, as one of the TelephonyManager.NETWORK_TYPE_* - * constants. - * @param typeName a human-readable string for the network type, or an empty string or null. - * @param subtypeName a human-readable string for the subtype, or an empty string or null. - */ - public NetworkInfo(int type, int subtype, - @Nullable String typeName, @Nullable String subtypeName) { - if (!ConnectivityManager.isNetworkTypeValid(type) - && type != ConnectivityManager.TYPE_NONE) { - throw new IllegalArgumentException("Invalid network type: " + type); - } - mNetworkType = type; - mSubtype = subtype; - mTypeName = typeName; - mSubtypeName = subtypeName; - setDetailedState(DetailedState.IDLE, null, null); - mState = State.UNKNOWN; - } - - /** {@hide} */ - @UnsupportedAppUsage - public NetworkInfo(NetworkInfo source) { - if (source != null) { - synchronized (source) { - mNetworkType = source.mNetworkType; - mSubtype = source.mSubtype; - mTypeName = source.mTypeName; - mSubtypeName = source.mSubtypeName; - mState = source.mState; - mDetailedState = source.mDetailedState; - mReason = source.mReason; - mExtraInfo = source.mExtraInfo; - mIsFailover = source.mIsFailover; - mIsAvailable = source.mIsAvailable; - mIsRoaming = source.mIsRoaming; - } - } - } - - /** - * Reports the type of network to which the - * info in this {@code NetworkInfo} pertains. - * @return one of {@link ConnectivityManager#TYPE_MOBILE}, {@link - * ConnectivityManager#TYPE_WIFI}, {@link ConnectivityManager#TYPE_WIMAX}, {@link - * ConnectivityManager#TYPE_ETHERNET}, {@link ConnectivityManager#TYPE_BLUETOOTH}, or other - * types defined by {@link ConnectivityManager}. - * @deprecated Callers should switch to checking {@link NetworkCapabilities#hasTransport} - * instead with one of the NetworkCapabilities#TRANSPORT_* constants : - * {@link #getType} and {@link #getTypeName} cannot account for networks using - * multiple transports. Note that generally apps should not care about transport; - * {@link NetworkCapabilities#NET_CAPABILITY_NOT_METERED} and - * {@link NetworkCapabilities#getLinkDownstreamBandwidthKbps} are calls that - * apps concerned with meteredness or bandwidth should be looking at, as they - * offer this information with much better accuracy. - */ - @Deprecated - public int getType() { - synchronized (this) { - return mNetworkType; - } - } - - /** - * @deprecated Use {@link NetworkCapabilities} instead - * @hide - */ - @Deprecated - public void setType(int type) { - synchronized (this) { - mNetworkType = type; - } - } - - /** - * Return a network-type-specific integer describing the subtype - * of the network. - * @return the network subtype - * @deprecated Use {@link android.telephony.TelephonyManager#getDataNetworkType} instead. - */ - @Deprecated - public int getSubtype() { - synchronized (this) { - return mSubtype; - } - } - - /** - * @hide - */ - @UnsupportedAppUsage - public void setSubtype(int subtype, String subtypeName) { - synchronized (this) { - mSubtype = subtype; - mSubtypeName = subtypeName; - } - } - - /** - * Return a human-readable name describe the type of the network, - * for example "WIFI" or "MOBILE". - * @return the name of the network type - * @deprecated Callers should switch to checking {@link NetworkCapabilities#hasTransport} - * instead with one of the NetworkCapabilities#TRANSPORT_* constants : - * {@link #getType} and {@link #getTypeName} cannot account for networks using - * multiple transports. Note that generally apps should not care about transport; - * {@link NetworkCapabilities#NET_CAPABILITY_NOT_METERED} and - * {@link NetworkCapabilities#getLinkDownstreamBandwidthKbps} are calls that - * apps concerned with meteredness or bandwidth should be looking at, as they - * offer this information with much better accuracy. - */ - @Deprecated - public String getTypeName() { - synchronized (this) { - return mTypeName; - } - } - - /** - * Return a human-readable name describing the subtype of the network. - * @return the name of the network subtype - * @deprecated Use {@link android.telephony.TelephonyManager#getDataNetworkType} instead. - */ - @Deprecated - public String getSubtypeName() { - synchronized (this) { - return mSubtypeName; - } - } - - /** - * Indicates whether network connectivity exists or is in the process - * of being established. This is good for applications that need to - * do anything related to the network other than read or write data. - * For the latter, call {@link #isConnected()} instead, which guarantees - * that the network is fully usable. - * @return {@code true} if network connectivity exists or is in the process - * of being established, {@code false} otherwise. - * @deprecated Apps should instead use the - * {@link android.net.ConnectivityManager.NetworkCallback} API to - * learn about connectivity changes. - * {@link ConnectivityManager#registerDefaultNetworkCallback} and - * {@link ConnectivityManager#registerNetworkCallback}. These will - * give a more accurate picture of the connectivity state of - * the device and let apps react more easily and quickly to changes. - */ - @Deprecated - public boolean isConnectedOrConnecting() { - synchronized (this) { - return mState == State.CONNECTED || mState == State.CONNECTING; - } - } - - /** - * Indicates whether network connectivity exists and it is possible to establish - * connections and pass data. - *

    Always call this before attempting to perform data transactions. - * @return {@code true} if network connectivity exists, {@code false} otherwise. - * @deprecated Apps should instead use the - * {@link android.net.ConnectivityManager.NetworkCallback} API to - * learn about connectivity changes. See - * {@link ConnectivityManager#registerDefaultNetworkCallback} and - * {@link ConnectivityManager#registerNetworkCallback}. These will - * give a more accurate picture of the connectivity state of - * the device and let apps react more easily and quickly to changes. - */ - @Deprecated - public boolean isConnected() { - synchronized (this) { - return mState == State.CONNECTED; - } - } - - /** - * Indicates whether network connectivity is possible. A network is unavailable - * when a persistent or semi-persistent condition prevents the possibility - * of connecting to that network. Examples include - *

      - *
    • The device is out of the coverage area for any network of this type.
    • - *
    • The device is on a network other than the home network (i.e., roaming), and - * data roaming has been disabled.
    • - *
    • The device's radio is turned off, e.g., because airplane mode is enabled.
    • - *
    - * Since Android L, this always returns {@code true}, because the system only - * returns info for available networks. - * @return {@code true} if the network is available, {@code false} otherwise - * @deprecated Apps should instead use the - * {@link android.net.ConnectivityManager.NetworkCallback} API to - * learn about connectivity changes. - * {@link ConnectivityManager#registerDefaultNetworkCallback} and - * {@link ConnectivityManager#registerNetworkCallback}. These will - * give a more accurate picture of the connectivity state of - * the device and let apps react more easily and quickly to changes. - */ - @Deprecated - public boolean isAvailable() { - synchronized (this) { - return mIsAvailable; - } - } - - /** - * Sets if the network is available, ie, if the connectivity is possible. - * @param isAvailable the new availability value. - * @deprecated Use {@link NetworkCapabilities} instead - * - * @hide - */ - @Deprecated - @UnsupportedAppUsage - public void setIsAvailable(boolean isAvailable) { - synchronized (this) { - mIsAvailable = isAvailable; - } - } - - /** - * Indicates whether the current attempt to connect to the network - * resulted from the ConnectivityManager trying to fail over to this - * network following a disconnect from another network. - * @return {@code true} if this is a failover attempt, {@code false} - * otherwise. - * @deprecated This field is not populated in recent Android releases, - * and does not make a lot of sense in a multi-network world. - */ - @Deprecated - public boolean isFailover() { - synchronized (this) { - return mIsFailover; - } - } - - /** - * Set the failover boolean. - * @param isFailover {@code true} to mark the current connection attempt - * as a failover. - * @deprecated This hasn't been set in any recent Android release. - * @hide - */ - @Deprecated - @UnsupportedAppUsage - public void setFailover(boolean isFailover) { - synchronized (this) { - mIsFailover = isFailover; - } - } - - /** - * Indicates whether the device is currently roaming on this network. When - * {@code true}, it suggests that use of data on this network may incur - * extra costs. - * - * @return {@code true} if roaming is in effect, {@code false} otherwise. - * @deprecated Callers should switch to checking - * {@link NetworkCapabilities#NET_CAPABILITY_NOT_ROAMING} - * instead, since that handles more complex situations, such as - * VPNs. - */ - @Deprecated - public boolean isRoaming() { - synchronized (this) { - return mIsRoaming; - } - } - - /** - * @deprecated Use {@link NetworkCapabilities#NET_CAPABILITY_NOT_ROAMING} instead. - * {@hide} - */ - @VisibleForTesting - @Deprecated - @UnsupportedAppUsage - public void setRoaming(boolean isRoaming) { - synchronized (this) { - mIsRoaming = isRoaming; - } - } - - /** - * Reports the current coarse-grained state of the network. - * @return the coarse-grained state - * @deprecated Apps should instead use the - * {@link android.net.ConnectivityManager.NetworkCallback} API to - * learn about connectivity changes. - * {@link ConnectivityManager#registerDefaultNetworkCallback} and - * {@link ConnectivityManager#registerNetworkCallback}. These will - * give a more accurate picture of the connectivity state of - * the device and let apps react more easily and quickly to changes. - */ - @Deprecated - public State getState() { - synchronized (this) { - return mState; - } - } - - /** - * Reports the current fine-grained state of the network. - * @return the fine-grained state - * @deprecated Apps should instead use the - * {@link android.net.ConnectivityManager.NetworkCallback} API to - * learn about connectivity changes. See - * {@link ConnectivityManager#registerDefaultNetworkCallback} and - * {@link ConnectivityManager#registerNetworkCallback}. These will - * give a more accurate picture of the connectivity state of - * the device and let apps react more easily and quickly to changes. - */ - @Deprecated - public @NonNull DetailedState getDetailedState() { - synchronized (this) { - return mDetailedState; - } - } - - /** - * Sets the fine-grained state of the network. - * - * This is only useful for testing. - * - * @param detailedState the {@link DetailedState}. - * @param reason a {@code String} indicating the reason for the state change, - * if one was supplied. May be {@code null}. - * @param extraInfo an optional {@code String} providing addditional network state - * information passed up from the lower networking layers. - * @deprecated Use {@link NetworkCapabilities} instead. - */ - @Deprecated - public void setDetailedState(@NonNull DetailedState detailedState, @Nullable String reason, - @Nullable String extraInfo) { - synchronized (this) { - this.mDetailedState = detailedState; - this.mState = stateMap.get(detailedState); - this.mReason = reason; - this.mExtraInfo = extraInfo; - } - } - - /** - * Set the extraInfo field. - * @param extraInfo an optional {@code String} providing addditional network state - * information passed up from the lower networking layers. - * @deprecated See {@link NetworkInfo#getExtraInfo}. - * @hide - */ - @Deprecated - public void setExtraInfo(String extraInfo) { - synchronized (this) { - this.mExtraInfo = extraInfo; - } - } - - /** - * Report the reason an attempt to establish connectivity failed, - * if one is available. - * @return the reason for failure, or null if not available - * @deprecated This method does not have a consistent contract that could make it useful - * to callers. - */ - public String getReason() { - synchronized (this) { - return mReason; - } - } - - /** - * Report the extra information about the network state, if any was - * provided by the lower networking layers. - * @return the extra information, or null if not available - * @deprecated Use other services e.g. WifiManager to get additional information passed up from - * the lower networking layers. - */ - @Deprecated - public String getExtraInfo() { - synchronized (this) { - return mExtraInfo; - } - } - - @Override - public String toString() { - synchronized (this) { - final StringBuilder builder = new StringBuilder("["); - builder.append("type: ").append(getTypeName()).append("[").append(getSubtypeName()). - append("], state: ").append(mState).append("/").append(mDetailedState). - append(", reason: ").append(mReason == null ? "(unspecified)" : mReason). - append(", extra: ").append(mExtraInfo == null ? "(none)" : mExtraInfo). - append(", failover: ").append(mIsFailover). - append(", available: ").append(mIsAvailable). - append(", roaming: ").append(mIsRoaming). - append("]"); - return builder.toString(); - } - } - - /** - * Returns a brief summary string suitable for debugging. - * @hide - */ - public String toShortString() { - synchronized (this) { - final StringBuilder builder = new StringBuilder(); - builder.append(getTypeName()); - - final String subtype = getSubtypeName(); - if (!TextUtils.isEmpty(subtype)) { - builder.append("[").append(subtype).append("]"); - } - - builder.append(" "); - builder.append(mDetailedState); - if (mIsRoaming) { - builder.append(" ROAMING"); - } - if (mExtraInfo != null) { - builder.append(" extra: ").append(mExtraInfo); - } - return builder.toString(); - } - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - synchronized (this) { - dest.writeInt(mNetworkType); - dest.writeInt(mSubtype); - dest.writeString(mTypeName); - dest.writeString(mSubtypeName); - dest.writeString(mState.name()); - dest.writeString(mDetailedState.name()); - dest.writeInt(mIsFailover ? 1 : 0); - dest.writeInt(mIsAvailable ? 1 : 0); - dest.writeInt(mIsRoaming ? 1 : 0); - dest.writeString(mReason); - dest.writeString(mExtraInfo); - } - } - - public static final @android.annotation.NonNull Creator CREATOR = new Creator() { - @Override - public NetworkInfo createFromParcel(Parcel in) { - int netType = in.readInt(); - int subtype = in.readInt(); - String typeName = in.readString(); - String subtypeName = in.readString(); - NetworkInfo netInfo = new NetworkInfo(netType, subtype, typeName, subtypeName); - netInfo.mState = State.valueOf(in.readString()); - netInfo.mDetailedState = DetailedState.valueOf(in.readString()); - netInfo.mIsFailover = in.readInt() != 0; - netInfo.mIsAvailable = in.readInt() != 0; - netInfo.mIsRoaming = in.readInt() != 0; - netInfo.mReason = in.readString(); - netInfo.mExtraInfo = in.readString(); - return netInfo; - } - - @Override - public NetworkInfo[] newArray(int size) { - return new NetworkInfo[size]; - } - }; -} diff --git a/packages/Connectivity/framework/src/android/net/NetworkProvider.java b/packages/Connectivity/framework/src/android/net/NetworkProvider.java deleted file mode 100644 index 0665af58498c0..0000000000000 --- a/packages/Connectivity/framework/src/android/net/NetworkProvider.java +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.IntRange; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.RequiresPermission; -import android.annotation.SystemApi; -import android.content.Context; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.os.Messenger; -import android.util.Log; - -import com.android.internal.annotations.GuardedBy; - -import java.util.ArrayList; -import java.util.concurrent.Executor; - -/** - * Base class for network providers such as telephony or Wi-Fi. NetworkProviders connect the device - * to networks and makes them available to the core network stack by creating - * {@link NetworkAgent}s. The networks can then provide connectivity to apps and can be interacted - * with via networking APIs such as {@link ConnectivityManager}. - * - * Subclasses should implement {@link #onNetworkRequested} and {@link #onNetworkRequestWithdrawn} - * to receive {@link NetworkRequest}s sent by the system and by apps. A network that is not the - * best (highest-scoring) network for any request is generally not used by the system, and torn - * down. - * - * @hide - */ -@SystemApi -public class NetworkProvider { - /** - * {@code providerId} value that indicates the absence of a provider. It is the providerId of - * any NetworkProvider that is not currently registered, and of any NetworkRequest that is not - * currently being satisfied by a network. - */ - public static final int ID_NONE = -1; - - /** - * The first providerId value that will be allocated. - * @hide only used by ConnectivityService. - */ - public static final int FIRST_PROVIDER_ID = 1; - - /** @hide only used by ConnectivityService */ - public static final int CMD_REQUEST_NETWORK = 1; - /** @hide only used by ConnectivityService */ - public static final int CMD_CANCEL_REQUEST = 2; - - private final Messenger mMessenger; - private final String mName; - private final Context mContext; - - private int mProviderId = ID_NONE; - - /** - * Constructs a new NetworkProvider. - * - * @param looper the Looper on which to run {@link #onNetworkRequested} and - * {@link #onNetworkRequestWithdrawn}. - * @param name the name of the listener, used only for debugging. - * - * @hide - */ - @SystemApi - public NetworkProvider(@NonNull Context context, @NonNull Looper looper, @NonNull String name) { - // TODO (b/174636568) : this class should be able to cache an instance of - // ConnectivityManager so it doesn't have to fetch it again every time. - final Handler handler = new Handler(looper) { - @Override - public void handleMessage(Message m) { - switch (m.what) { - case CMD_REQUEST_NETWORK: - onNetworkRequested((NetworkRequest) m.obj, m.arg1, m.arg2); - break; - case CMD_CANCEL_REQUEST: - onNetworkRequestWithdrawn((NetworkRequest) m.obj); - break; - default: - Log.e(mName, "Unhandled message: " + m.what); - } - } - }; - mContext = context; - mMessenger = new Messenger(handler); - mName = name; - } - - // TODO: consider adding a register() method so ConnectivityManager does not need to call this. - /** @hide */ - public @Nullable Messenger getMessenger() { - return mMessenger; - } - - /** @hide */ - public @NonNull String getName() { - return mName; - } - - /** - * Returns the ID of this provider. This is known only once the provider is registered via - * {@link ConnectivityManager#registerNetworkProvider()}, otherwise the ID is {@link #ID_NONE}. - * This ID must be used when registering any {@link NetworkAgent}s. - */ - public int getProviderId() { - return mProviderId; - } - - /** @hide */ - public void setProviderId(int providerId) { - mProviderId = providerId; - } - - /** - * Called when a NetworkRequest is received. The request may be a new request or an existing - * request with a different score. - * - * @param request the NetworkRequest being received - * @param score the score of the network currently satisfying the request, or 0 if none. - * @param providerId the ID of the provider that created the network currently satisfying this - * request, or {@link #ID_NONE} if none. - * - * @hide - */ - @SystemApi - public void onNetworkRequested(@NonNull NetworkRequest request, - @IntRange(from = 0, to = 99) int score, int providerId) {} - - /** - * Called when a NetworkRequest is withdrawn. - * @hide - */ - @SystemApi - public void onNetworkRequestWithdrawn(@NonNull NetworkRequest request) {} - - /** - * Asserts that no provider will ever be able to satisfy the specified request. The provider - * must only call this method if it knows that it is the only provider on the system capable of - * satisfying this request, and that the request cannot be satisfied. The application filing the - * request will receive an {@link NetworkCallback#onUnavailable()} callback. - * - * @param request the request that permanently cannot be fulfilled - * @hide - */ - @SystemApi - @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) - public void declareNetworkRequestUnfulfillable(@NonNull NetworkRequest request) { - ConnectivityManager.from(mContext).declareNetworkRequestUnfulfillable(request); - } - - /** - * A callback for parties registering a NetworkOffer. - * - * This is used with {@link ConnectivityManager#offerNetwork}. When offering a network, - * the system will use this callback to inform the caller that a network corresponding to - * this offer is needed or unneeded. - * - * @hide - */ - @SystemApi - public interface NetworkOfferCallback { - /** - * Called by the system when a network for this offer is needed to satisfy some - * networking request. - */ - void onNetworkNeeded(@NonNull NetworkRequest request); - /** - * Called by the system when this offer is no longer valuable for this request. - */ - void onNetworkUnneeded(@NonNull NetworkRequest request); - } - - private class NetworkOfferCallbackProxy extends INetworkOfferCallback.Stub { - @NonNull public final NetworkOfferCallback callback; - @NonNull private final Executor mExecutor; - - NetworkOfferCallbackProxy(@NonNull final NetworkOfferCallback callback, - @NonNull final Executor executor) { - this.callback = callback; - this.mExecutor = executor; - } - - @Override - public void onNetworkNeeded(final @NonNull NetworkRequest request) { - mExecutor.execute(() -> callback.onNetworkNeeded(request)); - } - - @Override - public void onNetworkUnneeded(final @NonNull NetworkRequest request) { - mExecutor.execute(() -> callback.onNetworkUnneeded(request)); - } - } - - @GuardedBy("mProxies") - @NonNull private final ArrayList mProxies = new ArrayList<>(); - - // Returns the proxy associated with this callback, or null if none. - @Nullable - private NetworkOfferCallbackProxy findProxyForCallback(@NonNull final NetworkOfferCallback cb) { - synchronized (mProxies) { - for (final NetworkOfferCallbackProxy p : mProxies) { - if (p.callback == cb) return p; - } - } - return null; - } - - /** - * Register or update an offer for network with the passed capabilities and score. - * - * A NetworkProvider's role is to provide networks. This method is how a provider tells the - * connectivity stack what kind of network it may provide. The score and caps arguments act - * as filters that the connectivity stack uses to tell when the offer is valuable. When an - * offer might be preferred over existing networks, the provider will receive a call to - * the associated callback's {@link NetworkOfferCallback#onNetworkNeeded} method. The provider - * should then try to bring up this network. When an offer is no longer useful, the stack - * will inform the provider by calling {@link NetworkOfferCallback#onNetworkUnneeded}. The - * provider should stop trying to bring up such a network, or disconnect it if it already has - * one. - * - * The stack determines what offers are valuable according to what networks are currently - * available to the system, and what networking requests are made by applications. If an - * offer looks like it could connect a better network than any existing network for any - * particular request, that's when the stack decides the network is needed. If the current - * networking requests are all satisfied by networks that this offer couldn't possibly be a - * better match for, that's when the offer is no longer valuable. An offer starts out as - * unneeded ; the provider should not try to bring up the network until - * {@link NetworkOfferCallback#onNetworkNeeded} is called. - * - * Note that the offers are non-binding to the providers, in particular because providers - * often don't know if they will be able to bring up such a network at any given time. For - * example, no wireless network may be in range when the offer would be valuable. This is fine - * and expected ; the provider should simply continue to try to bring up the network and do so - * if/when it becomes possible. In the mean time, the stack will continue to satisfy requests - * with the best network currently available, or if none, keep the apps informed that no - * network can currently satisfy this request. When/if the provider can bring up the network, - * the connectivity stack will match it against requests, and inform interested apps of the - * availability of this network. This may, in turn, render the offer of some other provider - * low-value if all requests it used to satisfy are now better served by this network. - * - * A network can become unneeded for a reason like the above : whether the provider managed - * to bring up the offered network after it became needed or not, some other provider may - * bring up a better network than this one, making this network unneeded. A network may also - * become unneeded if the application making the request withdrew it (for example, after it - * is done transferring data, or if the user canceled an operation). - * - * The capabilities and score act as filters as to what requests the provider will see. - * They are not promises, but for best performance, the providers should strive to put - * as much known information as possible in the offer. For the score, it should put as - * strong a score as the networks will have, since this will filter what requests the - * provider sees – it's not a promise, it only serves to avoid sending requests that - * the provider can't ever hope to satisfy better than any current network. For capabilities, - * it should put all NetworkAgent-managed capabilities a network may have, even if it doesn't - * have them at first. This applies to INTERNET, for example ; if a provider thinks the - * network it can bring up for this offer may offer Internet access it should include the - * INTERNET bit. It's fine if the brought up network ends up not actually having INTERNET. - * - * TODO : in the future, to avoid possible infinite loops, there should be constraints on - * what can be put in capabilities of networks brought up for an offer. If a provider might - * bring up a network with or without INTERNET, then it should file two offers : this will - * let it know precisely what networks are needed, so it can avoid bringing up networks that - * won't actually satisfy requests and remove the risk for bring-up-bring-down loops. - * - * @hide - */ - @SystemApi - @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) - public void registerNetworkOffer(@NonNull final NetworkScore score, - @NonNull final NetworkCapabilities caps, @NonNull final Executor executor, - @NonNull final NetworkOfferCallback callback) { - // Can't offer a network with a provider that is not yet registered or already unregistered. - final int providerId = mProviderId; - if (providerId == ID_NONE) return; - NetworkOfferCallbackProxy proxy = null; - synchronized (mProxies) { - for (final NetworkOfferCallbackProxy existingProxy : mProxies) { - if (existingProxy.callback == callback) { - proxy = existingProxy; - break; - } - } - if (null == proxy) { - proxy = new NetworkOfferCallbackProxy(callback, executor); - mProxies.add(proxy); - } - } - mContext.getSystemService(ConnectivityManager.class) - .offerNetwork(providerId, score, caps, proxy); - } - - /** - * Withdraw a network offer previously made to the networking stack. - * - * If a provider can no longer provide a network they offered, it should call this method. - * An example of usage could be if the hardware necessary to bring up the network was turned - * off in UI by the user. Note that because offers are never binding, the provider might - * alternatively decide not to withdraw this offer and simply refuse to bring up the network - * even when it's needed. However, withdrawing the request is slightly more resource-efficient - * because the networking stack won't have to compare this offer to exiting networks to see - * if it could beat any of them, and may be advantageous to the provider's implementation that - * can rely on no longer receiving callbacks for a network that they can't bring up anyways. - * - * @hide - */ - @SystemApi - @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) - public void unregisterNetworkOffer(final @NonNull NetworkOfferCallback callback) { - final NetworkOfferCallbackProxy proxy = findProxyForCallback(callback); - if (null == proxy) return; - mProxies.remove(proxy); - mContext.getSystemService(ConnectivityManager.class).unofferNetwork(proxy); - } -} diff --git a/packages/Connectivity/framework/src/android/net/NetworkReleasedException.java b/packages/Connectivity/framework/src/android/net/NetworkReleasedException.java deleted file mode 100644 index 0629b7563aea8..0000000000000 --- a/packages/Connectivity/framework/src/android/net/NetworkReleasedException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.SystemApi; - -/** - * Indicates that the {@link Network} was released and is no longer available. - * - * @hide - */ -@SystemApi -public class NetworkReleasedException extends Exception { - /** @hide */ - public NetworkReleasedException() { - super("The network was released and is no longer available"); - } -} diff --git a/packages/Connectivity/framework/src/android/net/NetworkRequest.java b/packages/Connectivity/framework/src/android/net/NetworkRequest.java deleted file mode 100644 index afc76d664af24..0000000000000 --- a/packages/Connectivity/framework/src/android/net/NetworkRequest.java +++ /dev/null @@ -1,753 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL; -import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN; -import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND; -import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED; -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_ROAMING; -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_NOT_VPN; -import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY; -import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; -import static android.net.NetworkCapabilities.TRANSPORT_TEST; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.RequiresPermission; -import android.annotation.SuppressLint; -import android.annotation.SystemApi; -import android.compat.annotation.UnsupportedAppUsage; -import android.net.NetworkCapabilities.NetCapability; -import android.net.NetworkCapabilities.Transport; -import android.os.Build; -import android.os.Parcel; -import android.os.Parcelable; -import android.os.Process; -import android.text.TextUtils; -import android.util.Range; - -import java.util.Arrays; -import java.util.List; -import java.util.Objects; -import java.util.Set; - -/** - * Defines a request for a network, made through {@link NetworkRequest.Builder} and used - * to request a network via {@link ConnectivityManager#requestNetwork} or listen for changes - * via {@link ConnectivityManager#registerNetworkCallback}. - */ -public class NetworkRequest implements Parcelable { - /** - * The first requestId value that will be allocated. - * @hide only used by ConnectivityService. - */ - public static final int FIRST_REQUEST_ID = 1; - - /** - * The requestId value that represents the absence of a request. - * @hide only used by ConnectivityService. - */ - public static final int REQUEST_ID_NONE = -1; - - /** - * The {@link NetworkCapabilities} that define this request. - * @hide - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public final @NonNull NetworkCapabilities networkCapabilities; - - /** - * Identifies the request. NetworkRequests should only be constructed by - * the Framework and given out to applications as tokens to be used to identify - * the request. - * @hide - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public final int requestId; - - /** - * Set for legacy requests and the default. Set to TYPE_NONE for none. - * Causes CONNECTIVITY_ACTION broadcasts to be sent. - * @hide - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) - public final int legacyType; - - /** - * A NetworkRequest as used by the system can be one of the following types: - * - * - LISTEN, for which the framework will issue callbacks about any - * and all networks that match the specified NetworkCapabilities, - * - * - REQUEST, capable of causing a specific network to be created - * first (e.g. a telephony DUN request), the framework will issue - * callbacks about the single, highest scoring current network - * (if any) that matches the specified NetworkCapabilities, or - * - * - TRACK_DEFAULT, which causes the framework to issue callbacks for - * the single, highest scoring current network (if any) that will - * be chosen for an app, but which cannot cause the framework to - * either create or retain the existence of any specific network. - * - * - TRACK_SYSTEM_DEFAULT, which causes the framework to send callbacks - * for the network (if any) that satisfies the default Internet - * request. - * - * - TRACK_BEST, which causes the framework to send callbacks about - * the single, highest scoring current network (if any) that matches - * the specified NetworkCapabilities. - * - * - BACKGROUND_REQUEST, like REQUEST but does not cause any networks - * to retain the NET_CAPABILITY_FOREGROUND capability. A network with - * no foreground requests is in the background. A network that has - * one or more background requests and loses its last foreground - * request to a higher-scoring network will not go into the - * background immediately, but will linger and go into the background - * after the linger timeout. - * - * - The value NONE is used only by applications. When an application - * creates a NetworkRequest, it does not have a type; the type is set - * by the system depending on the method used to file the request - * (requestNetwork, registerNetworkCallback, etc.). - * - * @hide - */ - public static enum Type { - NONE, - LISTEN, - TRACK_DEFAULT, - REQUEST, - BACKGROUND_REQUEST, - TRACK_SYSTEM_DEFAULT, - LISTEN_FOR_BEST, - }; - - /** - * The type of the request. This is only used by the system and is always NONE elsewhere. - * - * @hide - */ - public final Type type; - - /** - * @hide - */ - public NetworkRequest(NetworkCapabilities nc, int legacyType, int rId, Type type) { - if (nc == null) { - throw new NullPointerException(); - } - requestId = rId; - networkCapabilities = nc; - this.legacyType = legacyType; - this.type = type; - } - - /** - * @hide - */ - public NetworkRequest(NetworkRequest that) { - networkCapabilities = new NetworkCapabilities(that.networkCapabilities); - requestId = that.requestId; - this.legacyType = that.legacyType; - this.type = that.type; - } - - /** - * Builder used to create {@link NetworkRequest} objects. Specify the Network features - * needed in terms of {@link NetworkCapabilities} features - */ - public static class Builder { - /** - * Capabilities that are currently compatible with VCN networks. - */ - private static final List VCN_SUPPORTED_CAPABILITIES = Arrays.asList( - NET_CAPABILITY_CAPTIVE_PORTAL, - NET_CAPABILITY_DUN, - NET_CAPABILITY_FOREGROUND, - NET_CAPABILITY_INTERNET, - NET_CAPABILITY_NOT_CONGESTED, - NET_CAPABILITY_NOT_METERED, - NET_CAPABILITY_NOT_RESTRICTED, - NET_CAPABILITY_NOT_ROAMING, - NET_CAPABILITY_NOT_SUSPENDED, - NET_CAPABILITY_NOT_VPN, - NET_CAPABILITY_PARTIAL_CONNECTIVITY, - NET_CAPABILITY_TEMPORARILY_NOT_METERED, - NET_CAPABILITY_TRUSTED, - NET_CAPABILITY_VALIDATED); - - private final NetworkCapabilities mNetworkCapabilities; - - // A boolean that represents whether the NOT_VCN_MANAGED capability should be deduced when - // the NetworkRequest object is built. - private boolean mShouldDeduceNotVcnManaged = true; - - /** - * Default constructor for Builder. - */ - public Builder() { - // By default, restrict this request to networks available to this app. - // Apps can rescind this restriction, but ConnectivityService will enforce - // it for apps that do not have the NETWORK_SETTINGS permission. - mNetworkCapabilities = new NetworkCapabilities(); - mNetworkCapabilities.setSingleUid(Process.myUid()); - } - - /** - * Creates a new Builder of NetworkRequest from an existing instance. - */ - public Builder(@NonNull final NetworkRequest request) { - Objects.requireNonNull(request); - mNetworkCapabilities = request.networkCapabilities; - // If the caller constructed the builder from a request, it means the user - // might explicitly want the capabilities from the request. Thus, the NOT_VCN_MANAGED - // capabilities should not be touched later. - mShouldDeduceNotVcnManaged = false; - } - - /** - * Build {@link NetworkRequest} give the current set of capabilities. - */ - public NetworkRequest build() { - // Make a copy of mNetworkCapabilities so we don't inadvertently remove NOT_RESTRICTED - // when later an unrestricted capability could be added to mNetworkCapabilities, in - // which case NOT_RESTRICTED should be returned to mNetworkCapabilities, which - // maybeMarkCapabilitiesRestricted() doesn't add back. - final NetworkCapabilities nc = new NetworkCapabilities(mNetworkCapabilities); - nc.maybeMarkCapabilitiesRestricted(); - deduceNotVcnManagedCapability(nc); - return new NetworkRequest(nc, ConnectivityManager.TYPE_NONE, - ConnectivityManager.REQUEST_ID_UNSET, Type.NONE); - } - - /** - * Add the given capability requirement to this builder. These represent - * the requested network's required capabilities. Note that when searching - * for a network to satisfy a request, all capabilities requested must be - * satisfied. - * - * @param capability The capability to add. - * @return The builder to facilitate chaining - * {@code builder.addCapability(...).addCapability();}. - */ - public Builder addCapability(@NetworkCapabilities.NetCapability int capability) { - mNetworkCapabilities.addCapability(capability); - if (capability == NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) { - mShouldDeduceNotVcnManaged = false; - } - return this; - } - - /** - * Removes (if found) the given capability from this builder instance. - * - * @param capability The capability to remove. - * @return The builder to facilitate chaining. - */ - public Builder removeCapability(@NetworkCapabilities.NetCapability int capability) { - mNetworkCapabilities.removeCapability(capability); - if (capability == NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) { - mShouldDeduceNotVcnManaged = false; - } - return this; - } - - /** - * Set the {@code NetworkCapabilities} for this builder instance, - * overriding any capabilities that had been previously set. - * - * @param nc The superseding {@code NetworkCapabilities} instance. - * @return The builder to facilitate chaining. - * @hide - */ - public Builder setCapabilities(NetworkCapabilities nc) { - mNetworkCapabilities.set(nc); - return this; - } - - /** - * Sets this request to match only networks that apply to the specified UIDs. - * - * By default, the set of UIDs is the UID of the calling app, and this request will match - * any network that applies to the app. Setting it to {@code null} will observe any - * network on the system, even if it does not apply to this app. In this case, any - * {@link NetworkSpecifier} set on this request will be redacted or removed to prevent the - * application deducing restricted information such as location. - * - * @param uids The UIDs as a set of {@code Range}, or null for everything. - * @return The builder to facilitate chaining. - * @hide - */ - @NonNull - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - @SuppressLint("MissingGetterMatchingBuilder") - public Builder setUids(@Nullable Set> uids) { - mNetworkCapabilities.setUids(uids); - return this; - } - - /** - * Add a capability that must not exist in the requested network. - *

    - * If the capability was previously added to the list of required capabilities (for - * example, it was there by default or added using {@link #addCapability(int)} method), then - * it will be removed from the list of required capabilities as well. - * - * @see #addCapability(int) - * - * @param capability The capability to add to forbidden capability list. - * @return The builder to facilitate chaining. - * - * @hide - */ - @NonNull - @SuppressLint("MissingGetterMatchingBuilder") - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public Builder addForbiddenCapability(@NetworkCapabilities.NetCapability int capability) { - mNetworkCapabilities.addForbiddenCapability(capability); - return this; - } - - /** - * Removes (if found) the given forbidden capability from this builder instance. - * - * @param capability The forbidden capability to remove. - * @return The builder to facilitate chaining. - * - * @hide - */ - @NonNull - @SuppressLint("BuilderSetStyle") - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public Builder removeForbiddenCapability( - @NetworkCapabilities.NetCapability int capability) { - mNetworkCapabilities.removeForbiddenCapability(capability); - return this; - } - - /** - * Completely clears all the {@code NetworkCapabilities} from this builder instance, - * removing even the capabilities that are set by default when the object is constructed. - * - * @return The builder to facilitate chaining. - */ - @NonNull - public Builder clearCapabilities() { - mNetworkCapabilities.clearAll(); - // If the caller explicitly clear all capabilities, the NOT_VCN_MANAGED capabilities - // should not be add back later. - mShouldDeduceNotVcnManaged = false; - return this; - } - - /** - * Adds the given transport requirement to this builder. These represent - * the set of allowed transports for the request. Only networks using one - * of these transports will satisfy the request. If no particular transports - * are required, none should be specified here. - * - * @param transportType The transport type to add. - * @return The builder to facilitate chaining. - */ - public Builder addTransportType(@NetworkCapabilities.Transport int transportType) { - mNetworkCapabilities.addTransportType(transportType); - return this; - } - - /** - * Removes (if found) the given transport from this builder instance. - * - * @param transportType The transport type to remove. - * @return The builder to facilitate chaining. - */ - public Builder removeTransportType(@NetworkCapabilities.Transport int transportType) { - mNetworkCapabilities.removeTransportType(transportType); - return this; - } - - /** - * @hide - */ - public Builder setLinkUpstreamBandwidthKbps(int upKbps) { - mNetworkCapabilities.setLinkUpstreamBandwidthKbps(upKbps); - return this; - } - /** - * @hide - */ - public Builder setLinkDownstreamBandwidthKbps(int downKbps) { - mNetworkCapabilities.setLinkDownstreamBandwidthKbps(downKbps); - return this; - } - - /** - * Sets the optional bearer specific network specifier. - * This has no meaning if a single transport is also not specified, so calling - * this without a single transport set will generate an exception, as will - * subsequently adding or removing transports after this is set. - *

    - * If the {@code networkSpecifier} is provided, it shall be interpreted as follows: - *
      - *
    • If the specifier can be parsed as an integer, it will be treated as a - * {@link android.net TelephonyNetworkSpecifier}, and the provided integer will be - * interpreted as a SubscriptionId. - *
    • If the value is an ethernet interface name, it will be treated as such. - *
    • For all other cases, the behavior is undefined. - *
    - * - * @param networkSpecifier A {@code String} of either a SubscriptionId in cellular - * network request or an ethernet interface name in ethernet - * network request. - * - * @deprecated Use {@link #setNetworkSpecifier(NetworkSpecifier)} instead. - */ - @Deprecated - public Builder setNetworkSpecifier(String networkSpecifier) { - try { - int subId = Integer.parseInt(networkSpecifier); - return setNetworkSpecifier(new TelephonyNetworkSpecifier.Builder() - .setSubscriptionId(subId).build()); - } catch (NumberFormatException nfe) { - // An EthernetNetworkSpecifier or TestNetworkSpecifier does not accept null or empty - // ("") strings. When network specifiers were strings a null string and an empty - // string were considered equivalent. Hence no meaning is attached to a null or - // empty ("") string. - if (TextUtils.isEmpty(networkSpecifier)) { - return setNetworkSpecifier((NetworkSpecifier) null); - } else if (mNetworkCapabilities.hasTransport(TRANSPORT_TEST)) { - return setNetworkSpecifier(new TestNetworkSpecifier(networkSpecifier)); - } else { - return setNetworkSpecifier(new EthernetNetworkSpecifier(networkSpecifier)); - } - } - } - - /** - * Sets the optional bearer specific network specifier. - * This has no meaning if a single transport is also not specified, so calling - * this without a single transport set will generate an exception, as will - * subsequently adding or removing transports after this is set. - *

    - * - * @param networkSpecifier A concrete, parcelable framework class that extends - * NetworkSpecifier. - */ - public Builder setNetworkSpecifier(NetworkSpecifier networkSpecifier) { - if (networkSpecifier instanceof MatchAllNetworkSpecifier) { - throw new IllegalArgumentException("A MatchAllNetworkSpecifier is not permitted"); - } - mNetworkCapabilities.setNetworkSpecifier(networkSpecifier); - // Do not touch NOT_VCN_MANAGED if the caller needs to access to a very specific - // Network. - mShouldDeduceNotVcnManaged = false; - return this; - } - - /** - * Sets the signal strength. This is a signed integer, with higher values indicating a - * stronger signal. The exact units are bearer-dependent. For example, Wi-Fi uses the same - * RSSI units reported by WifiManager. - *

    - * Note that when used to register a network callback, this specifies the minimum acceptable - * signal strength. When received as the state of an existing network it specifies the - * current value. A value of {@code SIGNAL_STRENGTH_UNSPECIFIED} means no value when - * received and has no effect when requesting a callback. - * - *

    This method requires the caller to hold the - * {@link android.Manifest.permission#NETWORK_SIGNAL_STRENGTH_WAKEUP} permission - * - * @param signalStrength the bearer-specific signal strength. - * @hide - */ - @SystemApi - @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) - public @NonNull Builder setSignalStrength(int signalStrength) { - mNetworkCapabilities.setSignalStrength(signalStrength); - return this; - } - - /** - * Deduce the NET_CAPABILITY_NOT_VCN_MANAGED capability from other capabilities - * and user intention, which includes: - * 1. For the requests that don't have anything besides - * {@link #VCN_SUPPORTED_CAPABILITIES}, add the NET_CAPABILITY_NOT_VCN_MANAGED to - * allow the callers automatically utilize VCN networks if available. - * 2. For the requests that explicitly add or remove NET_CAPABILITY_NOT_VCN_MANAGED, - * or has clear intention of tracking specific network, - * do not alter them to allow user fire request that suits their need. - * - * @hide - */ - private void deduceNotVcnManagedCapability(final NetworkCapabilities nc) { - if (!mShouldDeduceNotVcnManaged) return; - for (final int cap : nc.getCapabilities()) { - if (!VCN_SUPPORTED_CAPABILITIES.contains(cap)) return; - } - nc.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); - } - - /** - * Sets the optional subscription ID set. - *

    - * This specify the subscription IDs requirement. - * A network will satisfy this request only if it matches one of the subIds in this set. - * An empty set matches all networks, including those without a subId. - * - *

    Registering a NetworkRequest with a non-empty set of subIds requires the - * NETWORK_FACTORY permission. - * - * @param subIds A {@code Set} that represents subscription IDs. - * @hide - */ - @NonNull - @SystemApi - public Builder setSubscriptionIds(@NonNull Set subIds) { - mNetworkCapabilities.setSubscriptionIds(subIds); - return this; - } - - /** - * Specifies whether the built request should also match networks that do not apply to the - * calling UID. - * - * By default, the built request will only match networks that apply to the calling UID. - * If this method is called with {@code true}, the built request will match any network on - * the system that matches the other parameters of the request. In this case, any - * information in the built request that is subject to redaction for security or privacy - * purposes, such as a {@link NetworkSpecifier}, will be redacted or removed to prevent the - * application deducing sensitive information. - * - * @param include Whether to match networks that do not apply to the calling UID. - * @return The builder to facilitate chaining. - */ - @NonNull - public Builder setIncludeOtherUidNetworks(boolean include) { - if (include) { - mNetworkCapabilities.setUids(null); - } else { - mNetworkCapabilities.setSingleUid(Process.myUid()); - } - return this; - } - } - - // implement the Parcelable interface - public int describeContents() { - return 0; - } - public void writeToParcel(Parcel dest, int flags) { - networkCapabilities.writeToParcel(dest, flags); - dest.writeInt(legacyType); - dest.writeInt(requestId); - dest.writeString(type.name()); - } - - public static final @android.annotation.NonNull Creator CREATOR = - new Creator() { - public NetworkRequest createFromParcel(Parcel in) { - NetworkCapabilities nc = NetworkCapabilities.CREATOR.createFromParcel(in); - int legacyType = in.readInt(); - int requestId = in.readInt(); - Type type = Type.valueOf(in.readString()); // IllegalArgumentException if invalid. - NetworkRequest result = new NetworkRequest(nc, legacyType, requestId, type); - return result; - } - public NetworkRequest[] newArray(int size) { - return new NetworkRequest[size]; - } - }; - - /** - * Returns true iff. this NetworkRequest is of type LISTEN. - * - * @hide - */ - public boolean isListen() { - return type == Type.LISTEN; - } - - /** - * Returns true iff. this NetworkRequest is of type LISTEN_FOR_BEST. - * - * @hide - */ - public boolean isListenForBest() { - return type == Type.LISTEN_FOR_BEST; - } - - /** - * Returns true iff. the contained NetworkRequest is one that: - * - * - should be associated with at most one satisfying network - * at a time; - * - * - should cause a network to be kept up, but not necessarily in - * the foreground, if it is the best network which can satisfy the - * NetworkRequest. - * - * For full detail of how isRequest() is used for pairing Networks with - * NetworkRequests read rematchNetworkAndRequests(). - * - * @hide - */ - public boolean isRequest() { - return type == Type.REQUEST || type == Type.BACKGROUND_REQUEST; - } - - /** - * Returns true iff. this NetworkRequest is of type BACKGROUND_REQUEST. - * - * @hide - */ - public boolean isBackgroundRequest() { - return type == Type.BACKGROUND_REQUEST; - } - - /** - * @see Builder#addCapability(int) - */ - public boolean hasCapability(@NetCapability int capability) { - return networkCapabilities.hasCapability(capability); - } - - /** - * @see Builder#addForbiddenCapability(int) - * - * @hide - */ - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public boolean hasForbiddenCapability(@NetCapability int capability) { - return networkCapabilities.hasForbiddenCapability(capability); - } - - /** - * Returns true if and only if the capabilities requested in this NetworkRequest are satisfied - * by the provided {@link NetworkCapabilities}. - * - * @param nc Capabilities that should satisfy this NetworkRequest. null capabilities do not - * satisfy any request. - */ - public boolean canBeSatisfiedBy(@Nullable NetworkCapabilities nc) { - return networkCapabilities.satisfiedByNetworkCapabilities(nc); - } - - /** - * @see Builder#addTransportType(int) - */ - public boolean hasTransport(@Transport int transportType) { - return networkCapabilities.hasTransport(transportType); - } - - /** - * @see Builder#setNetworkSpecifier(NetworkSpecifier) - */ - @Nullable - public NetworkSpecifier getNetworkSpecifier() { - return networkCapabilities.getNetworkSpecifier(); - } - - /** - * @return the uid of the app making the request. - * - * Note: This could return {@link Process#INVALID_UID} if the {@link NetworkRequest} object was - * not obtained from {@link ConnectivityManager}. - * @hide - */ - @SystemApi - public int getRequestorUid() { - return networkCapabilities.getRequestorUid(); - } - - /** - * @return the package name of the app making the request. - * - * Note: This could return {@code null} if the {@link NetworkRequest} object was not obtained - * from {@link ConnectivityManager}. - * @hide - */ - @SystemApi - @Nullable - public String getRequestorPackageName() { - return networkCapabilities.getRequestorPackageName(); - } - - public String toString() { - return "NetworkRequest [ " + type + " id=" + requestId + - (legacyType != ConnectivityManager.TYPE_NONE ? ", legacyType=" + legacyType : "") + - ", " + networkCapabilities.toString() + " ]"; - } - - public boolean equals(@Nullable Object obj) { - if (obj instanceof NetworkRequest == false) return false; - NetworkRequest that = (NetworkRequest)obj; - return (that.legacyType == this.legacyType && - that.requestId == this.requestId && - that.type == this.type && - Objects.equals(that.networkCapabilities, this.networkCapabilities)); - } - - public int hashCode() { - return Objects.hash(requestId, legacyType, networkCapabilities, type); - } - - /** - * Gets all the capabilities set on this {@code NetworkRequest} instance. - * - * @return an array of capability values for this instance. - */ - @NonNull - public @NetCapability int[] getCapabilities() { - // No need to make a defensive copy here as NC#getCapabilities() already returns - // a new array. - return networkCapabilities.getCapabilities(); - } - - /** - * Gets all the forbidden capabilities set on this {@code NetworkRequest} instance. - * - * @return an array of forbidden capability values for this instance. - * - * @hide - */ - @NonNull - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public @NetCapability int[] getForbiddenCapabilities() { - // No need to make a defensive copy here as NC#getForbiddenCapabilities() already returns - // a new array. - return networkCapabilities.getForbiddenCapabilities(); - } - - /** - * Gets all the transports set on this {@code NetworkRequest} instance. - * - * @return an array of transport type values for this instance. - */ - @NonNull - public @Transport int[] getTransportTypes() { - // No need to make a defensive copy here as NC#getTransportTypes() already returns - // a new array. - return networkCapabilities.getTransportTypes(); - } -} diff --git a/packages/Connectivity/framework/src/android/net/NetworkScore.java b/packages/Connectivity/framework/src/android/net/NetworkScore.java deleted file mode 100644 index 7be7deb999e2b..0000000000000 --- a/packages/Connectivity/framework/src/android/net/NetworkScore.java +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.SystemApi; -import android.os.Parcel; -import android.os.Parcelable; - -import com.android.internal.annotations.VisibleForTesting; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Object representing the quality of a network as perceived by the user. - * - * A NetworkScore object represents the characteristics of a network that affects how good the - * network is considered for a particular use. - * @hide - */ -@SystemApi -public final class NetworkScore implements Parcelable { - // This will be removed soon. Do *NOT* depend on it for any new code that is not part of - // a migration. - private final int mLegacyInt; - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(value = { - KEEP_CONNECTED_NONE, - KEEP_CONNECTED_FOR_HANDOVER - }) - public @interface KeepConnectedReason { } - - /** - * Do not keep this network connected if there is no outstanding request for it. - */ - public static final int KEEP_CONNECTED_NONE = 0; - /** - * Keep this network connected even if there is no outstanding request for it, because it - * is being considered for handover. - */ - public static final int KEEP_CONNECTED_FOR_HANDOVER = 1; - - // Agent-managed policies - // This network should lose to a wifi that has ever been validated - // NOTE : temporarily this policy is managed by ConnectivityService, because of legacy. The - // legacy design has this bit global to the system and tacked on WiFi which means it will affect - // networks from carriers who don't want it and non-carrier networks, which is bad for users. - // The S design has this on mobile networks only, so this can be fixed eventually ; as CS - // doesn't know what carriers need this bit, the initial S implementation will continue to - // affect other carriers but will at least leave non-mobile networks alone. Eventually Telephony - // should set this on networks from carriers that require it. - /** @hide */ - public static final int POLICY_YIELD_TO_BAD_WIFI = 1; - // This network is primary for this transport. - /** @hide */ - public static final int POLICY_TRANSPORT_PRIMARY = 2; - // This network is exiting : it will likely disconnect in a few seconds. - /** @hide */ - public static final int POLICY_EXITING = 3; - - /** @hide */ - public static final int MIN_AGENT_MANAGED_POLICY = POLICY_YIELD_TO_BAD_WIFI; - /** @hide */ - public static final int MAX_AGENT_MANAGED_POLICY = POLICY_EXITING; - - // Bitmask of all the policies applied to this score. - private final long mPolicies; - - private final int mKeepConnectedReason; - - /** @hide */ - NetworkScore(final int legacyInt, final long policies, - @KeepConnectedReason final int keepConnectedReason) { - mLegacyInt = legacyInt; - mPolicies = policies; - mKeepConnectedReason = keepConnectedReason; - } - - private NetworkScore(@NonNull final Parcel in) { - mLegacyInt = in.readInt(); - mPolicies = in.readLong(); - mKeepConnectedReason = in.readInt(); - } - - /** - * Get the legacy int score embedded in this NetworkScore. - * @see Builder#setLegacyInt(int) - */ - public int getLegacyInt() { - return mLegacyInt; - } - - /** - * Returns the keep-connected reason, or KEEP_CONNECTED_NONE. - */ - public int getKeepConnectedReason() { - return mKeepConnectedReason; - } - - /** - * @return whether this score has a particular policy. - * - * @hide - */ - @VisibleForTesting - public boolean hasPolicy(final int policy) { - return 0 != (mPolicies & (1L << policy)); - } - - /** - * To the exclusive usage of FullScore - * @hide - */ - public long getPolicies() { - return mPolicies; - } - - /** - * Whether this network should yield to a previously validated wifi gone bad. - * - * If this policy is set, other things being equal, the device will prefer a previously - * validated WiFi even if this network is validated and the WiFi is not. - * If this policy is not set, the device prefers the validated network. - * - * @hide - */ - // TODO : Unhide this for telephony and have telephony call it on the relevant carriers. - // In the mean time this is handled by Connectivity in a backward-compatible manner. - public boolean shouldYieldToBadWifi() { - return hasPolicy(POLICY_YIELD_TO_BAD_WIFI); - } - - /** - * Whether this network is primary for this transport. - * - * When multiple networks of the same transport are active, the device prefers the ones that - * are primary. This is meant in particular for DS-DA devices with a user setting to choose the - * default SIM card, or for WiFi STA+STA and make-before-break cases. - * - * @hide - */ - @SystemApi - public boolean isTransportPrimary() { - return hasPolicy(POLICY_TRANSPORT_PRIMARY); - } - - /** - * Whether this network is exiting. - * - * If this policy is set, the device will expect this network to disconnect within seconds. - * It will try to migrate to some other network if any is available, policy permitting, to - * avoid service disruption. - * This is useful in particular when a good cellular network is available and WiFi is getting - * weak and risks disconnecting soon. The WiFi network should be marked as exiting so that - * the device will prefer the reliable mobile network over this soon-to-be-lost WiFi. - * - * @hide - */ - @SystemApi - public boolean isExiting() { - return hasPolicy(POLICY_EXITING); - } - - @Override - public String toString() { - return "Score(" + mLegacyInt + " ; Policies : " + mPolicies + ")"; - } - - @Override - public void writeToParcel(@NonNull final Parcel dest, final int flags) { - dest.writeInt(mLegacyInt); - dest.writeLong(mPolicies); - dest.writeInt(mKeepConnectedReason); - } - - @Override - public int describeContents() { - return 0; - } - - @NonNull public static final Creator CREATOR = new Creator<>() { - @Override - @NonNull - public NetworkScore createFromParcel(@NonNull final Parcel in) { - return new NetworkScore(in); - } - - @Override - @NonNull - public NetworkScore[] newArray(int size) { - return new NetworkScore[size]; - } - }; - - /** - * A builder for NetworkScore. - */ - public static final class Builder { - private static final long POLICY_NONE = 0L; - private static final int INVALID_LEGACY_INT = Integer.MIN_VALUE; - private int mLegacyInt = INVALID_LEGACY_INT; - private int mKeepConnectedReason = KEEP_CONNECTED_NONE; - private int mPolicies = 0; - - /** - * Sets the legacy int for this score. - * - * This will be used for measurements and logs, but will no longer be used for ranking - * networks against each other. Callers that existed before Android S should send what - * they used to send as the int score. - * - * @param score the legacy int - * @return this - */ - @NonNull - public Builder setLegacyInt(final int score) { - mLegacyInt = score; - return this; - } - - - /** - * Set for a network that should never be preferred to a wifi that has ever been validated - * - * If this policy is set, other things being equal, the device will prefer a previously - * validated WiFi even if this network is validated and the WiFi is not. - * If this policy is not set, the device prefers the validated network. - * - * @return this builder - * @hide - */ - // TODO : Unhide this for telephony and have telephony call it on the relevant carriers. - // In the mean time this is handled by Connectivity in a backward-compatible manner. - @NonNull - public Builder setShouldYieldToBadWifi(final boolean val) { - if (val) { - mPolicies |= (1L << POLICY_YIELD_TO_BAD_WIFI); - } else { - mPolicies &= ~(1L << POLICY_YIELD_TO_BAD_WIFI); - } - return this; - } - - /** - * Set for a network that is primary for this transport. - * - * When multiple networks of the same transport are active, the device prefers the ones that - * are primary. This is meant in particular for DS-DA devices with a user setting to choose - * the default SIM card, or for WiFi STA+STA and make-before-break cases. - * - * @return this builder - * @hide - */ - @SystemApi - @NonNull - public Builder setTransportPrimary(final boolean val) { - if (val) { - mPolicies |= (1L << POLICY_TRANSPORT_PRIMARY); - } else { - mPolicies &= ~(1L << POLICY_TRANSPORT_PRIMARY); - } - return this; - } - - /** - * Set for a network that will likely disconnect in a few seconds. - * - * If this policy is set, the device will expect this network to disconnect within seconds. - * It will try to migrate to some other network if any is available, policy permitting, to - * avoid service disruption. - * This is useful in particular when a good cellular network is available and WiFi is - * getting weak and risks disconnecting soon. The WiFi network should be marked as exiting - * so that the device will prefer the reliable mobile network over this soon-to-be-lost - * WiFi. - * - * @return this builder - * @hide - */ - @SystemApi - @NonNull - public Builder setExiting(final boolean val) { - if (val) { - mPolicies |= (1L << POLICY_EXITING); - } else { - mPolicies &= ~(1L << POLICY_EXITING); - } - return this; - } - - /** - * Set the keep-connected reason. - * - * This can be reset by calling it again with {@link KEEP_CONNECTED_NONE}. - */ - @NonNull - public Builder setKeepConnectedReason(@KeepConnectedReason final int reason) { - mKeepConnectedReason = reason; - return this; - } - - /** - * Builds this NetworkScore. - * @return The built NetworkScore object. - */ - @NonNull - public NetworkScore build() { - return new NetworkScore(mLegacyInt, mPolicies, mKeepConnectedReason); - } - } -} diff --git a/packages/Connectivity/framework/src/android/net/NetworkState.java b/packages/Connectivity/framework/src/android/net/NetworkState.java deleted file mode 100644 index 9b69674728a85..0000000000000 --- a/packages/Connectivity/framework/src/android/net/NetworkState.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.compat.annotation.UnsupportedAppUsage; -import android.os.Build; -import android.os.Parcel; -import android.os.Parcelable; -import android.util.Log; - -/** - * Snapshot of network state. - * - * @hide - */ -public class NetworkState implements Parcelable { - private static final boolean VALIDATE_ROAMING_STATE = false; - - // TODO: remove and make members @NonNull. - public static final NetworkState EMPTY = new NetworkState(); - - public final NetworkInfo networkInfo; - public final LinkProperties linkProperties; - public final NetworkCapabilities networkCapabilities; - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) - public final Network network; - public final String subscriberId; - public final int legacyNetworkType; - - private NetworkState() { - networkInfo = null; - linkProperties = null; - networkCapabilities = null; - network = null; - subscriberId = null; - legacyNetworkType = 0; - } - - public NetworkState(int legacyNetworkType, @NonNull LinkProperties linkProperties, - @NonNull NetworkCapabilities networkCapabilities, @NonNull Network network, - @Nullable String subscriberId) { - this(legacyNetworkType, new NetworkInfo(legacyNetworkType, 0, null, null), linkProperties, - networkCapabilities, network, subscriberId); - } - - // Constructor that used internally in ConnectivityService mainline module. - public NetworkState(@NonNull NetworkInfo networkInfo, @NonNull LinkProperties linkProperties, - @NonNull NetworkCapabilities networkCapabilities, @NonNull Network network, - @Nullable String subscriberId) { - this(networkInfo.getType(), networkInfo, linkProperties, - networkCapabilities, network, subscriberId); - } - - public NetworkState(int legacyNetworkType, @NonNull NetworkInfo networkInfo, - @NonNull LinkProperties linkProperties, - @NonNull NetworkCapabilities networkCapabilities, @NonNull Network network, - @Nullable String subscriberId) { - this.networkInfo = networkInfo; - this.linkProperties = linkProperties; - this.networkCapabilities = networkCapabilities; - this.network = network; - this.subscriberId = subscriberId; - this.legacyNetworkType = legacyNetworkType; - - // This object is an atomic view of a network, so the various components - // should always agree on roaming state. - if (VALIDATE_ROAMING_STATE && networkInfo != null && networkCapabilities != null) { - if (networkInfo.isRoaming() == networkCapabilities - .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)) { - Log.wtf("NetworkState", "Roaming state disagreement between " + networkInfo - + " and " + networkCapabilities); - } - } - } - - @UnsupportedAppUsage - public NetworkState(Parcel in) { - networkInfo = in.readParcelable(null); - linkProperties = in.readParcelable(null); - networkCapabilities = in.readParcelable(null); - network = in.readParcelable(null); - subscriberId = in.readString(); - legacyNetworkType = in.readInt(); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel out, int flags) { - out.writeParcelable(networkInfo, flags); - out.writeParcelable(linkProperties, flags); - out.writeParcelable(networkCapabilities, flags); - out.writeParcelable(network, flags); - out.writeString(subscriberId); - out.writeInt(legacyNetworkType); - } - - @UnsupportedAppUsage - @NonNull - public static final Creator CREATOR = new Creator() { - @Override - public NetworkState createFromParcel(Parcel in) { - return new NetworkState(in); - } - - @Override - public NetworkState[] newArray(int size) { - return new NetworkState[size]; - } - }; -} diff --git a/packages/Connectivity/framework/src/android/net/NetworkUtils.java b/packages/Connectivity/framework/src/android/net/NetworkUtils.java deleted file mode 100644 index 2679b6218c197..0000000000000 --- a/packages/Connectivity/framework/src/android/net/NetworkUtils.java +++ /dev/null @@ -1,429 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static android.net.ConnectivityManager.NETID_UNSET; - -import android.compat.annotation.UnsupportedAppUsage; -import android.os.Build; -import android.system.ErrnoException; -import android.util.Log; -import android.util.Pair; - -import com.android.net.module.util.Inet4AddressUtils; - -import java.io.FileDescriptor; -import java.math.BigInteger; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.SocketException; -import java.net.UnknownHostException; -import java.util.Locale; -import java.util.TreeSet; - -/** - * Native methods for managing network interfaces. - * - * {@hide} - */ -public class NetworkUtils { - static { - System.loadLibrary("framework-connectivity-jni"); - } - - private static final String TAG = "NetworkUtils"; - - /** - * Attaches a socket filter that drops all of incoming packets. - * @param fd the socket's {@link FileDescriptor}. - */ - public static native void attachDropAllBPFFilter(FileDescriptor fd) throws SocketException; - - /** - * Detaches a socket filter. - * @param fd the socket's {@link FileDescriptor}. - */ - public static native void detachBPFFilter(FileDescriptor fd) throws SocketException; - - private static native boolean bindProcessToNetworkHandle(long netHandle); - - /** - * Binds the current process to the network designated by {@code netId}. All sockets created - * in the future (and not explicitly bound via a bound {@link SocketFactory} (see - * {@link Network#getSocketFactory}) will be bound to this network. Note that if this - * {@code Network} ever disconnects all sockets created in this way will cease to work. This - * is by design so an application doesn't accidentally use sockets it thinks are still bound to - * a particular {@code Network}. Passing NETID_UNSET clears the binding. - */ - public static boolean bindProcessToNetwork(int netId) { - return bindProcessToNetworkHandle(new Network(netId).getNetworkHandle()); - } - - private static native long getBoundNetworkHandleForProcess(); - - /** - * Return the netId last passed to {@link #bindProcessToNetwork}, or NETID_UNSET if - * {@link #unbindProcessToNetwork} has been called since {@link #bindProcessToNetwork}. - */ - public static int getBoundNetworkForProcess() { - final long netHandle = getBoundNetworkHandleForProcess(); - return netHandle == 0L ? NETID_UNSET : Network.fromNetworkHandle(netHandle).getNetId(); - } - - /** - * Binds host resolutions performed by this process to the network designated by {@code netId}. - * {@link #bindProcessToNetwork} takes precedence over this setting. Passing NETID_UNSET clears - * the binding. - * - * @deprecated This is strictly for legacy usage to support startUsingNetworkFeature(). - */ - @Deprecated - public native static boolean bindProcessToNetworkForHostResolution(int netId); - - private static native int bindSocketToNetworkHandle(FileDescriptor fd, long netHandle); - - /** - * Explicitly binds {@code fd} to the network designated by {@code netId}. This - * overrides any binding via {@link #bindProcessToNetwork}. - * @return 0 on success or negative errno on failure. - */ - public static int bindSocketToNetwork(FileDescriptor fd, int netId) { - return bindSocketToNetworkHandle(fd, new Network(netId).getNetworkHandle()); - } - - /** - * Determine if {@code uid} can access network designated by {@code netId}. - * @return {@code true} if {@code uid} can access network, {@code false} otherwise. - */ - public static boolean queryUserAccess(int uid, int netId) { - // TODO (b/183485986): remove this method - return false; - } - - private static native FileDescriptor resNetworkSend( - long netHandle, byte[] msg, int msglen, int flags) throws ErrnoException; - - /** - * DNS resolver series jni method. - * Issue the query {@code msg} on the network designated by {@code netId}. - * {@code flags} is an additional config to control actual querying behavior. - * @return a file descriptor to watch for read events - */ - public static FileDescriptor resNetworkSend( - int netId, byte[] msg, int msglen, int flags) throws ErrnoException { - return resNetworkSend(new Network(netId).getNetworkHandle(), msg, msglen, flags); - } - - private static native FileDescriptor resNetworkQuery( - long netHandle, String dname, int nsClass, int nsType, int flags) throws ErrnoException; - - /** - * DNS resolver series jni method. - * Look up the {@code nsClass} {@code nsType} Resource Record (RR) associated - * with Domain Name {@code dname} on the network designated by {@code netId}. - * {@code flags} is an additional config to control actual querying behavior. - * @return a file descriptor to watch for read events - */ - public static FileDescriptor resNetworkQuery( - int netId, String dname, int nsClass, int nsType, int flags) throws ErrnoException { - return resNetworkQuery(new Network(netId).getNetworkHandle(), dname, nsClass, nsType, - flags); - } - - /** - * DNS resolver series jni method. - * Read a result for the query associated with the {@code fd}. - * @return DnsResponse containing blob answer and rcode - */ - public static native DnsResolver.DnsResponse resNetworkResult(FileDescriptor fd) - throws ErrnoException; - - /** - * DNS resolver series jni method. - * Attempts to cancel the in-progress query associated with the {@code fd}. - */ - public static native void resNetworkCancel(FileDescriptor fd); - - /** - * DNS resolver series jni method. - * Attempts to get network which resolver will use if no network is explicitly selected. - */ - public static native Network getDnsNetwork() throws ErrnoException; - - /** - * Get the tcp repair window associated with the {@code fd}. - * - * @param fd the tcp socket's {@link FileDescriptor}. - * @return a {@link TcpRepairWindow} object indicates tcp window size. - */ - public static native TcpRepairWindow getTcpRepairWindow(FileDescriptor fd) - throws ErrnoException; - - /** - * @see Inet4AddressUtils#intToInet4AddressHTL(int) - * @deprecated Use either {@link Inet4AddressUtils#intToInet4AddressHTH(int)} - * or {@link Inet4AddressUtils#intToInet4AddressHTL(int)} - */ - @Deprecated - @UnsupportedAppUsage - public static InetAddress intToInetAddress(int hostAddress) { - return Inet4AddressUtils.intToInet4AddressHTL(hostAddress); - } - - /** - * @see Inet4AddressUtils#inet4AddressToIntHTL(Inet4Address) - * @deprecated Use either {@link Inet4AddressUtils#inet4AddressToIntHTH(Inet4Address)} - * or {@link Inet4AddressUtils#inet4AddressToIntHTL(Inet4Address)} - */ - @Deprecated - public static int inetAddressToInt(Inet4Address inetAddr) - throws IllegalArgumentException { - return Inet4AddressUtils.inet4AddressToIntHTL(inetAddr); - } - - /** - * @see Inet4AddressUtils#prefixLengthToV4NetmaskIntHTL(int) - * @deprecated Use either {@link Inet4AddressUtils#prefixLengthToV4NetmaskIntHTH(int)} - * or {@link Inet4AddressUtils#prefixLengthToV4NetmaskIntHTL(int)} - */ - @Deprecated - @UnsupportedAppUsage - public static int prefixLengthToNetmaskInt(int prefixLength) - throws IllegalArgumentException { - return Inet4AddressUtils.prefixLengthToV4NetmaskIntHTL(prefixLength); - } - - /** - * Convert a IPv4 netmask integer to a prefix length - * @param netmask as an integer (0xff000000 for a /8 subnet) - * @return the network prefix length - */ - public static int netmaskIntToPrefixLength(int netmask) { - return Integer.bitCount(netmask); - } - - /** - * Convert an IPv4 netmask to a prefix length, checking that the netmask is contiguous. - * @param netmask as a {@code Inet4Address}. - * @return the network prefix length - * @throws IllegalArgumentException the specified netmask was not contiguous. - * @hide - * @deprecated use {@link Inet4AddressUtils#netmaskToPrefixLength(Inet4Address)} - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - @Deprecated - public static int netmaskToPrefixLength(Inet4Address netmask) { - // This is only here because some apps seem to be using it (@UnsupportedAppUsage). - return Inet4AddressUtils.netmaskToPrefixLength(netmask); - } - - - /** - * Create an InetAddress from a string where the string must be a standard - * representation of a V4 or V6 address. Avoids doing a DNS lookup on failure - * but it will throw an IllegalArgumentException in that case. - * @param addrString - * @return the InetAddress - * @hide - * @deprecated Use {@link InetAddresses#parseNumericAddress(String)}, if possible. - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) - @Deprecated - public static InetAddress numericToInetAddress(String addrString) - throws IllegalArgumentException { - return InetAddresses.parseNumericAddress(addrString); - } - - /** - * Returns the implicit netmask of an IPv4 address, as was the custom before 1993. - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public static int getImplicitNetmask(Inet4Address address) { - // Only here because it seems to be used by apps - return Inet4AddressUtils.getImplicitNetmask(address); - } - - /** - * Utility method to parse strings such as "192.0.2.5/24" or "2001:db8::cafe:d00d/64". - * @hide - */ - public static Pair parseIpAndMask(String ipAndMaskString) { - InetAddress address = null; - int prefixLength = -1; - try { - String[] pieces = ipAndMaskString.split("/", 2); - prefixLength = Integer.parseInt(pieces[1]); - address = InetAddresses.parseNumericAddress(pieces[0]); - } catch (NullPointerException e) { // Null string. - } catch (ArrayIndexOutOfBoundsException e) { // No prefix length. - } catch (NumberFormatException e) { // Non-numeric prefix. - } catch (IllegalArgumentException e) { // Invalid IP address. - } - - if (address == null || prefixLength == -1) { - throw new IllegalArgumentException("Invalid IP address and mask " + ipAndMaskString); - } - - return new Pair(address, prefixLength); - } - - /** - * Utility method to parse strings such as "192.0.2.5/24" or "2001:db8::cafe:d00d/64". - * @hide - * - * @deprecated This method is used only for IpPrefix and LinkAddress. Since Android S, use - * {@link #parseIpAndMask(String)}, if possible. - */ - @Deprecated - public static Pair legacyParseIpAndMask(String ipAndMaskString) { - InetAddress address = null; - int prefixLength = -1; - try { - String[] pieces = ipAndMaskString.split("/", 2); - prefixLength = Integer.parseInt(pieces[1]); - if (pieces[0] == null || pieces[0].isEmpty()) { - final byte[] bytes = new byte[16]; - bytes[15] = 1; - return new Pair(Inet6Address.getByAddress( - "ip6-localhost"/* host */, bytes, 0 /* scope_id */), prefixLength); - } - - if (pieces[0].startsWith("[") - && pieces[0].endsWith("]") - && pieces[0].indexOf(':') != -1) { - pieces[0] = pieces[0].substring(1, pieces[0].length() - 1); - } - address = InetAddresses.parseNumericAddress(pieces[0]); - } catch (NullPointerException e) { // Null string. - } catch (ArrayIndexOutOfBoundsException e) { // No prefix length. - } catch (NumberFormatException e) { // Non-numeric prefix. - } catch (IllegalArgumentException e) { // Invalid IP address. - } catch (UnknownHostException e) { // IP address length is illegal - } - - if (address == null || prefixLength == -1) { - throw new IllegalArgumentException("Invalid IP address and mask " + ipAndMaskString); - } - - return new Pair(address, prefixLength); - } - - /** - * Convert a 32 char hex string into a Inet6Address. - * throws a runtime exception if the string isn't 32 chars, isn't hex or can't be - * made into an Inet6Address - * @param addrHexString a 32 character hex string representing an IPv6 addr - * @return addr an InetAddress representation for the string - */ - public static InetAddress hexToInet6Address(String addrHexString) - throws IllegalArgumentException { - try { - return numericToInetAddress(String.format(Locale.US, "%s:%s:%s:%s:%s:%s:%s:%s", - addrHexString.substring(0,4), addrHexString.substring(4,8), - addrHexString.substring(8,12), addrHexString.substring(12,16), - addrHexString.substring(16,20), addrHexString.substring(20,24), - addrHexString.substring(24,28), addrHexString.substring(28,32))); - } catch (Exception e) { - Log.e("NetworkUtils", "error in hexToInet6Address(" + addrHexString + "): " + e); - throw new IllegalArgumentException(e); - } - } - - /** - * Trim leading zeros from IPv4 address strings - * Our base libraries will interpret that as octel.. - * Must leave non v4 addresses and host names alone. - * For example, 192.168.000.010 -> 192.168.0.10 - * TODO - fix base libraries and remove this function - * @param addr a string representing an ip addr - * @return a string propertly trimmed - */ - @UnsupportedAppUsage - public static String trimV4AddrZeros(String addr) { - return Inet4AddressUtils.trimAddressZeros(addr); - } - - /** - * Returns a prefix set without overlaps. - * - * This expects the src set to be sorted from shorter to longer. Results are undefined - * failing this condition. The returned prefix set is sorted in the same order as the - * passed set, with the same comparator. - */ - private static TreeSet deduplicatePrefixSet(final TreeSet src) { - final TreeSet dst = new TreeSet<>(src.comparator()); - // Prefixes match addresses that share their upper part up to their length, therefore - // the only kind of possible overlap in two prefixes is strict inclusion of the longer - // (more restrictive) in the shorter (including equivalence if they have the same - // length). - // Because prefixes in the src set are sorted from shorter to longer, deduplicating - // is done by simply iterating in order, and not adding any longer prefix that is - // already covered by a shorter one. - newPrefixes: - for (IpPrefix newPrefix : src) { - for (IpPrefix existingPrefix : dst) { - if (existingPrefix.containsPrefix(newPrefix)) { - continue newPrefixes; - } - } - dst.add(newPrefix); - } - return dst; - } - - /** - * Returns how many IPv4 addresses match any of the prefixes in the passed ordered set. - * - * Obviously this returns an integral value between 0 and 2**32. - * The behavior is undefined if any of the prefixes is not an IPv4 prefix or if the - * set is not ordered smallest prefix to longer prefix. - * - * @param prefixes the set of prefixes, ordered by length - */ - public static long routedIPv4AddressCount(final TreeSet prefixes) { - long routedIPCount = 0; - for (final IpPrefix prefix : deduplicatePrefixSet(prefixes)) { - if (!prefix.isIPv4()) { - Log.wtf(TAG, "Non-IPv4 prefix in routedIPv4AddressCount"); - } - int rank = 32 - prefix.getPrefixLength(); - routedIPCount += 1L << rank; - } - return routedIPCount; - } - - /** - * Returns how many IPv6 addresses match any of the prefixes in the passed ordered set. - * - * This returns a BigInteger between 0 and 2**128. - * The behavior is undefined if any of the prefixes is not an IPv6 prefix or if the - * set is not ordered smallest prefix to longer prefix. - */ - public static BigInteger routedIPv6AddressCount(final TreeSet prefixes) { - BigInteger routedIPCount = BigInteger.ZERO; - for (final IpPrefix prefix : deduplicatePrefixSet(prefixes)) { - if (!prefix.isIPv6()) { - Log.wtf(TAG, "Non-IPv6 prefix in routedIPv6AddressCount"); - } - int rank = 128 - prefix.getPrefixLength(); - routedIPCount = routedIPCount.add(BigInteger.ONE.shiftLeft(rank)); - } - return routedIPCount; - } - -} diff --git a/packages/Connectivity/framework/src/android/net/OemNetworkPreferences.java b/packages/Connectivity/framework/src/android/net/OemNetworkPreferences.java deleted file mode 100644 index 2bb006df82e06..0000000000000 --- a/packages/Connectivity/framework/src/android/net/OemNetworkPreferences.java +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.SystemApi; -import android.os.Bundle; -import android.os.Parcelable; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; - -/** - * Network preferences to set the default active network on a per-application basis as per a given - * {@link OemNetworkPreference}. An example of this would be to set an application's network - * preference to {@link #OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK} which would have the default - * network for that application set to an unmetered network first if available and if not, it then - * set that application's default network to an OEM managed network if available. - * - * @hide - */ -@SystemApi -public final class OemNetworkPreferences implements Parcelable { - // Valid production preferences must be > 0, negative values reserved for testing - /** - * This preference is only to be used for testing and nothing else. - * Use only TRANSPORT_TEST transport networks. - * @hide - */ - public static final int OEM_NETWORK_PREFERENCE_TEST_ONLY = -2; - - /** - * This preference is only to be used for testing and nothing else. - * If an unmetered network is available, use it. - * Otherwise, if a network with the TRANSPORT_TEST transport is available, use it. - * Otherwise, use the general default network. - * @hide - */ - public static final int OEM_NETWORK_PREFERENCE_TEST = -1; - - /** - * Default in case this value is not set. Using it will result in an error. - */ - public static final int OEM_NETWORK_PREFERENCE_UNINITIALIZED = 0; - - /** - * If an unmetered network is available, use it. - * Otherwise, if a network with the OEM_PAID capability is available, use it. - * Otherwise, use the general default network. - */ - public static final int OEM_NETWORK_PREFERENCE_OEM_PAID = 1; - - /** - * If an unmetered network is available, use it. - * Otherwise, if a network with the OEM_PAID capability is available, use it. - * Otherwise, the app doesn't get a default network. - */ - public static final int OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK = 2; - - /** - * Use only NET_CAPABILITY_OEM_PAID networks. - */ - public static final int OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY = 3; - - /** - * Use only NET_CAPABILITY_OEM_PRIVATE networks. - */ - public static final int OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY = 4; - - /** - * The max allowed value for an OEM network preference. - * @hide - */ - public static final int OEM_NETWORK_PREFERENCE_MAX = OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY; - - @NonNull - private final Bundle mNetworkMappings; - - /** - * Return whether this object is empty. - * @hide - */ - public boolean isEmpty() { - return mNetworkMappings.keySet().size() == 0; - } - - /** - * Return the currently built application package name to {@link OemNetworkPreference} mappings. - * @return the current network preferences map. - */ - @NonNull - public Map getNetworkPreferences() { - return convertToUnmodifiableMap(mNetworkMappings); - } - - private OemNetworkPreferences(@NonNull final Bundle networkMappings) { - Objects.requireNonNull(networkMappings); - mNetworkMappings = (Bundle) networkMappings.clone(); - } - - @Override - public String toString() { - return "OemNetworkPreferences{" + "mNetworkMappings=" + getNetworkPreferences() + '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - OemNetworkPreferences that = (OemNetworkPreferences) o; - - return mNetworkMappings.size() == that.mNetworkMappings.size() - && mNetworkMappings.toString().equals(that.mNetworkMappings.toString()); - } - - @Override - public int hashCode() { - return Objects.hash(mNetworkMappings); - } - - /** - * Builder used to create {@link OemNetworkPreferences} objects. Specify the preferred Network - * to package name mappings. - */ - public static final class Builder { - private final Bundle mNetworkMappings; - - public Builder() { - mNetworkMappings = new Bundle(); - } - - /** - * Constructor to populate the builder's values with an already built - * {@link OemNetworkPreferences}. - * @param preferences the {@link OemNetworkPreferences} to populate with. - */ - public Builder(@NonNull final OemNetworkPreferences preferences) { - Objects.requireNonNull(preferences); - mNetworkMappings = (Bundle) preferences.mNetworkMappings.clone(); - } - - /** - * Add a network preference for a given package. Previously stored values for the given - * package will be overwritten. - * - * @param packageName full package name (e.g.: "com.google.apps.contacts") of the app - * to use the given preference - * @param preference the desired network preference to use - * @return The builder to facilitate chaining. - */ - @NonNull - public Builder addNetworkPreference(@NonNull final String packageName, - @OemNetworkPreference final int preference) { - Objects.requireNonNull(packageName); - mNetworkMappings.putInt(packageName, preference); - return this; - } - - /** - * Remove a network preference for a given package. - * - * @param packageName full package name (e.g.: "com.google.apps.contacts") of the app to - * remove a preference for. - * @return The builder to facilitate chaining. - */ - @NonNull - public Builder clearNetworkPreference(@NonNull final String packageName) { - Objects.requireNonNull(packageName); - mNetworkMappings.remove(packageName); - return this; - } - - /** - * Build {@link OemNetworkPreferences} return the current OEM network preferences. - */ - @NonNull - public OemNetworkPreferences build() { - return new OemNetworkPreferences(mNetworkMappings); - } - } - - private static Map convertToUnmodifiableMap(@NonNull final Bundle bundle) { - final Map networkPreferences = new HashMap<>(); - for (final String key : bundle.keySet()) { - networkPreferences.put(key, bundle.getInt(key)); - } - return Collections.unmodifiableMap(networkPreferences); - } - - /** @hide */ - @IntDef(prefix = "OEM_NETWORK_PREFERENCE_", value = { - OEM_NETWORK_PREFERENCE_TEST_ONLY, - OEM_NETWORK_PREFERENCE_TEST, - OEM_NETWORK_PREFERENCE_UNINITIALIZED, - OEM_NETWORK_PREFERENCE_OEM_PAID, - OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK, - OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY, - OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY - }) - @Retention(RetentionPolicy.SOURCE) - public @interface OemNetworkPreference {} - - /** - * Return the string value for OemNetworkPreference - * - * @param value int value of OemNetworkPreference - * @return string version of OemNetworkPreference - * - * @hide - */ - @NonNull - public static String oemNetworkPreferenceToString(@OemNetworkPreference int value) { - switch (value) { - case OEM_NETWORK_PREFERENCE_TEST_ONLY: - return "OEM_NETWORK_PREFERENCE_TEST_ONLY"; - case OEM_NETWORK_PREFERENCE_TEST: - return "OEM_NETWORK_PREFERENCE_TEST"; - case OEM_NETWORK_PREFERENCE_UNINITIALIZED: - return "OEM_NETWORK_PREFERENCE_UNINITIALIZED"; - case OEM_NETWORK_PREFERENCE_OEM_PAID: - return "OEM_NETWORK_PREFERENCE_OEM_PAID"; - case OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK: - return "OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK"; - case OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY: - return "OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY"; - case OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY: - return "OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY"; - default: - return Integer.toHexString(value); - } - } - - @Override - public void writeToParcel(@NonNull android.os.Parcel dest, int flags) { - dest.writeBundle(mNetworkMappings); - } - - @Override - public int describeContents() { - return 0; - } - - @NonNull - public static final Parcelable.Creator CREATOR = - new Parcelable.Creator() { - @Override - public OemNetworkPreferences[] newArray(int size) { - return new OemNetworkPreferences[size]; - } - - @Override - public OemNetworkPreferences createFromParcel(@NonNull android.os.Parcel in) { - return new OemNetworkPreferences( - in.readBundle(getClass().getClassLoader())); - } - }; -} diff --git a/packages/Connectivity/framework/src/android/net/ParseException.java b/packages/Connectivity/framework/src/android/net/ParseException.java deleted file mode 100644 index 9d4727a84bc0f..0000000000000 --- a/packages/Connectivity/framework/src/android/net/ParseException.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.NonNull; - -/** - * Thrown when parsing failed. - */ -// See non-public class {@link WebAddress}. -public class ParseException extends RuntimeException { - public String response; - - public ParseException(@NonNull String response) { - super(response); - this.response = response; - } - - public ParseException(@NonNull String response, @NonNull Throwable cause) { - super(response, cause); - this.response = response; - } -} diff --git a/packages/Connectivity/framework/src/android/net/ProxyInfo.java b/packages/Connectivity/framework/src/android/net/ProxyInfo.java deleted file mode 100644 index 0deda371f6b9e..0000000000000 --- a/packages/Connectivity/framework/src/android/net/ProxyInfo.java +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.compat.annotation.UnsupportedAppUsage; -import android.os.Parcel; -import android.os.Parcelable; -import android.text.TextUtils; - -import com.android.net.module.util.ProxyUtils; - -import java.net.InetSocketAddress; -import java.net.URLConnection; -import java.util.List; -import java.util.Locale; - -/** - * Describes a proxy configuration. - * - * Proxy configurations are already integrated within the {@code java.net} and - * Apache HTTP stack. So {@link URLConnection} and Apache's {@code HttpClient} will use - * them automatically. - * - * Other HTTP stacks will need to obtain the proxy info by watching for the - * {@link Proxy#PROXY_CHANGE_ACTION} broadcast and calling methods such as - * {@link android.net.ConnectivityManager#getDefaultProxy}. - */ -public class ProxyInfo implements Parcelable { - - private final String mHost; - private final int mPort; - private final String mExclusionList; - private final String[] mParsedExclusionList; - private final Uri mPacFileUrl; - - /** - *@hide - */ - public static final String LOCAL_EXCL_LIST = ""; - /** - *@hide - */ - public static final int LOCAL_PORT = -1; - /** - *@hide - */ - public static final String LOCAL_HOST = "localhost"; - - /** - * Constructs a {@link ProxyInfo} object that points at a Direct proxy - * on the specified host and port. - */ - public static ProxyInfo buildDirectProxy(String host, int port) { - return new ProxyInfo(host, port, null); - } - - /** - * Constructs a {@link ProxyInfo} object that points at a Direct proxy - * on the specified host and port. - * - * The proxy will not be used to access any host in exclusion list, exclList. - * - * @param exclList Hosts to exclude using the proxy on connections for. These - * hosts can use wildcards such as *.example.com. - */ - public static ProxyInfo buildDirectProxy(String host, int port, List exclList) { - String[] array = exclList.toArray(new String[exclList.size()]); - return new ProxyInfo(host, port, TextUtils.join(",", array), array); - } - - /** - * Construct a {@link ProxyInfo} that will download and run the PAC script - * at the specified URL. - */ - public static ProxyInfo buildPacProxy(Uri pacUri) { - return new ProxyInfo(pacUri); - } - - /** - * Construct a {@link ProxyInfo} object that will download and run the PAC script at the - * specified URL and port. - */ - @NonNull - public static ProxyInfo buildPacProxy(@NonNull Uri pacUrl, int port) { - return new ProxyInfo(pacUrl, port); - } - - /** - * Create a ProxyProperties that points at a HTTP Proxy. - * @hide - */ - @UnsupportedAppUsage - public ProxyInfo(String host, int port, String exclList) { - mHost = host; - mPort = port; - mExclusionList = exclList; - mParsedExclusionList = parseExclusionList(mExclusionList); - mPacFileUrl = Uri.EMPTY; - } - - /** - * Create a ProxyProperties that points at a PAC URL. - * @hide - */ - public ProxyInfo(@NonNull Uri pacFileUrl) { - mHost = LOCAL_HOST; - mPort = LOCAL_PORT; - mExclusionList = LOCAL_EXCL_LIST; - mParsedExclusionList = parseExclusionList(mExclusionList); - if (pacFileUrl == null) { - throw new NullPointerException(); - } - mPacFileUrl = pacFileUrl; - } - - /** - * Only used in PacProxyService after Local Proxy is bound. - * @hide - */ - public ProxyInfo(@NonNull Uri pacFileUrl, int localProxyPort) { - mHost = LOCAL_HOST; - mPort = localProxyPort; - mExclusionList = LOCAL_EXCL_LIST; - mParsedExclusionList = parseExclusionList(mExclusionList); - if (pacFileUrl == null) { - throw new NullPointerException(); - } - mPacFileUrl = pacFileUrl; - } - - private static String[] parseExclusionList(String exclusionList) { - if (exclusionList == null) { - return new String[0]; - } else { - return exclusionList.toLowerCase(Locale.ROOT).split(","); - } - } - - private ProxyInfo(String host, int port, String exclList, String[] parsedExclList) { - mHost = host; - mPort = port; - mExclusionList = exclList; - mParsedExclusionList = parsedExclList; - mPacFileUrl = Uri.EMPTY; - } - - /** - * A copy constructor to hold proxy properties. - */ - public ProxyInfo(@Nullable ProxyInfo source) { - if (source != null) { - mHost = source.getHost(); - mPort = source.getPort(); - mPacFileUrl = source.mPacFileUrl; - mExclusionList = source.getExclusionListAsString(); - mParsedExclusionList = source.mParsedExclusionList; - } else { - mHost = null; - mPort = 0; - mExclusionList = null; - mParsedExclusionList = null; - mPacFileUrl = Uri.EMPTY; - } - } - - /** - * @hide - */ - public InetSocketAddress getSocketAddress() { - InetSocketAddress inetSocketAddress = null; - try { - inetSocketAddress = new InetSocketAddress(mHost, mPort); - } catch (IllegalArgumentException e) { } - return inetSocketAddress; - } - - /** - * Returns the URL of the current PAC script or null if there is - * no PAC script. - */ - public Uri getPacFileUrl() { - return mPacFileUrl; - } - - /** - * When configured to use a Direct Proxy this returns the host - * of the proxy. - */ - public String getHost() { - return mHost; - } - - /** - * When configured to use a Direct Proxy this returns the port - * of the proxy - */ - public int getPort() { - return mPort; - } - - /** - * When configured to use a Direct Proxy this returns the list - * of hosts for which the proxy is ignored. - */ - public String[] getExclusionList() { - return mParsedExclusionList; - } - - /** - * comma separated - * @hide - */ - @Nullable - public String getExclusionListAsString() { - return mExclusionList; - } - - /** - * Return true if the pattern of proxy is valid, otherwise return false. - */ - public boolean isValid() { - if (!Uri.EMPTY.equals(mPacFileUrl)) return true; - return ProxyUtils.PROXY_VALID == ProxyUtils.validate(mHost == null ? "" : mHost, - mPort == 0 ? "" : Integer.toString(mPort), - mExclusionList == null ? "" : mExclusionList); - } - - /** - * @hide - */ - public java.net.Proxy makeProxy() { - java.net.Proxy proxy = java.net.Proxy.NO_PROXY; - if (mHost != null) { - try { - InetSocketAddress inetSocketAddress = new InetSocketAddress(mHost, mPort); - proxy = new java.net.Proxy(java.net.Proxy.Type.HTTP, inetSocketAddress); - } catch (IllegalArgumentException e) { - } - } - return proxy; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - if (!Uri.EMPTY.equals(mPacFileUrl)) { - sb.append("PAC Script: "); - sb.append(mPacFileUrl); - } - if (mHost != null) { - sb.append("["); - sb.append(mHost); - sb.append("] "); - sb.append(Integer.toString(mPort)); - if (mExclusionList != null) { - sb.append(" xl=").append(mExclusionList); - } - } else { - sb.append("[ProxyProperties.mHost == null]"); - } - return sb.toString(); - } - - @Override - public boolean equals(@Nullable Object o) { - if (!(o instanceof ProxyInfo)) return false; - ProxyInfo p = (ProxyInfo)o; - // If PAC URL is present in either then they must be equal. - // Other parameters will only be for fall back. - if (!Uri.EMPTY.equals(mPacFileUrl)) { - return mPacFileUrl.equals(p.getPacFileUrl()) && mPort == p.mPort; - } - if (!Uri.EMPTY.equals(p.mPacFileUrl)) { - return false; - } - if (mExclusionList != null && !mExclusionList.equals(p.getExclusionListAsString())) { - return false; - } - if (mHost != null && p.getHost() != null && mHost.equals(p.getHost()) == false) { - return false; - } - if (mHost != null && p.mHost == null) return false; - if (mHost == null && p.mHost != null) return false; - if (mPort != p.mPort) return false; - return true; - } - - /** - * Implement the Parcelable interface - * @hide - */ - public int describeContents() { - return 0; - } - - @Override - /* - * generate hashcode based on significant fields - */ - public int hashCode() { - return ((null == mHost) ? 0 : mHost.hashCode()) - + ((null == mExclusionList) ? 0 : mExclusionList.hashCode()) - + mPort; - } - - /** - * Implement the Parcelable interface. - * @hide - */ - public void writeToParcel(Parcel dest, int flags) { - if (!Uri.EMPTY.equals(mPacFileUrl)) { - dest.writeByte((byte)1); - mPacFileUrl.writeToParcel(dest, 0); - dest.writeInt(mPort); - return; - } else { - dest.writeByte((byte)0); - } - if (mHost != null) { - dest.writeByte((byte)1); - dest.writeString(mHost); - dest.writeInt(mPort); - } else { - dest.writeByte((byte)0); - } - dest.writeString(mExclusionList); - dest.writeStringArray(mParsedExclusionList); - } - - public static final @android.annotation.NonNull Creator CREATOR = - new Creator() { - public ProxyInfo createFromParcel(Parcel in) { - String host = null; - int port = 0; - if (in.readByte() != 0) { - Uri url = Uri.CREATOR.createFromParcel(in); - int localPort = in.readInt(); - return new ProxyInfo(url, localPort); - } - if (in.readByte() != 0) { - host = in.readString(); - port = in.readInt(); - } - String exclList = in.readString(); - String[] parsedExclList = in.createStringArray(); - ProxyInfo proxyProperties = new ProxyInfo(host, port, exclList, parsedExclList); - return proxyProperties; - } - - public ProxyInfo[] newArray(int size) { - return new ProxyInfo[size]; - } - }; -} diff --git a/packages/Connectivity/framework/src/android/net/QosCallback.java b/packages/Connectivity/framework/src/android/net/QosCallback.java deleted file mode 100644 index 22f06bc0e690c..0000000000000 --- a/packages/Connectivity/framework/src/android/net/QosCallback.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.NonNull; -import android.annotation.SystemApi; - -import java.util.concurrent.Executor; - -/** - * Receives Qos information given a {@link Network}. The callback is registered with - * {@link ConnectivityManager#registerQosCallback}. - * - *

    - *
    - * The callback will no longer receive calls if any of the following takes place: - *

      - *
    1. {@link ConnectivityManager#unregisterQosCallback(QosCallback)} is called with the same - * callback instance.
    2. - *
    3. {@link QosCallback#onError(QosCallbackException)} is called.
    4. - *
    5. A network specific issue occurs. eg. Congestion on a carrier network.
    6. - *
    7. The network registered with the callback has no associated QoS providers
    8. - * - * {@hide} - */ -@SystemApi -public abstract class QosCallback { - /** - * Invoked after an error occurs on a registered callback. Once called, the callback is - * automatically unregistered and the callback will no longer receive calls. - * - *

      The underlying exception can either be a runtime exception or a custom exception made for - * {@link QosCallback}. see: {@link QosCallbackException}. - * - * @param exception wraps the underlying cause - */ - public void onError(@NonNull final QosCallbackException exception) { - } - - /** - * Called when a Qos Session first becomes available to the callback or if its attributes have - * changed. - *

      - * Note: The callback may be called multiple times with the same attributes. - * - * @param session the available session - * @param sessionAttributes the attributes of the session - */ - public void onQosSessionAvailable(@NonNull final QosSession session, - @NonNull final QosSessionAttributes sessionAttributes) { - } - - /** - * Called after a Qos Session is lost. - *

      - * At least one call to - * {@link QosCallback#onQosSessionAvailable(QosSession, QosSessionAttributes)} - * with the same {@link QosSession} will precede a call to lost. - * - * @param session the lost session - */ - public void onQosSessionLost(@NonNull final QosSession session) { - } - - /** - * Thrown when there is a problem registering {@link QosCallback} with - * {@link ConnectivityManager#registerQosCallback(QosSocketInfo, QosCallback, Executor)}. - */ - public static class QosCallbackRegistrationException extends RuntimeException { - /** - * @hide - */ - public QosCallbackRegistrationException() { - super(); - } - } -} diff --git a/packages/Connectivity/framework/src/android/net/QosCallbackConnection.java b/packages/Connectivity/framework/src/android/net/QosCallbackConnection.java deleted file mode 100644 index de0fc243b43be..0000000000000 --- a/packages/Connectivity/framework/src/android/net/QosCallbackConnection.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.telephony.data.EpsBearerQosSessionAttributes; -import android.telephony.data.NrQosSessionAttributes; - -import com.android.internal.annotations.VisibleForTesting; - -import java.util.Objects; -import java.util.concurrent.Executor; - -/** - * Sends messages from {@link com.android.server.ConnectivityService} to the registered - * {@link QosCallback}. - *

      - * This is a satellite class of {@link ConnectivityManager} and not meant - * to be used in other contexts. - * - * @hide - */ -class QosCallbackConnection extends android.net.IQosCallback.Stub { - - @NonNull private final ConnectivityManager mConnectivityManager; - @Nullable private volatile QosCallback mCallback; - @NonNull private final Executor mExecutor; - - @VisibleForTesting - @Nullable - public QosCallback getCallback() { - return mCallback; - } - - /** - * The constructor for the connection - * - * @param connectivityManager the mgr that created this connection - * @param callback the callback to send messages back to - * @param executor The executor on which the callback will be invoked. The provided - * {@link Executor} must run callback sequentially, otherwise the order of - * callbacks cannot be guaranteed. - */ - QosCallbackConnection(@NonNull final ConnectivityManager connectivityManager, - @NonNull final QosCallback callback, - @NonNull final Executor executor) { - mConnectivityManager = Objects.requireNonNull(connectivityManager, - "connectivityManager must be non-null"); - mCallback = Objects.requireNonNull(callback, "callback must be non-null"); - mExecutor = Objects.requireNonNull(executor, "executor must be non-null"); - } - - /** - * Called when either the {@link EpsBearerQosSessionAttributes} has changed or on the first time - * the attributes have become available. - * - * @param session the session that is now available - * @param attributes the corresponding attributes of session - */ - @Override - public void onQosEpsBearerSessionAvailable(@NonNull final QosSession session, - @NonNull final EpsBearerQosSessionAttributes attributes) { - - mExecutor.execute(() -> { - final QosCallback callback = mCallback; - if (callback != null) { - callback.onQosSessionAvailable(session, attributes); - } - }); - } - - /** - * Called when either the {@link NrQosSessionAttributes} has changed or on the first time - * the attributes have become available. - * - * @param session the session that is now available - * @param attributes the corresponding attributes of session - */ - @Override - public void onNrQosSessionAvailable(@NonNull final QosSession session, - @NonNull final NrQosSessionAttributes attributes) { - - mExecutor.execute(() -> { - final QosCallback callback = mCallback; - if (callback != null) { - callback.onQosSessionAvailable(session, attributes); - } - }); - } - - /** - * Called when the session is lost. - * - * @param session the session that was lost - */ - @Override - public void onQosSessionLost(@NonNull final QosSession session) { - mExecutor.execute(() -> { - final QosCallback callback = mCallback; - if (callback != null) { - callback.onQosSessionLost(session); - } - }); - } - - /** - * Called when there is an error on the registered callback. - * - * @param errorType the type of error - */ - @Override - public void onError(@QosCallbackException.ExceptionType final int errorType) { - mExecutor.execute(() -> { - final QosCallback callback = mCallback; - if (callback != null) { - // Messages no longer need to be received since there was an error. - stopReceivingMessages(); - mConnectivityManager.unregisterQosCallback(callback); - callback.onError(QosCallbackException.createException(errorType)); - } - }); - } - - /** - * The callback will stop receiving messages. - *

      - * There are no synchronization guarantees on exactly when the callback will stop receiving - * messages. - */ - void stopReceivingMessages() { - mCallback = null; - } -} diff --git a/packages/Connectivity/framework/src/android/net/QosCallbackException.java b/packages/Connectivity/framework/src/android/net/QosCallbackException.java deleted file mode 100644 index 7fd9a527e2ac2..0000000000000 --- a/packages/Connectivity/framework/src/android/net/QosCallbackException.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.SystemApi; -import android.util.Log; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * This is the exception type passed back through the onError method on {@link QosCallback}. - * {@link QosCallbackException#getCause()} contains the actual error that caused this exception. - * - * The possible exception types as causes are: - * 1. {@link NetworkReleasedException} - * 2. {@link SocketNotBoundException} - * 3. {@link UnsupportedOperationException} - * 4. {@link SocketLocalAddressChangedException} - * - * @hide - */ -@SystemApi -public final class QosCallbackException extends Exception { - - /** @hide */ - @IntDef(prefix = {"EX_TYPE_"}, value = { - EX_TYPE_FILTER_NONE, - EX_TYPE_FILTER_NETWORK_RELEASED, - EX_TYPE_FILTER_SOCKET_NOT_BOUND, - EX_TYPE_FILTER_NOT_SUPPORTED, - EX_TYPE_FILTER_SOCKET_LOCAL_ADDRESS_CHANGED, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface ExceptionType {} - - private static final String TAG = "QosCallbackException"; - - // Types of exceptions supported // - /** {@hide} */ - public static final int EX_TYPE_FILTER_NONE = 0; - - /** {@hide} */ - public static final int EX_TYPE_FILTER_NETWORK_RELEASED = 1; - - /** {@hide} */ - public static final int EX_TYPE_FILTER_SOCKET_NOT_BOUND = 2; - - /** {@hide} */ - public static final int EX_TYPE_FILTER_NOT_SUPPORTED = 3; - - /** {@hide} */ - public static final int EX_TYPE_FILTER_SOCKET_LOCAL_ADDRESS_CHANGED = 4; - - /** - * Creates exception based off of a type and message. Not all types of exceptions accept a - * custom message. - * - * {@hide} - */ - @NonNull - static QosCallbackException createException(@ExceptionType final int type) { - switch (type) { - case EX_TYPE_FILTER_NETWORK_RELEASED: - return new QosCallbackException(new NetworkReleasedException()); - case EX_TYPE_FILTER_SOCKET_NOT_BOUND: - return new QosCallbackException(new SocketNotBoundException()); - case EX_TYPE_FILTER_NOT_SUPPORTED: - return new QosCallbackException(new UnsupportedOperationException( - "This device does not support the specified filter")); - case EX_TYPE_FILTER_SOCKET_LOCAL_ADDRESS_CHANGED: - return new QosCallbackException( - new SocketLocalAddressChangedException()); - default: - Log.wtf(TAG, "create: No case setup for exception type: '" + type + "'"); - return new QosCallbackException( - new RuntimeException("Unknown exception code: " + type)); - } - } - - /** - * @hide - */ - public QosCallbackException(@NonNull final String message) { - super(message); - } - - /** - * @hide - */ - public QosCallbackException(@NonNull final Throwable cause) { - super(cause); - } -} diff --git a/packages/Connectivity/framework/src/android/net/QosFilter.java b/packages/Connectivity/framework/src/android/net/QosFilter.java deleted file mode 100644 index 957c867f206da..0000000000000 --- a/packages/Connectivity/framework/src/android/net/QosFilter.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.NonNull; -import android.annotation.SystemApi; - -import java.net.InetAddress; - -/** - * Provides the related filtering logic to the {@link NetworkAgent} to match {@link QosSession}s - * to their related {@link QosCallback}. - * - * Used by the {@link com.android.server.ConnectivityService} to validate a {@link QosCallback} - * is still able to receive a {@link QosSession}. - * - * @hide - */ -@SystemApi -public abstract class QosFilter { - - /** - * The constructor is kept hidden from outside this package to ensure that all derived types - * are known and properly handled when being passed to and from {@link NetworkAgent}. - * - * @hide - */ - QosFilter() { - } - - /** - * The network used with this filter. - * - * @return the registered {@link Network} - */ - @NonNull - public abstract Network getNetwork(); - - /** - * Validates that conditions have not changed such that no further {@link QosSession}s should - * be passed back to the {@link QosCallback} associated to this filter. - * - * @return the error code when present, otherwise the filter is valid - * - * @hide - */ - @QosCallbackException.ExceptionType - public abstract int validate(); - - /** - * Determines whether or not the parameters is a match for the filter. - * - * @param address the local address - * @param startPort the start of the port range - * @param endPort the end of the port range - * @return whether the parameters match the local address of the filter - */ - public abstract boolean matchesLocalAddress(@NonNull InetAddress address, - int startPort, int endPort); - - /** - * Determines whether or not the parameters is a match for the filter. - * - * @param address the remote address - * @param startPort the start of the port range - * @param endPort the end of the port range - * @return whether the parameters match the remote address of the filter - */ - public abstract boolean matchesRemoteAddress(@NonNull InetAddress address, - int startPort, int endPort); -} - diff --git a/packages/Connectivity/framework/src/android/net/QosFilterParcelable.java b/packages/Connectivity/framework/src/android/net/QosFilterParcelable.java deleted file mode 100644 index da3b2cf8ff7ae..0000000000000 --- a/packages/Connectivity/framework/src/android/net/QosFilterParcelable.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.os.Parcel; -import android.os.Parcelable; -import android.util.Log; - -import java.util.Objects; - -/** - * Aware of how to parcel different types of {@link QosFilter}s. Any new type of qos filter must - * have a specialized case written here. - *

      - * Specifically leveraged when transferring {@link QosFilter} from - * {@link com.android.server.ConnectivityService} to {@link NetworkAgent} when the filter is first - * registered. - *

      - * This is not meant to be used in other contexts. - * - * @hide - */ -public final class QosFilterParcelable implements Parcelable { - - private static final String LOG_TAG = QosFilterParcelable.class.getSimpleName(); - - // Indicates that the filter was not successfully written to the parcel. - private static final int NO_FILTER_PRESENT = 0; - - // The parcel is of type qos socket filter. - private static final int QOS_SOCKET_FILTER = 1; - - private final QosFilter mQosFilter; - - /** - * The underlying qos filter. - *

      - * Null only in the case parceling failed. - */ - @Nullable - public QosFilter getQosFilter() { - return mQosFilter; - } - - public QosFilterParcelable(@NonNull final QosFilter qosFilter) { - Objects.requireNonNull(qosFilter, "qosFilter must be non-null"); - - // NOTE: Normally a type check would belong here, but doing so breaks unit tests that rely - // on mocking qos filter. - mQosFilter = qosFilter; - } - - private QosFilterParcelable(final Parcel in) { - final int filterParcelType = in.readInt(); - - switch (filterParcelType) { - case QOS_SOCKET_FILTER: { - mQosFilter = new QosSocketFilter(QosSocketInfo.CREATOR.createFromParcel(in)); - break; - } - - case NO_FILTER_PRESENT: - default: { - mQosFilter = null; - } - } - } - - public static final Creator CREATOR = new Creator() { - @Override - public QosFilterParcelable createFromParcel(final Parcel in) { - return new QosFilterParcelable(in); - } - - @Override - public QosFilterParcelable[] newArray(final int size) { - return new QosFilterParcelable[size]; - } - }; - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(final Parcel dest, final int flags) { - if (mQosFilter instanceof QosSocketFilter) { - dest.writeInt(QOS_SOCKET_FILTER); - final QosSocketFilter qosSocketFilter = (QosSocketFilter) mQosFilter; - qosSocketFilter.getQosSocketInfo().writeToParcel(dest, 0); - return; - } - dest.writeInt(NO_FILTER_PRESENT); - Log.e(LOG_TAG, "Parceling failed, unknown type of filter present: " + mQosFilter); - } -} diff --git a/packages/Connectivity/framework/src/android/net/QosSession.java b/packages/Connectivity/framework/src/android/net/QosSession.java deleted file mode 100644 index 93f2ff2bf724c..0000000000000 --- a/packages/Connectivity/framework/src/android/net/QosSession.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.SystemApi; -import android.os.Parcel; -import android.os.Parcelable; - -/** - * Provides identifying information of a QoS session. Sent to an application through - * {@link QosCallback}. - * - * @hide - */ -@SystemApi -public final class QosSession implements Parcelable { - - /** - * The {@link QosSession} is a LTE EPS Session. - */ - public static final int TYPE_EPS_BEARER = 1; - - /** - * The {@link QosSession} is a NR Session. - */ - public static final int TYPE_NR_BEARER = 2; - - private final int mSessionId; - - private final int mSessionType; - - /** - * Gets the unique id of the session that is used to differentiate sessions across different - * types. - *

      - * Note: Different qos sessions can be provided by different actors. - * - * @return the unique id - */ - public long getUniqueId() { - return (long) mSessionType << 32 | mSessionId; - } - - /** - * Gets the session id that is unique within that type. - *

      - * Note: The session id is set by the actor providing the qos. It can be either manufactured by - * the actor, but also may have a particular meaning within that type. For example, using the - * bearer id as the session id for {@link android.telephony.data.EpsBearerQosSessionAttributes} - * is a straight forward way to keep the sessions unique from one another within that type. - * - * @return the id of the session - */ - public int getSessionId() { - return mSessionId; - } - - /** - * Gets the type of session. - */ - @QosSessionType - public int getSessionType() { - return mSessionType; - } - - /** - * Creates a {@link QosSession}. - * - * @param sessionId uniquely identifies the session across all sessions of the same type - * @param sessionType the type of session - */ - public QosSession(final int sessionId, @QosSessionType final int sessionType) { - //Ensures the session id is unique across types of sessions - mSessionId = sessionId; - mSessionType = sessionType; - } - - - @Override - public String toString() { - return "QosSession{" - + "mSessionId=" + mSessionId - + ", mSessionType=" + mSessionType - + '}'; - } - - /** - * Annotations for types of qos sessions. - */ - @IntDef(value = { - TYPE_EPS_BEARER, - TYPE_NR_BEARER, - }) - @interface QosSessionType {} - - private QosSession(final Parcel in) { - mSessionId = in.readInt(); - mSessionType = in.readInt(); - } - - @NonNull - public static final Creator CREATOR = new Creator() { - @NonNull - @Override - public QosSession createFromParcel(@NonNull final Parcel in) { - return new QosSession(in); - } - - @NonNull - @Override - public QosSession[] newArray(final int size) { - return new QosSession[size]; - } - }; - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(@NonNull final Parcel dest, final int flags) { - dest.writeInt(mSessionId); - dest.writeInt(mSessionType); - } -} diff --git a/packages/Connectivity/framework/src/android/net/QosSessionAttributes.java b/packages/Connectivity/framework/src/android/net/QosSessionAttributes.java deleted file mode 100644 index 7a885942d1b5c..0000000000000 --- a/packages/Connectivity/framework/src/android/net/QosSessionAttributes.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.SystemApi; - -/** - * Implemented by classes that encapsulate Qos related attributes that describe a Qos Session. - * - * Use the instanceof keyword to determine the underlying type. - * - * @hide - */ -@SystemApi -public interface QosSessionAttributes { -} diff --git a/packages/Connectivity/framework/src/android/net/QosSocketFilter.java b/packages/Connectivity/framework/src/android/net/QosSocketFilter.java deleted file mode 100644 index 69da7f4401853..0000000000000 --- a/packages/Connectivity/framework/src/android/net/QosSocketFilter.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static android.net.QosCallbackException.EX_TYPE_FILTER_NONE; -import static android.net.QosCallbackException.EX_TYPE_FILTER_SOCKET_LOCAL_ADDRESS_CHANGED; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.os.ParcelFileDescriptor; -import android.system.ErrnoException; -import android.system.Os; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; - -import java.io.FileDescriptor; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.net.SocketAddress; -import java.util.Objects; - -/** - * Filters a {@link QosSession} according to the binding on the provided {@link Socket}. - * - * @hide - */ -public class QosSocketFilter extends QosFilter { - - private static final String TAG = QosSocketFilter.class.getSimpleName(); - - @NonNull - private final QosSocketInfo mQosSocketInfo; - - /** - * Creates a {@link QosSocketFilter} based off of {@link QosSocketInfo}. - * - * @param qosSocketInfo the information required to filter and validate - */ - public QosSocketFilter(@NonNull final QosSocketInfo qosSocketInfo) { - Objects.requireNonNull(qosSocketInfo, "qosSocketInfo must be non-null"); - mQosSocketInfo = qosSocketInfo; - } - - /** - * Gets the parcelable qos socket info that was used to create the filter. - */ - @NonNull - public QosSocketInfo getQosSocketInfo() { - return mQosSocketInfo; - } - - /** - * Performs two validations: - * 1. If the socket is not bound, then return - * {@link QosCallbackException.EX_TYPE_FILTER_SOCKET_NOT_BOUND}. This is detected - * by checking the local address on the filter which becomes null when the socket is no - * longer bound. - * 2. In the scenario that the socket is now bound to a different local address, which can - * happen in the case of UDP, then - * {@link QosCallbackException.EX_TYPE_FILTER_SOCKET_LOCAL_ADDRESS_CHANGED} is returned. - * @return validation error code - */ - @Override - public int validate() { - final InetSocketAddress sa = getAddressFromFileDescriptor(); - if (sa == null) { - return QosCallbackException.EX_TYPE_FILTER_SOCKET_NOT_BOUND; - } - - if (!sa.equals(mQosSocketInfo.getLocalSocketAddress())) { - return EX_TYPE_FILTER_SOCKET_LOCAL_ADDRESS_CHANGED; - } - - return EX_TYPE_FILTER_NONE; - } - - /** - * The local address of the socket's binding. - * - * Note: If the socket is no longer bound, null is returned. - * - * @return the local address - */ - @Nullable - private InetSocketAddress getAddressFromFileDescriptor() { - final ParcelFileDescriptor parcelFileDescriptor = mQosSocketInfo.getParcelFileDescriptor(); - if (parcelFileDescriptor == null) return null; - - final FileDescriptor fd = parcelFileDescriptor.getFileDescriptor(); - if (fd == null) return null; - - final SocketAddress address; - try { - address = Os.getsockname(fd); - } catch (final ErrnoException e) { - Log.e(TAG, "getAddressFromFileDescriptor: getLocalAddress exception", e); - return null; - } - if (address instanceof InetSocketAddress) { - return (InetSocketAddress) address; - } - return null; - } - - /** - * The network used with this filter. - * - * @return the registered {@link Network} - */ - @NonNull - @Override - public Network getNetwork() { - return mQosSocketInfo.getNetwork(); - } - - /** - * @inheritDoc - */ - @Override - public boolean matchesLocalAddress(@NonNull final InetAddress address, final int startPort, - final int endPort) { - if (mQosSocketInfo.getLocalSocketAddress() == null) { - return false; - } - return matchesAddress(mQosSocketInfo.getLocalSocketAddress(), address, startPort, - endPort); - } - - /** - * @inheritDoc - */ - @Override - public boolean matchesRemoteAddress(@NonNull final InetAddress address, final int startPort, - final int endPort) { - if (mQosSocketInfo.getRemoteSocketAddress() == null) { - return false; - } - return matchesAddress(mQosSocketInfo.getRemoteSocketAddress(), address, startPort, - endPort); - } - - /** - * Called from {@link QosSocketFilter#matchesLocalAddress(InetAddress, int, int)} - * and {@link QosSocketFilter#matchesRemoteAddress(InetAddress, int, int)} with the - * filterSocketAddress coming from {@link QosSocketInfo#getLocalSocketAddress()}. - *

      - * This method exists for testing purposes since {@link QosSocketInfo} couldn't be mocked - * due to being final. - * - * @param filterSocketAddress the socket address of the filter - * @param address the address to compare the filterSocketAddressWith - * @param startPort the start of the port range to check - * @param endPort the end of the port range to check - */ - @VisibleForTesting - public static boolean matchesAddress(@NonNull final InetSocketAddress filterSocketAddress, - @NonNull final InetAddress address, - final int startPort, final int endPort) { - return startPort <= filterSocketAddress.getPort() - && endPort >= filterSocketAddress.getPort() - && filterSocketAddress.getAddress().equals(address); - } -} diff --git a/packages/Connectivity/framework/src/android/net/QosSocketInfo.java b/packages/Connectivity/framework/src/android/net/QosSocketInfo.java deleted file mode 100644 index a45d5075d6c77..0000000000000 --- a/packages/Connectivity/framework/src/android/net/QosSocketInfo.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SystemApi; -import android.os.Parcel; -import android.os.ParcelFileDescriptor; -import android.os.Parcelable; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.net.UnknownHostException; -import java.util.Objects; - -/** - * Used in conjunction with - * {@link ConnectivityManager#registerQosCallback} - * in order to receive Qos Sessions related to the local address and port of a bound {@link Socket} - * and/or remote address and port of a connected {@link Socket}. - * - * @hide - */ -@SystemApi -public final class QosSocketInfo implements Parcelable { - - @NonNull - private final Network mNetwork; - - @NonNull - private final ParcelFileDescriptor mParcelFileDescriptor; - - @NonNull - private final InetSocketAddress mLocalSocketAddress; - - @Nullable - private final InetSocketAddress mRemoteSocketAddress; - - /** - * The {@link Network} the socket is on. - * - * @return the registered {@link Network} - */ - @NonNull - public Network getNetwork() { - return mNetwork; - } - - /** - * The parcel file descriptor wrapped around the socket's file descriptor. - * - * @return the parcel file descriptor of the socket - */ - @NonNull - ParcelFileDescriptor getParcelFileDescriptor() { - return mParcelFileDescriptor; - } - - /** - * The local address of the socket passed into {@link QosSocketInfo(Network, Socket)}. - * The value does not reflect any changes that occur to the socket after it is first set - * in the constructor. - * - * @return the local address of the socket - */ - @NonNull - public InetSocketAddress getLocalSocketAddress() { - return mLocalSocketAddress; - } - - /** - * The remote address of the socket passed into {@link QosSocketInfo(Network, Socket)}. - * The value does not reflect any changes that occur to the socket after it is first set - * in the constructor. - * - * @return the remote address of the socket if socket is connected, null otherwise - */ - @Nullable - public InetSocketAddress getRemoteSocketAddress() { - return mRemoteSocketAddress; - } - - /** - * Creates a {@link QosSocketInfo} given a {@link Network} and bound {@link Socket}. The - * {@link Socket} must remain bound in order to receive {@link QosSession}s. - * - * @param network the network - * @param socket the bound {@link Socket} - */ - public QosSocketInfo(@NonNull final Network network, @NonNull final Socket socket) - throws IOException { - Objects.requireNonNull(socket, "socket cannot be null"); - - mNetwork = Objects.requireNonNull(network, "network cannot be null"); - mParcelFileDescriptor = ParcelFileDescriptor.fromSocket(socket); - mLocalSocketAddress = - new InetSocketAddress(socket.getLocalAddress(), socket.getLocalPort()); - - if (socket.isConnected()) { - mRemoteSocketAddress = (InetSocketAddress) socket.getRemoteSocketAddress(); - } else { - mRemoteSocketAddress = null; - } - } - - /* Parcelable methods */ - private QosSocketInfo(final Parcel in) { - mNetwork = Objects.requireNonNull(Network.CREATOR.createFromParcel(in)); - mParcelFileDescriptor = ParcelFileDescriptor.CREATOR.createFromParcel(in); - - final int localAddressLength = in.readInt(); - mLocalSocketAddress = readSocketAddress(in, localAddressLength); - - final int remoteAddressLength = in.readInt(); - mRemoteSocketAddress = remoteAddressLength == 0 ? null - : readSocketAddress(in, remoteAddressLength); - } - - private @NonNull InetSocketAddress readSocketAddress(final Parcel in, final int addressLength) { - final byte[] address = new byte[addressLength]; - in.readByteArray(address); - final int port = in.readInt(); - - try { - return new InetSocketAddress(InetAddress.getByAddress(address), port); - } catch (final UnknownHostException e) { - /* This can never happen. UnknownHostException will never be thrown - since the address provided is numeric and non-null. */ - throw new RuntimeException("UnknownHostException on numeric address", e); - } - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(@NonNull final Parcel dest, final int flags) { - mNetwork.writeToParcel(dest, 0); - mParcelFileDescriptor.writeToParcel(dest, 0); - - final byte[] localAddress = mLocalSocketAddress.getAddress().getAddress(); - dest.writeInt(localAddress.length); - dest.writeByteArray(localAddress); - dest.writeInt(mLocalSocketAddress.getPort()); - - if (mRemoteSocketAddress == null) { - dest.writeInt(0); - } else { - final byte[] remoteAddress = mRemoteSocketAddress.getAddress().getAddress(); - dest.writeInt(remoteAddress.length); - dest.writeByteArray(remoteAddress); - dest.writeInt(mRemoteSocketAddress.getPort()); - } - } - - @NonNull - public static final Parcelable.Creator CREATOR = - new Parcelable.Creator() { - @NonNull - @Override - public QosSocketInfo createFromParcel(final Parcel in) { - return new QosSocketInfo(in); - } - - @NonNull - @Override - public QosSocketInfo[] newArray(final int size) { - return new QosSocketInfo[size]; - } - }; -} diff --git a/packages/Connectivity/framework/src/android/net/RouteInfo.java b/packages/Connectivity/framework/src/android/net/RouteInfo.java deleted file mode 100644 index fad3144a4b80a..0000000000000 --- a/packages/Connectivity/framework/src/android/net/RouteInfo.java +++ /dev/null @@ -1,659 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SystemApi; -import android.compat.annotation.UnsupportedAppUsage; -import android.os.Build; -import android.os.Parcel; -import android.os.Parcelable; - -import com.android.net.module.util.NetUtils; -import com.android.net.module.util.NetworkStackConstants; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.Collection; -import java.util.Objects; - -/** - * Represents a network route. - *

      - * This is used both to describe static network configuration and live network - * configuration information. - * - * A route contains three pieces of information: - *

        - *
      • a destination {@link IpPrefix} specifying the network destinations covered by this route. - * If this is {@code null} it indicates a default route of the address family (IPv4 or IPv6) - * implied by the gateway IP address. - *
      • a gateway {@link InetAddress} indicating the next hop to use. If this is {@code null} it - * indicates a directly-connected route. - *
      • an interface (which may be unspecified). - *
      - * Either the destination or the gateway may be {@code null}, but not both. If the - * destination and gateway are both specified, they must be of the same address family - * (IPv4 or IPv6). - */ -public final class RouteInfo implements Parcelable { - /** @hide */ - @IntDef(value = { - RTN_UNICAST, - RTN_UNREACHABLE, - RTN_THROW, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface RouteType {} - - /** - * The IP destination address for this route. - */ - @NonNull - private final IpPrefix mDestination; - - /** - * The gateway address for this route. - */ - @UnsupportedAppUsage - @Nullable - private final InetAddress mGateway; - - /** - * The interface for this route. - */ - @Nullable - private final String mInterface; - - - /** Unicast route. @hide */ - @SystemApi - public static final int RTN_UNICAST = 1; - - /** Unreachable route. @hide */ - @SystemApi - public static final int RTN_UNREACHABLE = 7; - - /** Throw route. @hide */ - @SystemApi - public static final int RTN_THROW = 9; - - /** - * The type of this route; one of the RTN_xxx constants above. - */ - private final int mType; - - /** - * The maximum transmission unit size for this route. - */ - private final int mMtu; - - // Derived data members. - // TODO: remove these. - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) - private final boolean mIsHost; - private final boolean mHasGateway; - - /** - * Constructs a RouteInfo object. - * - * If destination is null, then gateway must be specified and the - * constructed route is either the IPv4 default route 0.0.0.0 - * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default - * route ::/0 if gateway is an instance of - * {@link Inet6Address}. - *

      - * destination and gateway may not both be null. - * - * @param destination the destination prefix - * @param gateway the IP address to route packets through - * @param iface the interface name to send packets on - * @param type the type of this route - * - * @hide - */ - @SystemApi - public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway, - @Nullable String iface, @RouteType int type) { - this(destination, gateway, iface, type, 0); - } - - /** - * Constructs a RouteInfo object. - * - * If destination is null, then gateway must be specified and the - * constructed route is either the IPv4 default route 0.0.0.0 - * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default - * route ::/0 if gateway is an instance of - * {@link Inet6Address}. - *

      - * destination and gateway may not both be null. - * - * @param destination the destination prefix - * @param gateway the IP address to route packets through - * @param iface the interface name to send packets on - * @param type the type of this route - * @param mtu the maximum transmission unit size for this route - * - * @hide - */ - @SystemApi - public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway, - @Nullable String iface, @RouteType int type, int mtu) { - switch (type) { - case RTN_UNICAST: - case RTN_UNREACHABLE: - case RTN_THROW: - // TODO: It would be nice to ensure that route types that don't have nexthops or - // interfaces, such as unreachable or throw, can't be created if an interface or - // a gateway is specified. This is a bit too complicated to do at the moment - // because: - // - // - LinkProperties sets the interface on routes added to it, and modifies the - // interfaces of all the routes when its interface name changes. - // - Even when the gateway is null, we store a non-null gateway here. - // - // For now, we just rely on the code that sets routes to do things properly. - break; - default: - throw new IllegalArgumentException("Unknown route type " + type); - } - - if (destination == null) { - if (gateway != null) { - if (gateway instanceof Inet4Address) { - destination = new IpPrefix(NetworkStackConstants.IPV4_ADDR_ANY, 0); - } else { - destination = new IpPrefix(NetworkStackConstants.IPV6_ADDR_ANY, 0); - } - } else { - // no destination, no gateway. invalid. - throw new IllegalArgumentException("Invalid arguments passed in: " + gateway + "," + - destination); - } - } - // TODO: set mGateway to null if there is no gateway. This is more correct, saves space, and - // matches the documented behaviour. Before we can do this we need to fix all callers (e.g., - // ConnectivityService) to stop doing things like r.getGateway().equals(), ... . - if (gateway == null) { - if (destination.getAddress() instanceof Inet4Address) { - gateway = NetworkStackConstants.IPV4_ADDR_ANY; - } else { - gateway = NetworkStackConstants.IPV6_ADDR_ANY; - } - } - mHasGateway = (!gateway.isAnyLocalAddress()); - - if ((destination.getAddress() instanceof Inet4Address - && !(gateway instanceof Inet4Address)) - || (destination.getAddress() instanceof Inet6Address - && !(gateway instanceof Inet6Address))) { - throw new IllegalArgumentException("address family mismatch in RouteInfo constructor"); - } - mDestination = destination; // IpPrefix objects are immutable. - mGateway = gateway; // InetAddress objects are immutable. - mInterface = iface; // Strings are immutable. - mType = type; - mIsHost = isHost(); - mMtu = mtu; - } - - /** - * Constructs a {@code RouteInfo} object. - * - * If destination is null, then gateway must be specified and the - * constructed route is either the IPv4 default route 0.0.0.0 - * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default - * route ::/0 if gateway is an instance of {@link Inet6Address}. - *

      - * Destination and gateway may not both be null. - * - * @param destination the destination address and prefix in an {@link IpPrefix} - * @param gateway the {@link InetAddress} to route packets through - * @param iface the interface name to send packets on - * - * @hide - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway, - @Nullable String iface) { - this(destination, gateway, iface, RTN_UNICAST); - } - - /** - * @hide - */ - @UnsupportedAppUsage - public RouteInfo(@Nullable LinkAddress destination, @Nullable InetAddress gateway, - @Nullable String iface) { - this(destination == null ? null : - new IpPrefix(destination.getAddress(), destination.getPrefixLength()), - gateway, iface); - } - - /** - * Constructs a {@code RouteInfo} object. - * - * If destination is null, then gateway must be specified and the - * constructed route is either the IPv4 default route 0.0.0.0 - * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default - * route ::/0 if gateway is an instance of {@link Inet6Address}. - *

      - * Destination and gateway may not both be null. - * - * @param destination the destination address and prefix in an {@link IpPrefix} - * @param gateway the {@link InetAddress} to route packets through - * - * @hide - */ - public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway) { - this(destination, gateway, null); - } - - /** - * @hide - * - * TODO: Remove this. - */ - @UnsupportedAppUsage - public RouteInfo(@Nullable LinkAddress destination, @Nullable InetAddress gateway) { - this(destination, gateway, null); - } - - /** - * Constructs a default {@code RouteInfo} object. - * - * @param gateway the {@link InetAddress} to route packets through - * - * @hide - */ - @UnsupportedAppUsage - public RouteInfo(@NonNull InetAddress gateway) { - this((IpPrefix) null, gateway, null); - } - - /** - * Constructs a {@code RouteInfo} object representing a direct connected subnet. - * - * @param destination the {@link IpPrefix} describing the address and prefix - * length of the subnet. - * - * @hide - */ - public RouteInfo(@NonNull IpPrefix destination) { - this(destination, null, null); - } - - /** - * @hide - */ - public RouteInfo(@NonNull LinkAddress destination) { - this(destination, null, null); - } - - /** - * @hide - */ - public RouteInfo(@NonNull IpPrefix destination, @RouteType int type) { - this(destination, null, null, type); - } - - /** - * @hide - */ - public static RouteInfo makeHostRoute(@NonNull InetAddress host, @Nullable String iface) { - return makeHostRoute(host, null, iface); - } - - /** - * @hide - */ - public static RouteInfo makeHostRoute(@Nullable InetAddress host, @Nullable InetAddress gateway, - @Nullable String iface) { - if (host == null) return null; - - if (host instanceof Inet4Address) { - return new RouteInfo(new IpPrefix(host, 32), gateway, iface); - } else { - return new RouteInfo(new IpPrefix(host, 128), gateway, iface); - } - } - - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) - private boolean isHost() { - return (mDestination.getAddress() instanceof Inet4Address && - mDestination.getPrefixLength() == 32) || - (mDestination.getAddress() instanceof Inet6Address && - mDestination.getPrefixLength() == 128); - } - - /** - * Retrieves the destination address and prefix length in the form of an {@link IpPrefix}. - * - * @return {@link IpPrefix} specifying the destination. This is never {@code null}. - */ - @NonNull - public IpPrefix getDestination() { - return mDestination; - } - - /** - * TODO: Convert callers to use IpPrefix and then remove. - * @hide - */ - @NonNull - public LinkAddress getDestinationLinkAddress() { - return new LinkAddress(mDestination.getAddress(), mDestination.getPrefixLength()); - } - - /** - * Retrieves the gateway or next hop {@link InetAddress} for this route. - * - * @return {@link InetAddress} specifying the gateway or next hop. This may be - * {@code null} for a directly-connected route." - */ - @Nullable - public InetAddress getGateway() { - return mGateway; - } - - /** - * Retrieves the interface used for this route if specified, else {@code null}. - * - * @return The name of the interface used for this route. - */ - @Nullable - public String getInterface() { - return mInterface; - } - - /** - * Retrieves the type of this route. - * - * @return The type of this route; one of the {@code RTN_xxx} constants defined in this class. - * - * @hide - */ - @SystemApi - @RouteType - public int getType() { - return mType; - } - - /** - * Retrieves the MTU size for this route. - * - * @return The MTU size, or 0 if it has not been set. - * @hide - */ - @SystemApi - public int getMtu() { - return mMtu; - } - - /** - * Indicates if this route is a default route (ie, has no destination specified). - * - * @return {@code true} if the destination has a prefix length of 0. - */ - public boolean isDefaultRoute() { - return mType == RTN_UNICAST && mDestination.getPrefixLength() == 0; - } - - /** - * Indicates if this route is an unreachable default route. - * - * @return {@code true} if it's an unreachable route with prefix length of 0. - * @hide - */ - private boolean isUnreachableDefaultRoute() { - return mType == RTN_UNREACHABLE && mDestination.getPrefixLength() == 0; - } - - /** - * Indicates if this route is an IPv4 default route. - * @hide - */ - public boolean isIPv4Default() { - return isDefaultRoute() && mDestination.getAddress() instanceof Inet4Address; - } - - /** - * Indicates if this route is an IPv4 unreachable default route. - * @hide - */ - public boolean isIPv4UnreachableDefault() { - return isUnreachableDefaultRoute() && mDestination.getAddress() instanceof Inet4Address; - } - - /** - * Indicates if this route is an IPv6 default route. - * @hide - */ - public boolean isIPv6Default() { - return isDefaultRoute() && mDestination.getAddress() instanceof Inet6Address; - } - - /** - * Indicates if this route is an IPv6 unreachable default route. - * @hide - */ - public boolean isIPv6UnreachableDefault() { - return isUnreachableDefaultRoute() && mDestination.getAddress() instanceof Inet6Address; - } - - /** - * Indicates if this route is a host route (ie, matches only a single host address). - * - * @return {@code true} if the destination has a prefix length of 32 or 128 for IPv4 or IPv6, - * respectively. - * @hide - */ - public boolean isHostRoute() { - return mIsHost; - } - - /** - * Indicates if this route has a next hop ({@code true}) or is directly-connected - * ({@code false}). - * - * @return {@code true} if a gateway is specified - */ - public boolean hasGateway() { - return mHasGateway; - } - - /** - * Determines whether the destination and prefix of this route includes the specified - * address. - * - * @param destination A {@link InetAddress} to test to see if it would match this route. - * @return {@code true} if the destination and prefix length cover the given address. - */ - public boolean matches(InetAddress destination) { - return mDestination.contains(destination); - } - - /** - * Find the route from a Collection of routes that best matches a given address. - * May return null if no routes are applicable. - * @param routes a Collection of RouteInfos to chose from - * @param dest the InetAddress your trying to get to - * @return the RouteInfo from the Collection that best fits the given address - * - * @hide - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - @Nullable - public static RouteInfo selectBestRoute(Collection routes, InetAddress dest) { - return NetUtils.selectBestRoute(routes, dest); - } - - /** - * Returns a human-readable description of this object. - */ - public String toString() { - String val = ""; - if (mDestination != null) val = mDestination.toString(); - if (mType == RTN_UNREACHABLE) { - val += " unreachable"; - } else if (mType == RTN_THROW) { - val += " throw"; - } else { - val += " ->"; - if (mGateway != null) val += " " + mGateway.getHostAddress(); - if (mInterface != null) val += " " + mInterface; - if (mType != RTN_UNICAST) { - val += " unknown type " + mType; - } - } - val += " mtu " + mMtu; - return val; - } - - /** - * Compares this RouteInfo object against the specified object and indicates if they are equal. - * @return {@code true} if the objects are equal, {@code false} otherwise. - */ - public boolean equals(@Nullable Object obj) { - if (this == obj) return true; - - if (!(obj instanceof RouteInfo)) return false; - - RouteInfo target = (RouteInfo) obj; - - return Objects.equals(mDestination, target.getDestination()) && - Objects.equals(mGateway, target.getGateway()) && - Objects.equals(mInterface, target.getInterface()) && - mType == target.getType() && mMtu == target.getMtu(); - } - - /** - * A helper class that contains the destination, the gateway and the interface in a - * {@code RouteInfo}, used by {@link ConnectivityService#updateRoutes} or - * {@link LinkProperties#addRoute} to calculate the list to be updated. - * {@code RouteInfo} objects with different interfaces are treated as different routes because - * *usually* on Android different interfaces use different routing tables, and moving a route - * to a new routing table never constitutes an update, but is always a remove and an add. - * - * @hide - */ - public static class RouteKey { - @NonNull private final IpPrefix mDestination; - @Nullable private final InetAddress mGateway; - @Nullable private final String mInterface; - - RouteKey(@NonNull IpPrefix destination, @Nullable InetAddress gateway, - @Nullable String iface) { - mDestination = destination; - mGateway = gateway; - mInterface = iface; - } - - @Override - public boolean equals(@Nullable Object o) { - if (!(o instanceof RouteKey)) { - return false; - } - RouteKey p = (RouteKey) o; - // No need to do anything special for scoped addresses. Inet6Address#equals does not - // consider the scope ID, but the netd route IPCs (e.g., INetd#networkAddRouteParcel) - // and the kernel ignore scoped addresses both in the prefix and in the nexthop and only - // look at RTA_OIF. - return Objects.equals(p.mDestination, mDestination) - && Objects.equals(p.mGateway, mGateway) - && Objects.equals(p.mInterface, mInterface); - } - - @Override - public int hashCode() { - return Objects.hash(mDestination, mGateway, mInterface); - } - } - - /** - * Get {@code RouteKey} of this {@code RouteInfo}. - * @return a {@code RouteKey} object. - * - * @hide - */ - @NonNull - public RouteKey getRouteKey() { - return new RouteKey(mDestination, mGateway, mInterface); - } - - /** - * Returns a hashcode for this RouteInfo object. - */ - public int hashCode() { - return (mDestination.hashCode() * 41) - + (mGateway == null ? 0 :mGateway.hashCode() * 47) - + (mInterface == null ? 0 :mInterface.hashCode() * 67) - + (mType * 71) + (mMtu * 89); - } - - /** - * Implement the Parcelable interface - */ - public int describeContents() { - return 0; - } - - /** - * Implement the Parcelable interface - */ - public void writeToParcel(Parcel dest, int flags) { - dest.writeParcelable(mDestination, flags); - byte[] gatewayBytes = (mGateway == null) ? null : mGateway.getAddress(); - dest.writeByteArray(gatewayBytes); - dest.writeString(mInterface); - dest.writeInt(mType); - dest.writeInt(mMtu); - } - - /** - * Implement the Parcelable interface. - */ - public static final @android.annotation.NonNull Creator CREATOR = - new Creator() { - public RouteInfo createFromParcel(Parcel in) { - IpPrefix dest = in.readParcelable(null); - - InetAddress gateway = null; - byte[] addr = in.createByteArray(); - try { - gateway = InetAddress.getByAddress(addr); - } catch (UnknownHostException e) {} - - String iface = in.readString(); - int type = in.readInt(); - int mtu = in.readInt(); - - return new RouteInfo(dest, gateway, iface, type, mtu); - } - - public RouteInfo[] newArray(int size) { - return new RouteInfo[size]; - } - }; -} diff --git a/packages/Connectivity/framework/src/android/net/SocketKeepalive.java b/packages/Connectivity/framework/src/android/net/SocketKeepalive.java deleted file mode 100644 index f6cae72516091..0000000000000 --- a/packages/Connectivity/framework/src/android/net/SocketKeepalive.java +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.IntDef; -import android.annotation.IntRange; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SystemApi; -import android.os.Binder; -import android.os.ParcelFileDescriptor; -import android.os.RemoteException; - -import java.io.IOException; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.concurrent.Executor; - -/** - * Allows applications to request that the system periodically send specific packets on their - * behalf, using hardware offload to save battery power. - * - * To request that the system send keepalives, call one of the methods that return a - * {@link SocketKeepalive} object, such as {@link ConnectivityManager#createSocketKeepalive}, - * passing in a non-null callback. If the {@link SocketKeepalive} is successfully - * started, the callback's {@code onStarted} method will be called. If an error occurs, - * {@code onError} will be called, specifying one of the {@code ERROR_*} constants in this - * class. - * - * To stop an existing keepalive, call {@link SocketKeepalive#stop}. The system will call - * {@link SocketKeepalive.Callback#onStopped} if the operation was successful or - * {@link SocketKeepalive.Callback#onError} if an error occurred. - * - * For cellular, the device MUST support at least 1 keepalive slot. - * - * For WiFi, the device SHOULD support keepalive offload. If it does not, it MUST reply with - * {@link SocketKeepalive.Callback#onError} with {@code ERROR_UNSUPPORTED} to any keepalive offload - * request. If it does, it MUST support at least 3 concurrent keepalive slots. - */ -public abstract class SocketKeepalive implements AutoCloseable { - static final String TAG = "SocketKeepalive"; - - /** - * Success. It indicates there is no error. - * @hide - */ - @SystemApi - public static final int SUCCESS = 0; - - /** - * No keepalive. This should only be internally as it indicates There is no keepalive. - * It should not propagate to applications. - * @hide - */ - public static final int NO_KEEPALIVE = -1; - - /** - * Data received. - * @hide - */ - public static final int DATA_RECEIVED = -2; - - /** - * The binder died. - * @hide - */ - public static final int BINDER_DIED = -10; - - /** - * The invalid network. It indicates the specified {@code Network} is not connected. - */ - public static final int ERROR_INVALID_NETWORK = -20; - - /** - * The invalid IP addresses. Indicates the specified IP addresses are invalid. - * For example, the specified source IP address is not configured on the - * specified {@code Network}. - */ - public static final int ERROR_INVALID_IP_ADDRESS = -21; - - /** - * The port is invalid. - */ - public static final int ERROR_INVALID_PORT = -22; - - /** - * The length is invalid (e.g. too long). - */ - public static final int ERROR_INVALID_LENGTH = -23; - - /** - * The interval is invalid (e.g. too short). - */ - public static final int ERROR_INVALID_INTERVAL = -24; - - /** - * The socket is invalid. - */ - public static final int ERROR_INVALID_SOCKET = -25; - - /** - * The socket is not idle. - */ - public static final int ERROR_SOCKET_NOT_IDLE = -26; - - /** - * The stop reason is uninitialized. This should only be internally used as initial state - * of stop reason, instead of propagating to application. - * @hide - */ - public static final int ERROR_STOP_REASON_UNINITIALIZED = -27; - - /** - * The request is unsupported. - */ - public static final int ERROR_UNSUPPORTED = -30; - - /** - * There was a hardware error. - */ - public static final int ERROR_HARDWARE_ERROR = -31; - - /** - * Resources are insufficient (e.g. all hardware slots are in use). - */ - public static final int ERROR_INSUFFICIENT_RESOURCES = -32; - - /** - * There was no such slot. This should only be internally as it indicates - * a programming error in the system server. It should not propagate to - * applications. - * @hide - */ - @SystemApi - public static final int ERROR_NO_SUCH_SLOT = -33; - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = { "ERROR_" }, value = { - ERROR_INVALID_NETWORK, - ERROR_INVALID_IP_ADDRESS, - ERROR_INVALID_PORT, - ERROR_INVALID_LENGTH, - ERROR_INVALID_INTERVAL, - ERROR_INVALID_SOCKET, - ERROR_SOCKET_NOT_IDLE, - ERROR_NO_SUCH_SLOT - }) - public @interface ErrorCode {} - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(value = { - SUCCESS, - ERROR_INVALID_LENGTH, - ERROR_UNSUPPORTED, - ERROR_INSUFFICIENT_RESOURCES, - }) - public @interface KeepaliveEvent {} - - /** - * The minimum interval in seconds between keepalive packet transmissions. - * - * @hide - **/ - public static final int MIN_INTERVAL_SEC = 10; - - /** - * The maximum interval in seconds between keepalive packet transmissions. - * - * @hide - **/ - public static final int MAX_INTERVAL_SEC = 3600; - - /** - * An exception that embarks an error code. - * @hide - */ - public static class ErrorCodeException extends Exception { - public final int error; - public ErrorCodeException(final int error, final Throwable e) { - super(e); - this.error = error; - } - public ErrorCodeException(final int error) { - this.error = error; - } - } - - /** - * This socket is invalid. - * See the error code for details, and the optional cause. - * @hide - */ - public static class InvalidSocketException extends ErrorCodeException { - public InvalidSocketException(final int error, final Throwable e) { - super(error, e); - } - public InvalidSocketException(final int error) { - super(error); - } - } - - @NonNull final IConnectivityManager mService; - @NonNull final Network mNetwork; - @NonNull final ParcelFileDescriptor mPfd; - @NonNull final Executor mExecutor; - @NonNull final ISocketKeepaliveCallback mCallback; - // TODO: remove slot since mCallback could be used to identify which keepalive to stop. - @Nullable Integer mSlot; - - SocketKeepalive(@NonNull IConnectivityManager service, @NonNull Network network, - @NonNull ParcelFileDescriptor pfd, - @NonNull Executor executor, @NonNull Callback callback) { - mService = service; - mNetwork = network; - mPfd = pfd; - mExecutor = executor; - mCallback = new ISocketKeepaliveCallback.Stub() { - @Override - public void onStarted(int slot) { - final long token = Binder.clearCallingIdentity(); - try { - mExecutor.execute(() -> { - mSlot = slot; - callback.onStarted(); - }); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public void onStopped() { - final long token = Binder.clearCallingIdentity(); - try { - executor.execute(() -> { - mSlot = null; - callback.onStopped(); - }); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public void onError(int error) { - final long token = Binder.clearCallingIdentity(); - try { - executor.execute(() -> { - mSlot = null; - callback.onError(error); - }); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public void onDataReceived() { - final long token = Binder.clearCallingIdentity(); - try { - executor.execute(() -> { - mSlot = null; - callback.onDataReceived(); - }); - } finally { - Binder.restoreCallingIdentity(token); - } - } - }; - } - - /** - * Request that keepalive be started with the given {@code intervalSec}. See - * {@link SocketKeepalive}. If the remote binder dies, or the binder call throws an exception - * when invoking start or stop of the {@link SocketKeepalive}, a {@link RemoteException} will be - * thrown into the {@code executor}. This is typically not important to catch because the remote - * party is the system, so if it is not in shape to communicate through binder the system is - * probably going down anyway. If the caller cares regardless, it can use a custom - * {@link Executor} to catch the {@link RemoteException}. - * - * @param intervalSec The target interval in seconds between keepalive packet transmissions. - * The interval should be between 10 seconds and 3600 seconds, otherwise - * {@link #ERROR_INVALID_INTERVAL} will be returned. - */ - public final void start(@IntRange(from = MIN_INTERVAL_SEC, to = MAX_INTERVAL_SEC) - int intervalSec) { - startImpl(intervalSec); - } - - abstract void startImpl(int intervalSec); - - /** - * Requests that keepalive be stopped. The application must wait for {@link Callback#onStopped} - * before using the object. See {@link SocketKeepalive}. - */ - public final void stop() { - stopImpl(); - } - - abstract void stopImpl(); - - /** - * Deactivate this {@link SocketKeepalive} and free allocated resources. The instance won't be - * usable again if {@code close()} is called. - */ - @Override - public final void close() { - stop(); - try { - mPfd.close(); - } catch (IOException e) { - // Nothing much can be done. - } - } - - /** - * The callback which app can use to learn the status changes of {@link SocketKeepalive}. See - * {@link SocketKeepalive}. - */ - public static class Callback { - /** The requested keepalive was successfully started. */ - public void onStarted() {} - /** The keepalive was successfully stopped. */ - public void onStopped() {} - /** An error occurred. */ - public void onError(@ErrorCode int error) {} - /** The keepalive on a TCP socket was stopped because the socket received data. This is - * never called for UDP sockets. */ - public void onDataReceived() {} - } -} diff --git a/packages/Connectivity/framework/src/android/net/SocketLocalAddressChangedException.java b/packages/Connectivity/framework/src/android/net/SocketLocalAddressChangedException.java deleted file mode 100644 index 9daad83fd13e8..0000000000000 --- a/packages/Connectivity/framework/src/android/net/SocketLocalAddressChangedException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.SystemApi; - -/** - * Thrown when the local address of the socket has changed. - * - * @hide - */ -@SystemApi -public class SocketLocalAddressChangedException extends Exception { - /** @hide */ - public SocketLocalAddressChangedException() { - super("The local address of the socket changed"); - } -} diff --git a/packages/Connectivity/framework/src/android/net/SocketNotBoundException.java b/packages/Connectivity/framework/src/android/net/SocketNotBoundException.java deleted file mode 100644 index b1d7026ac9817..0000000000000 --- a/packages/Connectivity/framework/src/android/net/SocketNotBoundException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.SystemApi; - -/** - * Thrown when a previously bound socket becomes unbound. - * - * @hide - */ -@SystemApi -public class SocketNotBoundException extends Exception { - /** @hide */ - public SocketNotBoundException() { - super("The socket is unbound"); - } -} diff --git a/packages/Connectivity/framework/src/android/net/StaticIpConfiguration.java b/packages/Connectivity/framework/src/android/net/StaticIpConfiguration.java deleted file mode 100644 index 7904f7a4ec17d..0000000000000 --- a/packages/Connectivity/framework/src/android/net/StaticIpConfiguration.java +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SystemApi; -import android.compat.annotation.UnsupportedAppUsage; -import android.os.Build; -import android.os.Parcel; -import android.os.Parcelable; - -import com.android.net.module.util.InetAddressUtils; - -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -/** - * Class that describes static IP configuration. - * - *

      This class is different from {@link LinkProperties} because it represents - * configuration intent. The general contract is that if we can represent - * a configuration here, then we should be able to configure it on a network. - * The intent is that it closely match the UI we have for configuring networks. - * - *

      In contrast, {@link LinkProperties} represents current state. It is much more - * expressive. For example, it supports multiple IP addresses, multiple routes, - * stacked interfaces, and so on. Because LinkProperties is so expressive, - * using it to represent configuration intent as well as current state causes - * problems. For example, we could unknowingly save a configuration that we are - * not in fact capable of applying, or we could save a configuration that the - * UI cannot display, which has the potential for malicious code to hide - * hostile or unexpected configuration from the user. - * - * @hide - */ -@SystemApi -public final class StaticIpConfiguration implements Parcelable { - /** @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - @Nullable - public LinkAddress ipAddress; - /** @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - @Nullable - public InetAddress gateway; - /** @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - @NonNull - public final ArrayList dnsServers; - /** @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - @Nullable - public String domains; - - public StaticIpConfiguration() { - dnsServers = new ArrayList<>(); - } - - public StaticIpConfiguration(@Nullable StaticIpConfiguration source) { - this(); - if (source != null) { - // All of these except dnsServers are immutable, so no need to make copies. - ipAddress = source.ipAddress; - gateway = source.gateway; - dnsServers.addAll(source.dnsServers); - domains = source.domains; - } - } - - public void clear() { - ipAddress = null; - gateway = null; - dnsServers.clear(); - domains = null; - } - - /** - * Get the static IP address included in the configuration. - */ - public @Nullable LinkAddress getIpAddress() { - return ipAddress; - } - - /** - * Get the gateway included in the configuration. - */ - public @Nullable InetAddress getGateway() { - return gateway; - } - - /** - * Get the DNS servers included in the configuration. - */ - public @NonNull List getDnsServers() { - return dnsServers; - } - - /** - * Get a {@link String} containing the comma separated domains to search when resolving host - * names on this link, in priority order. - */ - public @Nullable String getDomains() { - return domains; - } - - /** - * Helper class to build a new instance of {@link StaticIpConfiguration}. - */ - public static final class Builder { - private LinkAddress mIpAddress; - private InetAddress mGateway; - private Iterable mDnsServers; - private String mDomains; - - /** - * Set the IP address to be included in the configuration; null by default. - * @return The {@link Builder} for chaining. - */ - public @NonNull Builder setIpAddress(@Nullable LinkAddress ipAddress) { - mIpAddress = ipAddress; - return this; - } - - /** - * Set the address of the gateway to be included in the configuration; null by default. - * @return The {@link Builder} for chaining. - */ - public @NonNull Builder setGateway(@Nullable InetAddress gateway) { - mGateway = gateway; - return this; - } - - /** - * Set the addresses of the DNS servers included in the configuration; empty by default. - * @return The {@link Builder} for chaining. - */ - public @NonNull Builder setDnsServers(@NonNull Iterable dnsServers) { - Objects.requireNonNull(dnsServers); - mDnsServers = dnsServers; - return this; - } - - /** - * Sets the DNS domain search path to be used on the link; null by default. - * @param newDomains A {@link String} containing the comma separated domains to search when - * resolving host names on this link, in priority order. - * @return The {@link Builder} for chaining. - */ - public @NonNull Builder setDomains(@Nullable String newDomains) { - mDomains = newDomains; - return this; - } - - /** - * Create a {@link StaticIpConfiguration} from the parameters in this {@link Builder}. - * @return The newly created StaticIpConfiguration. - */ - public @NonNull StaticIpConfiguration build() { - final StaticIpConfiguration config = new StaticIpConfiguration(); - config.ipAddress = mIpAddress; - config.gateway = mGateway; - if (mDnsServers != null) { - for (InetAddress server : mDnsServers) { - config.dnsServers.add(server); - } - } - config.domains = mDomains; - return config; - } - } - - /** - * Add a DNS server to this configuration. - */ - public void addDnsServer(@NonNull InetAddress server) { - dnsServers.add(server); - } - - /** - * Returns the network routes specified by this object. Will typically include a - * directly-connected route for the IP address's local subnet and a default route. - * @param iface Interface to include in the routes. - */ - public @NonNull List getRoutes(@Nullable String iface) { - List routes = new ArrayList(3); - if (ipAddress != null) { - RouteInfo connectedRoute = new RouteInfo(ipAddress, null, iface); - routes.add(connectedRoute); - // If the default gateway is not covered by the directly-connected route, also add a - // host route to the gateway as well. This configuration is arguably invalid, but it - // used to work in K and earlier, and other OSes appear to accept it. - if (gateway != null && !connectedRoute.matches(gateway)) { - routes.add(RouteInfo.makeHostRoute(gateway, iface)); - } - } - if (gateway != null) { - routes.add(new RouteInfo((IpPrefix) null, gateway, iface)); - } - return routes; - } - - /** - * Returns a LinkProperties object expressing the data in this object. Note that the information - * contained in the LinkProperties will not be a complete picture of the link's configuration, - * because any configuration information that is obtained dynamically by the network (e.g., - * IPv6 configuration) will not be included. - * @hide - */ - public @NonNull LinkProperties toLinkProperties(String iface) { - LinkProperties lp = new LinkProperties(); - lp.setInterfaceName(iface); - if (ipAddress != null) { - lp.addLinkAddress(ipAddress); - } - for (RouteInfo route : getRoutes(iface)) { - lp.addRoute(route); - } - for (InetAddress dns : dnsServers) { - lp.addDnsServer(dns); - } - lp.setDomains(domains); - return lp; - } - - @NonNull - @Override - public String toString() { - StringBuffer str = new StringBuffer(); - - str.append("IP address "); - if (ipAddress != null ) str.append(ipAddress).append(" "); - - str.append("Gateway "); - if (gateway != null) str.append(gateway.getHostAddress()).append(" "); - - str.append(" DNS servers: ["); - for (InetAddress dnsServer : dnsServers) { - str.append(" ").append(dnsServer.getHostAddress()); - } - - str.append(" ] Domains "); - if (domains != null) str.append(domains); - return str.toString(); - } - - @Override - public int hashCode() { - int result = 13; - result = 47 * result + (ipAddress == null ? 0 : ipAddress.hashCode()); - result = 47 * result + (gateway == null ? 0 : gateway.hashCode()); - result = 47 * result + (domains == null ? 0 : domains.hashCode()); - result = 47 * result + dnsServers.hashCode(); - return result; - } - - @Override - public boolean equals(@Nullable Object obj) { - if (this == obj) return true; - - if (!(obj instanceof StaticIpConfiguration)) return false; - - StaticIpConfiguration other = (StaticIpConfiguration) obj; - - return other != null && - Objects.equals(ipAddress, other.ipAddress) && - Objects.equals(gateway, other.gateway) && - dnsServers.equals(other.dnsServers) && - Objects.equals(domains, other.domains); - } - - /** Implement the Parcelable interface */ - public static final @android.annotation.NonNull Creator CREATOR = - new Creator() { - public StaticIpConfiguration createFromParcel(Parcel in) { - return readFromParcel(in); - } - - public StaticIpConfiguration[] newArray(int size) { - return new StaticIpConfiguration[size]; - } - }; - - /** Implement the Parcelable interface */ - @Override - public int describeContents() { - return 0; - } - - /** Implement the Parcelable interface */ - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeParcelable(ipAddress, flags); - InetAddressUtils.parcelInetAddress(dest, gateway, flags); - dest.writeInt(dnsServers.size()); - for (InetAddress dnsServer : dnsServers) { - InetAddressUtils.parcelInetAddress(dest, dnsServer, flags); - } - dest.writeString(domains); - } - - /** @hide */ - public static StaticIpConfiguration readFromParcel(Parcel in) { - final StaticIpConfiguration s = new StaticIpConfiguration(); - s.ipAddress = in.readParcelable(null); - s.gateway = InetAddressUtils.unparcelInetAddress(in); - s.dnsServers.clear(); - int size = in.readInt(); - for (int i = 0; i < size; i++) { - s.dnsServers.add(InetAddressUtils.unparcelInetAddress(in)); - } - s.domains = in.readString(); - return s; - } -} diff --git a/packages/Connectivity/framework/src/android/net/TcpKeepalivePacketData.java b/packages/Connectivity/framework/src/android/net/TcpKeepalivePacketData.java deleted file mode 100644 index c2c4f32ca6738..0000000000000 --- a/packages/Connectivity/framework/src/android/net/TcpKeepalivePacketData.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.net; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SystemApi; -import android.os.Parcel; -import android.os.Parcelable; - -import java.net.InetAddress; -import java.util.Objects; - -/** - * Represents the actual tcp keep alive packets which will be used for hardware offload. - * @hide - */ -@SystemApi -public final class TcpKeepalivePacketData extends KeepalivePacketData implements Parcelable { - private static final String TAG = "TcpKeepalivePacketData"; - - /** - * TCP sequence number. - * @hide - */ - public final int tcpSeq; - - /** - * TCP ACK number. - * @hide - */ - public final int tcpAck; - - /** - * TCP RCV window. - * @hide - */ - public final int tcpWindow; - - /** TCP RCV window scale. - * @hide - */ - public final int tcpWindowScale; - - /** - * IP TOS. - * @hide - */ - public final int ipTos; - - /** - * IP TTL. - * @hide - */ - public final int ipTtl; - - public TcpKeepalivePacketData(@NonNull final InetAddress srcAddress, int srcPort, - @NonNull final InetAddress dstAddress, int dstPort, @NonNull final byte[] data, - int tcpSeq, int tcpAck, int tcpWindow, int tcpWindowScale, int ipTos, int ipTtl) - throws InvalidPacketException { - super(srcAddress, srcPort, dstAddress, dstPort, data); - this.tcpSeq = tcpSeq; - this.tcpAck = tcpAck; - this.tcpWindow = tcpWindow; - this.tcpWindowScale = tcpWindowScale; - this.ipTos = ipTos; - this.ipTtl = ipTtl; - } - - /** - * Get the TCP sequence number. - * - * See https://tools.ietf.org/html/rfc793#page-15. - */ - public int getTcpSeq() { - return tcpSeq; - } - - /** - * Get the TCP ACK number. - * - * See https://tools.ietf.org/html/rfc793#page-15. - */ - public int getTcpAck() { - return tcpAck; - } - - /** - * Get the TCP RCV window. - * - * See https://tools.ietf.org/html/rfc793#page-15. - */ - public int getTcpWindow() { - return tcpWindow; - } - - /** - * Get the TCP RCV window scale. - * - * See https://tools.ietf.org/html/rfc793#page-15. - */ - public int getTcpWindowScale() { - return tcpWindowScale; - } - - /** - * Get the IP type of service. - */ - public int getIpTos() { - return ipTos; - } - - /** - * Get the IP TTL. - */ - public int getIpTtl() { - return ipTtl; - } - - @Override - public boolean equals(@Nullable final Object o) { - if (!(o instanceof TcpKeepalivePacketData)) return false; - final TcpKeepalivePacketData other = (TcpKeepalivePacketData) o; - final InetAddress srcAddress = getSrcAddress(); - final InetAddress dstAddress = getDstAddress(); - return srcAddress.equals(other.getSrcAddress()) - && dstAddress.equals(other.getDstAddress()) - && getSrcPort() == other.getSrcPort() - && getDstPort() == other.getDstPort() - && this.tcpAck == other.tcpAck - && this.tcpSeq == other.tcpSeq - && this.tcpWindow == other.tcpWindow - && this.tcpWindowScale == other.tcpWindowScale - && this.ipTos == other.ipTos - && this.ipTtl == other.ipTtl; - } - - @Override - public int hashCode() { - return Objects.hash(getSrcAddress(), getDstAddress(), getSrcPort(), getDstPort(), - tcpAck, tcpSeq, tcpWindow, tcpWindowScale, ipTos, ipTtl); - } - - /** - * Parcelable Implementation. - * Note that this object implements parcelable (and needs to keep doing this as it inherits - * from a class that does), but should usually be parceled as a stable parcelable using - * the toStableParcelable() and fromStableParcelable() methods. - */ - @Override - public int describeContents() { - return 0; - } - - /** Write to parcel. */ - @Override - public void writeToParcel(@NonNull Parcel out, int flags) { - out.writeString(getSrcAddress().getHostAddress()); - out.writeString(getDstAddress().getHostAddress()); - out.writeInt(getSrcPort()); - out.writeInt(getDstPort()); - out.writeByteArray(getPacket()); - out.writeInt(tcpSeq); - out.writeInt(tcpAck); - out.writeInt(tcpWindow); - out.writeInt(tcpWindowScale); - out.writeInt(ipTos); - out.writeInt(ipTtl); - } - - private static TcpKeepalivePacketData readFromParcel(Parcel in) throws InvalidPacketException { - InetAddress srcAddress = InetAddresses.parseNumericAddress(in.readString()); - InetAddress dstAddress = InetAddresses.parseNumericAddress(in.readString()); - int srcPort = in.readInt(); - int dstPort = in.readInt(); - byte[] packet = in.createByteArray(); - int tcpSeq = in.readInt(); - int tcpAck = in.readInt(); - int tcpWnd = in.readInt(); - int tcpWndScale = in.readInt(); - int ipTos = in.readInt(); - int ipTtl = in.readInt(); - return new TcpKeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, packet, tcpSeq, - tcpAck, tcpWnd, tcpWndScale, ipTos, ipTtl); - } - - /** Parcelable Creator. */ - public static final @NonNull Parcelable.Creator CREATOR = - new Parcelable.Creator() { - public TcpKeepalivePacketData createFromParcel(Parcel in) { - try { - return readFromParcel(in); - } catch (InvalidPacketException e) { - throw new IllegalArgumentException( - "Invalid TCP keepalive data: " + e.getError()); - } - } - - public TcpKeepalivePacketData[] newArray(int size) { - return new TcpKeepalivePacketData[size]; - } - }; - - @Override - public String toString() { - return "saddr: " + getSrcAddress() - + " daddr: " + getDstAddress() - + " sport: " + getSrcPort() - + " dport: " + getDstPort() - + " seq: " + tcpSeq - + " ack: " + tcpAck - + " window: " + tcpWindow - + " windowScale: " + tcpWindowScale - + " tos: " + ipTos - + " ttl: " + ipTtl; - } -} diff --git a/packages/Connectivity/framework/src/android/net/TcpRepairWindow.java b/packages/Connectivity/framework/src/android/net/TcpRepairWindow.java deleted file mode 100644 index 86034f0a76ed2..0000000000000 --- a/packages/Connectivity/framework/src/android/net/TcpRepairWindow.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -/** - * Corresponds to C's {@code struct tcp_repair_window} from - * include/uapi/linux/tcp.h - * - * @hide - */ -public final class TcpRepairWindow { - public final int sndWl1; - public final int sndWnd; - public final int maxWindow; - public final int rcvWnd; - public final int rcvWup; - public final int rcvWndScale; - - /** - * Constructs an instance with the given field values. - */ - public TcpRepairWindow(final int sndWl1, final int sndWnd, final int maxWindow, - final int rcvWnd, final int rcvWup, final int rcvWndScale) { - this.sndWl1 = sndWl1; - this.sndWnd = sndWnd; - this.maxWindow = maxWindow; - this.rcvWnd = rcvWnd; - this.rcvWup = rcvWup; - this.rcvWndScale = rcvWndScale; - } -} diff --git a/packages/Connectivity/framework/src/android/net/TcpSocketKeepalive.java b/packages/Connectivity/framework/src/android/net/TcpSocketKeepalive.java deleted file mode 100644 index d89814d49bd0c..0000000000000 --- a/packages/Connectivity/framework/src/android/net/TcpSocketKeepalive.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.NonNull; -import android.os.ParcelFileDescriptor; -import android.os.RemoteException; -import android.util.Log; - -import java.util.concurrent.Executor; - -/** @hide */ -final class TcpSocketKeepalive extends SocketKeepalive { - - TcpSocketKeepalive(@NonNull IConnectivityManager service, - @NonNull Network network, - @NonNull ParcelFileDescriptor pfd, - @NonNull Executor executor, - @NonNull Callback callback) { - super(service, network, pfd, executor, callback); - } - - /** - * Starts keepalives. {@code mSocket} must be a connected TCP socket. - * - * - The application must not write to or read from the socket after calling this method, until - * onDataReceived, onStopped, or onError are called. If it does, the keepalive will fail - * with {@link #ERROR_SOCKET_NOT_IDLE}, or {@code #ERROR_INVALID_SOCKET} if the socket - * experienced an error (as in poll(2) returned POLLERR or POLLHUP); if this happens, the data - * received from the socket may be invalid, and the socket can't be recovered. - * - If the socket has data in the send or receive buffer, then this call will fail with - * {@link #ERROR_SOCKET_NOT_IDLE} and can be retried after the data has been processed. - * An app could ensure this by using an application-layer protocol to receive acknowledgement - * that indicates all data has been delivered to server, e.g. HTTP 200 OK. - * Then the app could go into keepalive mode after reading all remaining data within the - * acknowledgement. - */ - @Override - void startImpl(int intervalSec) { - mExecutor.execute(() -> { - try { - mService.startTcpKeepalive(mNetwork, mPfd, intervalSec, mCallback); - } catch (RemoteException e) { - Log.e(TAG, "Error starting packet keepalive: ", e); - throw e.rethrowFromSystemServer(); - } - }); - } - - @Override - void stopImpl() { - mExecutor.execute(() -> { - try { - if (mSlot != null) { - mService.stopKeepalive(mNetwork, mSlot); - } - } catch (RemoteException e) { - Log.e(TAG, "Error stopping packet keepalive: ", e); - throw e.rethrowFromSystemServer(); - } - }); - } -} diff --git a/packages/Connectivity/framework/src/android/net/TestNetworkInterface.java b/packages/Connectivity/framework/src/android/net/TestNetworkInterface.java deleted file mode 100644 index 4449ff80180b6..0000000000000 --- a/packages/Connectivity/framework/src/android/net/TestNetworkInterface.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.net; - -import android.annotation.NonNull; -import android.annotation.SystemApi; -import android.os.Parcel; -import android.os.ParcelFileDescriptor; -import android.os.Parcelable; - -/** - * This class is used to return the interface name and fd of the test interface - * - * @hide - */ -@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) -public final class TestNetworkInterface implements Parcelable { - @NonNull - private final ParcelFileDescriptor mFileDescriptor; - @NonNull - private final String mInterfaceName; - - @Override - public int describeContents() { - return (mFileDescriptor != null) ? Parcelable.CONTENTS_FILE_DESCRIPTOR : 0; - } - - @Override - public void writeToParcel(@NonNull Parcel out, int flags) { - out.writeParcelable(mFileDescriptor, PARCELABLE_WRITE_RETURN_VALUE); - out.writeString(mInterfaceName); - } - - public TestNetworkInterface(@NonNull ParcelFileDescriptor pfd, @NonNull String intf) { - mFileDescriptor = pfd; - mInterfaceName = intf; - } - - private TestNetworkInterface(@NonNull Parcel in) { - mFileDescriptor = in.readParcelable(ParcelFileDescriptor.class.getClassLoader()); - mInterfaceName = in.readString(); - } - - @NonNull - public ParcelFileDescriptor getFileDescriptor() { - return mFileDescriptor; - } - - @NonNull - public String getInterfaceName() { - return mInterfaceName; - } - - @NonNull - public static final Parcelable.Creator CREATOR = - new Parcelable.Creator() { - public TestNetworkInterface createFromParcel(Parcel in) { - return new TestNetworkInterface(in); - } - - public TestNetworkInterface[] newArray(int size) { - return new TestNetworkInterface[size]; - } - }; -} diff --git a/packages/Connectivity/framework/src/android/net/TestNetworkManager.java b/packages/Connectivity/framework/src/android/net/TestNetworkManager.java deleted file mode 100644 index 9ddd2f57679b9..0000000000000 --- a/packages/Connectivity/framework/src/android/net/TestNetworkManager.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.net; - -import android.Manifest; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.RequiresPermission; -import android.annotation.SystemApi; -import android.os.IBinder; -import android.os.RemoteException; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Objects; - -/** - * Class that allows creation and management of per-app, test-only networks - * - * @hide - */ -@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) -public class TestNetworkManager { - /** - * Prefix for tun interfaces created by this class. - * @hide - */ - public static final String TEST_TUN_PREFIX = "testtun"; - - /** - * Prefix for tap interfaces created by this class. - */ - public static final String TEST_TAP_PREFIX = "testtap"; - - @NonNull private static final String TAG = TestNetworkManager.class.getSimpleName(); - - @NonNull private final ITestNetworkManager mService; - - /** @hide */ - public TestNetworkManager(@NonNull ITestNetworkManager service) { - mService = Objects.requireNonNull(service, "missing ITestNetworkManager"); - } - - /** - * Teardown the capability-limited, testing-only network for a given interface - * - * @param network The test network that should be torn down - * @hide - */ - @RequiresPermission(Manifest.permission.MANAGE_TEST_NETWORKS) - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public void teardownTestNetwork(@NonNull Network network) { - try { - mService.teardownTestNetwork(network.netId); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - private void setupTestNetwork( - @NonNull String iface, - @Nullable LinkProperties lp, - boolean isMetered, - @NonNull int[] administratorUids, - @NonNull IBinder binder) { - try { - mService.setupTestNetwork(iface, lp, isMetered, administratorUids, binder); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Sets up a capability-limited, testing-only network for a given interface - * - * @param lp The LinkProperties for the TestNetworkService to use for this test network. Note - * that the interface name and link addresses will be overwritten, and the passed-in values - * discarded. - * @param isMetered Whether or not the network should be considered metered. - * @param binder A binder object guarding the lifecycle of this test network. - * @hide - */ - public void setupTestNetwork( - @NonNull LinkProperties lp, boolean isMetered, @NonNull IBinder binder) { - Objects.requireNonNull(lp, "Invalid LinkProperties"); - setupTestNetwork(lp.getInterfaceName(), lp, isMetered, new int[0], binder); - } - - /** - * Sets up a capability-limited, testing-only network for a given interface - * - * @param iface the name of the interface to be used for the Network LinkProperties. - * @param binder A binder object guarding the lifecycle of this test network. - * @hide - */ - @RequiresPermission(Manifest.permission.MANAGE_TEST_NETWORKS) - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public void setupTestNetwork(@NonNull String iface, @NonNull IBinder binder) { - setupTestNetwork(iface, null, true, new int[0], binder); - } - - /** - * Sets up a capability-limited, testing-only network for a given interface with the given - * administrator UIDs. - * - * @param iface the name of the interface to be used for the Network LinkProperties. - * @param administratorUids The administrator UIDs to be used for the test-only network - * @param binder A binder object guarding the lifecycle of this test network. - * @hide - */ - public void setupTestNetwork( - @NonNull String iface, @NonNull int[] administratorUids, @NonNull IBinder binder) { - setupTestNetwork(iface, null, true, administratorUids, binder); - } - - /** - * Create a tun interface for testing purposes - * - * @param linkAddrs an array of LinkAddresses to assign to the TUN interface - * @return A ParcelFileDescriptor of the underlying TUN interface. Close this to tear down the - * TUN interface. - * @deprecated Use {@link #createTunInterface(Collection)} instead. - * @hide - */ - @Deprecated - @NonNull - public TestNetworkInterface createTunInterface(@NonNull LinkAddress[] linkAddrs) { - return createTunInterface(Arrays.asList(linkAddrs)); - } - - /** - * Create a tun interface for testing purposes - * - * @param linkAddrs an array of LinkAddresses to assign to the TUN interface - * @return A ParcelFileDescriptor of the underlying TUN interface. Close this to tear down the - * TUN interface. - * @hide - */ - @RequiresPermission(Manifest.permission.MANAGE_TEST_NETWORKS) - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - @NonNull - public TestNetworkInterface createTunInterface(@NonNull Collection linkAddrs) { - try { - final LinkAddress[] arr = new LinkAddress[linkAddrs.size()]; - return mService.createTunInterface(linkAddrs.toArray(arr)); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Create a tap interface for testing purposes - * - * @return A ParcelFileDescriptor of the underlying TAP interface. Close this to tear down the - * TAP interface. - * @hide - */ - @RequiresPermission(Manifest.permission.MANAGE_TEST_NETWORKS) - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - @NonNull - public TestNetworkInterface createTapInterface() { - try { - return mService.createTapInterface(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - -} diff --git a/packages/Connectivity/framework/src/android/net/TestNetworkSpecifier.java b/packages/Connectivity/framework/src/android/net/TestNetworkSpecifier.java deleted file mode 100644 index 117457dffc9f2..0000000000000 --- a/packages/Connectivity/framework/src/android/net/TestNetworkSpecifier.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SystemApi; -import android.os.Parcel; -import android.os.Parcelable; -import android.text.TextUtils; - -import java.util.Objects; - -/** - * A {@link NetworkSpecifier} used to identify test interfaces. - * - * @see TestNetworkManager - * @hide - */ -@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) -public final class TestNetworkSpecifier extends NetworkSpecifier implements Parcelable { - - /** - * Name of the network interface. - */ - @NonNull - private final String mInterfaceName; - - public TestNetworkSpecifier(@NonNull String interfaceName) { - if (TextUtils.isEmpty(interfaceName)) { - throw new IllegalArgumentException("Empty interfaceName"); - } - mInterfaceName = interfaceName; - } - - // This may be null in the future to support specifiers based on data other than the interface - // name. - @Nullable - public String getInterfaceName() { - return mInterfaceName; - } - - @Override - public boolean canBeSatisfiedBy(@Nullable NetworkSpecifier other) { - return equals(other); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof TestNetworkSpecifier)) return false; - return TextUtils.equals(mInterfaceName, ((TestNetworkSpecifier) o).mInterfaceName); - } - - @Override - public int hashCode() { - return Objects.hashCode(mInterfaceName); - } - - @Override - public String toString() { - return "TestNetworkSpecifier (" + mInterfaceName + ")"; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeString(mInterfaceName); - } - - public static final @NonNull Creator CREATOR = - new Creator() { - public TestNetworkSpecifier createFromParcel(Parcel in) { - return new TestNetworkSpecifier(in.readString()); - } - public TestNetworkSpecifier[] newArray(int size) { - return new TestNetworkSpecifier[size]; - } - }; -} diff --git a/packages/Connectivity/framework/src/android/net/TransportInfo.java b/packages/Connectivity/framework/src/android/net/TransportInfo.java deleted file mode 100644 index fa889eabb842b..0000000000000 --- a/packages/Connectivity/framework/src/android/net/TransportInfo.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.NonNull; -import android.annotation.SystemApi; - -/** - * A container for transport-specific capabilities which is returned by - * {@link NetworkCapabilities#getTransportInfo()}. Specific networks - * may provide concrete implementations of this interface. - * @see android.net.wifi.aware.WifiAwareNetworkInfo - * @see android.net.wifi.WifiInfo - */ -public interface TransportInfo { - - /** - * Create a copy of a {@link TransportInfo} with some fields redacted based on the permissions - * held by the receiving app. - * - *

      - * Usage by connectivity stack: - *

        - *
      • Connectivity stack will invoke {@link #getApplicableRedactions()} to find the list - * of redactions that are required by this {@link TransportInfo} instance.
      • - *
      • Connectivity stack then loops through each bit in the bitmask returned and checks if the - * receiving app holds the corresponding permission. - *
          - *
        • If the app holds the corresponding permission, the bit is cleared from the - * |redactions| bitmask.
        • - *
        • If the app does not hold the corresponding permission, the bit is retained in the - * |redactions| bitmask.
        • - *
        - *
      • Connectivity stack then invokes {@link #makeCopy(long)} with the necessary |redactions| - * to create a copy to send to the corresponding app.
      • - *
      - *

      - * - * @param redactions bitmask of redactions that needs to be performed on this instance. - * @return Copy of this instance with the necessary redactions. - * @hide - */ - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - @NonNull - default TransportInfo makeCopy(@NetworkCapabilities.RedactionType long redactions) { - return this; - } - - /** - * Returns a bitmask of all the applicable redactions (based on the permissions held by the - * receiving app) to be performed on this TransportInfo. - * - * @return bitmask of redactions applicable on this instance. - * @see #makeCopy(long) - * @hide - */ - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - default @NetworkCapabilities.RedactionType long getApplicableRedactions() { - return NetworkCapabilities.REDACT_NONE; - } -} diff --git a/packages/Connectivity/framework/src/android/net/UidRange.aidl b/packages/Connectivity/framework/src/android/net/UidRange.aidl deleted file mode 100644 index f70fc8e2fefd9..0000000000000 --- a/packages/Connectivity/framework/src/android/net/UidRange.aidl +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -/** - * An inclusive range of UIDs. - * - * {@hide} - */ -parcelable UidRange; \ No newline at end of file diff --git a/packages/Connectivity/framework/src/android/net/UidRange.java b/packages/Connectivity/framework/src/android/net/UidRange.java deleted file mode 100644 index bd332928f4632..0000000000000 --- a/packages/Connectivity/framework/src/android/net/UidRange.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.Nullable; -import android.os.Parcel; -import android.os.Parcelable; -import android.os.UserHandle; -import android.util.ArraySet; -import android.util.Range; - -import java.util.Collection; -import java.util.Set; - -/** - * An inclusive range of UIDs. - * - * @hide - */ -public final class UidRange implements Parcelable { - public final int start; - public final int stop; - - public UidRange(int startUid, int stopUid) { - if (startUid < 0) throw new IllegalArgumentException("Invalid start UID."); - if (stopUid < 0) throw new IllegalArgumentException("Invalid stop UID."); - if (startUid > stopUid) throw new IllegalArgumentException("Invalid UID range."); - start = startUid; - stop = stopUid; - } - - /** Creates a UidRange for the specified user. */ - public static UidRange createForUser(UserHandle user) { - final UserHandle nextUser = UserHandle.of(user.getIdentifier() + 1); - final int start = user.getUid(0 /* appId */); - final int end = nextUser.getUid(0 /* appId */) - 1; - return new UidRange(start, end); - } - - /** Returns the smallest user Id which is contained in this UidRange */ - public int getStartUser() { - return UserHandle.getUserHandleForUid(start).getIdentifier(); - } - - /** Returns the largest user Id which is contained in this UidRange */ - public int getEndUser() { - return UserHandle.getUserHandleForUid(stop).getIdentifier(); - } - - /** Returns whether the UidRange contains the specified UID. */ - public boolean contains(int uid) { - return start <= uid && uid <= stop; - } - - /** - * Returns the count of UIDs in this range. - */ - public int count() { - return 1 + stop - start; - } - - /** - * @return {@code true} if this range contains every UID contained by the {@code other} range. - */ - public boolean containsRange(UidRange other) { - return start <= other.start && other.stop <= stop; - } - - @Override - public int hashCode() { - int result = 17; - result = 31 * result + start; - result = 31 * result + stop; - return result; - } - - @Override - public boolean equals(@Nullable Object o) { - if (this == o) { - return true; - } - if (o instanceof UidRange) { - UidRange other = (UidRange) o; - return start == other.start && stop == other.stop; - } - return false; - } - - @Override - public String toString() { - return start + "-" + stop; - } - - // Implement the Parcelable interface - // TODO: Consider making this class no longer parcelable, since all users are likely in the - // system server. - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(start); - dest.writeInt(stop); - } - - public static final @android.annotation.NonNull Creator CREATOR = - new Creator() { - @Override - public UidRange createFromParcel(Parcel in) { - int start = in.readInt(); - int stop = in.readInt(); - - return new UidRange(start, stop); - } - @Override - public UidRange[] newArray(int size) { - return new UidRange[size]; - } - }; - - /** - * Returns whether any of the UidRange in the collection contains the specified uid - * - * @param ranges The collection of UidRange to check - * @param uid the uid in question - * @return {@code true} if the uid is contained within the ranges, {@code false} otherwise - * - * @see UidRange#contains(int) - */ - public static boolean containsUid(Collection ranges, int uid) { - if (ranges == null) return false; - for (UidRange range : ranges) { - if (range.contains(uid)) { - return true; - } - } - return false; - } - - /** - * Convert a set of {@code Range} to a set of {@link UidRange}. - */ - @Nullable - public static ArraySet fromIntRanges(@Nullable Set> ranges) { - if (null == ranges) return null; - - final ArraySet uids = new ArraySet<>(); - for (Range range : ranges) { - uids.add(new UidRange(range.getLower(), range.getUpper())); - } - return uids; - } - - /** - * Convert a set of {@link UidRange} to a set of {@code Range}. - */ - @Nullable - public static ArraySet> toIntRanges(@Nullable Set ranges) { - if (null == ranges) return null; - - final ArraySet> uids = new ArraySet<>(); - for (UidRange range : ranges) { - uids.add(new Range(range.start, range.stop)); - } - return uids; - } -} diff --git a/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java b/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java deleted file mode 100644 index 4071c9ab71b4f..0000000000000 --- a/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; -import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SystemApi; -import android.net.NetworkCapabilities.RedactionType; -import android.os.Parcel; -import android.os.Parcelable; -import android.text.TextUtils; - -import java.util.Objects; - -/** - * Container for VPN-specific transport information. - * - * @see android.net.TransportInfo - * @see NetworkCapabilities#getTransportInfo() - * - * @hide - */ -@SystemApi(client = MODULE_LIBRARIES) -public final class VpnTransportInfo implements TransportInfo, Parcelable { - /** Type of this VPN. */ - private final int mType; - - @Nullable - private final String mSessionId; - - @Override - public @RedactionType long getApplicableRedactions() { - return REDACT_FOR_NETWORK_SETTINGS; - } - - /** - * Create a copy of a {@link VpnTransportInfo} with the sessionId redacted if necessary. - */ - @NonNull - public VpnTransportInfo makeCopy(@RedactionType long redactions) { - return new VpnTransportInfo(mType, - ((redactions & REDACT_FOR_NETWORK_SETTINGS) != 0) ? null : mSessionId); - } - - public VpnTransportInfo(int type, @Nullable String sessionId) { - this.mType = type; - this.mSessionId = sessionId; - } - - /** - * Returns the session Id of this VpnTransportInfo. - */ - @Nullable - public String getSessionId() { - return mSessionId; - } - - /** - * Returns the type of this VPN. - */ - public int getType() { - return mType; - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof VpnTransportInfo)) return false; - - VpnTransportInfo that = (VpnTransportInfo) o; - return (this.mType == that.mType) && TextUtils.equals(this.mSessionId, that.mSessionId); - } - - @Override - public int hashCode() { - return Objects.hash(mType, mSessionId); - } - - @Override - public String toString() { - return String.format("VpnTransportInfo{type=%d, sessionId=%s}", mType, mSessionId); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeInt(mType); - dest.writeString(mSessionId); - } - - public static final @NonNull Creator CREATOR = - new Creator() { - public VpnTransportInfo createFromParcel(Parcel in) { - return new VpnTransportInfo(in.readInt(), in.readString()); - } - public VpnTransportInfo[] newArray(int size) { - return new VpnTransportInfo[size]; - } - }; -} diff --git a/packages/Connectivity/framework/src/android/net/apf/ApfCapabilities.java b/packages/Connectivity/framework/src/android/net/apf/ApfCapabilities.java deleted file mode 100644 index 663c1b3d2dc9f..0000000000000 --- a/packages/Connectivity/framework/src/android/net/apf/ApfCapabilities.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (C) 2016 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.apf; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SystemApi; -import android.content.Context; -import android.content.res.Resources; -import android.net.ConnectivityResources; -import android.os.Parcel; -import android.os.Parcelable; - -/** - * APF program support capabilities. APF stands for Android Packet Filtering and it is a flexible - * way to drop unwanted network packets to save power. - * - * See documentation at hardware/google/apf/apf.h - * - * This class is immutable. - * @hide - */ -@SystemApi -public final class ApfCapabilities implements Parcelable { - private static ConnectivityResources sResources; - - /** - * Version of APF instruction set supported for packet filtering. 0 indicates no support for - * packet filtering using APF programs. - */ - public final int apfVersionSupported; - - /** - * Maximum size of APF program allowed. - */ - public final int maximumApfProgramSize; - - /** - * Format of packets passed to APF filter. Should be one of ARPHRD_* - */ - public final int apfPacketFormat; - - public ApfCapabilities( - int apfVersionSupported, int maximumApfProgramSize, int apfPacketFormat) { - this.apfVersionSupported = apfVersionSupported; - this.maximumApfProgramSize = maximumApfProgramSize; - this.apfPacketFormat = apfPacketFormat; - } - - private ApfCapabilities(Parcel in) { - apfVersionSupported = in.readInt(); - maximumApfProgramSize = in.readInt(); - apfPacketFormat = in.readInt(); - } - - @NonNull - private static synchronized ConnectivityResources getResources(@NonNull Context ctx) { - if (sResources == null) { - sResources = new ConnectivityResources(ctx); - } - return sResources; - } - - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(apfVersionSupported); - dest.writeInt(maximumApfProgramSize); - dest.writeInt(apfPacketFormat); - } - - public static final Creator CREATOR = new Creator() { - @Override - public ApfCapabilities createFromParcel(Parcel in) { - return new ApfCapabilities(in); - } - - @Override - public ApfCapabilities[] newArray(int size) { - return new ApfCapabilities[size]; - } - }; - - @NonNull - @Override - public String toString() { - return String.format("%s{version: %d, maxSize: %d, format: %d}", getClass().getSimpleName(), - apfVersionSupported, maximumApfProgramSize, apfPacketFormat); - } - - @Override - public boolean equals(@Nullable Object obj) { - if (!(obj instanceof ApfCapabilities)) return false; - final ApfCapabilities other = (ApfCapabilities) obj; - return apfVersionSupported == other.apfVersionSupported - && maximumApfProgramSize == other.maximumApfProgramSize - && apfPacketFormat == other.apfPacketFormat; - } - - /** - * Determines whether the APF interpreter advertises support for the data buffer access opcodes - * LDDW (LoaD Data Word) and STDW (STore Data Word). Full LDDW (LoaD Data Word) and - * STDW (STore Data Word) support is present from APFv4 on. - * - * @return {@code true} if the IWifiStaIface#readApfPacketFilterData is supported. - */ - public boolean hasDataAccess() { - return apfVersionSupported >= 4; - } - - /** - * @return Whether the APF Filter in the device should filter out IEEE 802.3 Frames. - */ - public static boolean getApfDrop8023Frames() { - // TODO: deprecate/remove this method (now unused in the platform), as the resource was - // moved to NetworkStack. - final Resources systemRes = Resources.getSystem(); - final int id = systemRes.getIdentifier("config_apfDrop802_3Frames", "bool", "android"); - return systemRes.getBoolean(id); - } - - /** - * @return An array of denylisted EtherType, packets with EtherTypes within it will be dropped. - */ - public static @NonNull int[] getApfEtherTypeBlackList() { - // TODO: deprecate/remove this method (now unused in the platform), as the resource was - // moved to NetworkStack. - final Resources systemRes = Resources.getSystem(); - final int id = systemRes.getIdentifier("config_apfEthTypeBlackList", "array", "android"); - return systemRes.getIntArray(id); - } -} diff --git a/packages/Connectivity/framework/src/android/net/util/DnsUtils.java b/packages/Connectivity/framework/src/android/net/util/DnsUtils.java deleted file mode 100644 index 3fe245edb9e2f..0000000000000 --- a/packages/Connectivity/framework/src/android/net/util/DnsUtils.java +++ /dev/null @@ -1,377 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.util; - -import static android.system.OsConstants.AF_INET; -import static android.system.OsConstants.AF_INET6; -import static android.system.OsConstants.IPPROTO_UDP; -import static android.system.OsConstants.SOCK_DGRAM; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.net.InetAddresses; -import android.net.Network; -import android.system.ErrnoException; -import android.system.Os; -import android.util.Log; - -import libcore.io.IoUtils; - -import java.io.FileDescriptor; -import java.io.IOException; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -/** - * @hide - */ -public class DnsUtils { - private static final String TAG = "DnsUtils"; - private static final int CHAR_BIT = 8; - public static final int IPV6_ADDR_SCOPE_NODELOCAL = 0x01; - public static final int IPV6_ADDR_SCOPE_LINKLOCAL = 0x02; - public static final int IPV6_ADDR_SCOPE_SITELOCAL = 0x05; - public static final int IPV6_ADDR_SCOPE_GLOBAL = 0x0e; - private static final Comparator sRfc6724Comparator = new Rfc6724Comparator(); - - /** - * Comparator to sort SortableAddress in Rfc6724 style. - */ - public static class Rfc6724Comparator implements Comparator { - // This function matches the behaviour of _rfc6724_compare in the native resolver. - @Override - public int compare(SortableAddress span1, SortableAddress span2) { - // Rule 1: Avoid unusable destinations. - if (span1.hasSrcAddr != span2.hasSrcAddr) { - return span2.hasSrcAddr - span1.hasSrcAddr; - } - - // Rule 2: Prefer matching scope. - if (span1.scopeMatch != span2.scopeMatch) { - return span2.scopeMatch - span1.scopeMatch; - } - - // TODO: Implement rule 3: Avoid deprecated addresses. - // TODO: Implement rule 4: Prefer home addresses. - - // Rule 5: Prefer matching label. - if (span1.labelMatch != span2.labelMatch) { - return span2.labelMatch - span1.labelMatch; - } - - // Rule 6: Prefer higher precedence. - if (span1.precedence != span2.precedence) { - return span2.precedence - span1.precedence; - } - - // TODO: Implement rule 7: Prefer native transport. - - // Rule 8: Prefer smaller scope. - if (span1.scope != span2.scope) { - return span1.scope - span2.scope; - } - - // Rule 9: Use longest matching prefix. IPv6 only. - if (span1.prefixMatchLen != span2.prefixMatchLen) { - return span2.prefixMatchLen - span1.prefixMatchLen; - } - - // Rule 10: Leave the order unchanged. Collections.sort is a stable sort. - return 0; - } - } - - /** - * Class used to sort with RFC 6724 - */ - public static class SortableAddress { - public final int label; - public final int labelMatch; - public final int scope; - public final int scopeMatch; - public final int precedence; - public final int prefixMatchLen; - public final int hasSrcAddr; - public final InetAddress address; - - public SortableAddress(@NonNull InetAddress addr, @Nullable InetAddress srcAddr) { - address = addr; - hasSrcAddr = (srcAddr != null) ? 1 : 0; - label = findLabel(addr); - scope = findScope(addr); - precedence = findPrecedence(addr); - labelMatch = ((srcAddr != null) && (label == findLabel(srcAddr))) ? 1 : 0; - scopeMatch = ((srcAddr != null) && (scope == findScope(srcAddr))) ? 1 : 0; - if (isIpv6Address(addr) && isIpv6Address(srcAddr)) { - prefixMatchLen = compareIpv6PrefixMatchLen(srcAddr, addr); - } else { - prefixMatchLen = 0; - } - } - } - - /** - * Sort the given address list in RFC6724 order. - * Will leave the list unchanged if an error occurs. - * - * This function matches the behaviour of _rfc6724_sort in the native resolver. - */ - public static @NonNull List rfc6724Sort(@Nullable Network network, - @NonNull List answers) { - final ArrayList sortableAnswerList = new ArrayList<>(); - for (InetAddress addr : answers) { - sortableAnswerList.add(new SortableAddress(addr, findSrcAddress(network, addr))); - } - - Collections.sort(sortableAnswerList, sRfc6724Comparator); - - final List sortedAnswers = new ArrayList<>(); - for (SortableAddress ans : sortableAnswerList) { - sortedAnswers.add(ans.address); - } - - return sortedAnswers; - } - - private static @Nullable InetAddress findSrcAddress(@Nullable Network network, - @NonNull InetAddress addr) { - final int domain; - if (isIpv4Address(addr)) { - domain = AF_INET; - } else if (isIpv6Address(addr)) { - domain = AF_INET6; - } else { - return null; - } - final FileDescriptor socket; - try { - socket = Os.socket(domain, SOCK_DGRAM, IPPROTO_UDP); - } catch (ErrnoException e) { - Log.e(TAG, "findSrcAddress:" + e.toString()); - return null; - } - try { - if (network != null) network.bindSocket(socket); - Os.connect(socket, new InetSocketAddress(addr, 0)); - return ((InetSocketAddress) Os.getsockname(socket)).getAddress(); - } catch (IOException | ErrnoException e) { - return null; - } finally { - IoUtils.closeQuietly(socket); - } - } - - /** - * Get the label for a given IPv4/IPv6 address. - * RFC 6724, section 2.1. - * - * Note that Java will return an IPv4-mapped address as an IPv4 address. - */ - private static int findLabel(@NonNull InetAddress addr) { - if (isIpv4Address(addr)) { - return 4; - } else if (isIpv6Address(addr)) { - if (addr.isLoopbackAddress()) { - return 0; - } else if (isIpv6Address6To4(addr)) { - return 2; - } else if (isIpv6AddressTeredo(addr)) { - return 5; - } else if (isIpv6AddressULA(addr)) { - return 13; - } else if (((Inet6Address) addr).isIPv4CompatibleAddress()) { - return 3; - } else if (addr.isSiteLocalAddress()) { - return 11; - } else if (isIpv6Address6Bone(addr)) { - return 12; - } else { - // All other IPv6 addresses, including global unicast addresses. - return 1; - } - } else { - // This should never happen. - return 1; - } - } - - private static boolean isIpv6Address(@Nullable InetAddress addr) { - return addr instanceof Inet6Address; - } - - private static boolean isIpv4Address(@Nullable InetAddress addr) { - return addr instanceof Inet4Address; - } - - private static boolean isIpv6Address6To4(@NonNull InetAddress addr) { - if (!isIpv6Address(addr)) return false; - final byte[] byteAddr = addr.getAddress(); - return byteAddr[0] == 0x20 && byteAddr[1] == 0x02; - } - - private static boolean isIpv6AddressTeredo(@NonNull InetAddress addr) { - if (!isIpv6Address(addr)) return false; - final byte[] byteAddr = addr.getAddress(); - return byteAddr[0] == 0x20 && byteAddr[1] == 0x01 && byteAddr[2] == 0x00 - && byteAddr[3] == 0x00; - } - - private static boolean isIpv6AddressULA(@NonNull InetAddress addr) { - return isIpv6Address(addr) && (addr.getAddress()[0] & 0xfe) == 0xfc; - } - - private static boolean isIpv6Address6Bone(@NonNull InetAddress addr) { - if (!isIpv6Address(addr)) return false; - final byte[] byteAddr = addr.getAddress(); - return byteAddr[0] == 0x3f && byteAddr[1] == (byte) 0xfe; - } - - private static int getIpv6MulticastScope(@NonNull InetAddress addr) { - return !isIpv6Address(addr) ? 0 : (addr.getAddress()[1] & 0x0f); - } - - private static int findScope(@NonNull InetAddress addr) { - if (isIpv6Address(addr)) { - if (addr.isMulticastAddress()) { - return getIpv6MulticastScope(addr); - } else if (addr.isLoopbackAddress() || addr.isLinkLocalAddress()) { - /** - * RFC 4291 section 2.5.3 says loopback is to be treated as having - * link-local scope. - */ - return IPV6_ADDR_SCOPE_LINKLOCAL; - } else if (addr.isSiteLocalAddress()) { - return IPV6_ADDR_SCOPE_SITELOCAL; - } else { - return IPV6_ADDR_SCOPE_GLOBAL; - } - } else if (isIpv4Address(addr)) { - if (addr.isLoopbackAddress() || addr.isLinkLocalAddress()) { - return IPV6_ADDR_SCOPE_LINKLOCAL; - } else { - /** - * RFC 6724 section 3.2. Other IPv4 addresses, including private addresses - * and shared addresses (100.64.0.0/10), are assigned global scope. - */ - return IPV6_ADDR_SCOPE_GLOBAL; - } - } else { - /** - * This should never happen. - * Return a scope with low priority as a last resort. - */ - return IPV6_ADDR_SCOPE_NODELOCAL; - } - } - - /** - * Get the precedence for a given IPv4/IPv6 address. - * RFC 6724, section 2.1. - * - * Note that Java will return an IPv4-mapped address as an IPv4 address. - */ - private static int findPrecedence(@NonNull InetAddress addr) { - if (isIpv4Address(addr)) { - return 35; - } else if (isIpv6Address(addr)) { - if (addr.isLoopbackAddress()) { - return 50; - } else if (isIpv6Address6To4(addr)) { - return 30; - } else if (isIpv6AddressTeredo(addr)) { - return 5; - } else if (isIpv6AddressULA(addr)) { - return 3; - } else if (((Inet6Address) addr).isIPv4CompatibleAddress() || addr.isSiteLocalAddress() - || isIpv6Address6Bone(addr)) { - return 1; - } else { - // All other IPv6 addresses, including global unicast addresses. - return 40; - } - } else { - return 1; - } - } - - /** - * Find number of matching initial bits between the two addresses. - */ - private static int compareIpv6PrefixMatchLen(@NonNull InetAddress srcAddr, - @NonNull InetAddress dstAddr) { - final byte[] srcByte = srcAddr.getAddress(); - final byte[] dstByte = dstAddr.getAddress(); - - // This should never happen. - if (srcByte.length != dstByte.length) return 0; - - for (int i = 0; i < dstByte.length; ++i) { - if (srcByte[i] == dstByte[i]) { - continue; - } - int x = (srcByte[i] & 0xff) ^ (dstByte[i] & 0xff); - return i * CHAR_BIT + (Integer.numberOfLeadingZeros(x) - 24); // Java ints are 32 bits - } - return dstByte.length * CHAR_BIT; - } - - /** - * Check if given network has Ipv4 capability - * This function matches the behaviour of have_ipv4 in the native resolver. - */ - public static boolean haveIpv4(@Nullable Network network) { - final SocketAddress addrIpv4 = - new InetSocketAddress(InetAddresses.parseNumericAddress("8.8.8.8"), 0); - return checkConnectivity(network, AF_INET, addrIpv4); - } - - /** - * Check if given network has Ipv6 capability - * This function matches the behaviour of have_ipv6 in the native resolver. - */ - public static boolean haveIpv6(@Nullable Network network) { - final SocketAddress addrIpv6 = - new InetSocketAddress(InetAddresses.parseNumericAddress("2000::"), 0); - return checkConnectivity(network, AF_INET6, addrIpv6); - } - - private static boolean checkConnectivity(@Nullable Network network, - int domain, @NonNull SocketAddress addr) { - final FileDescriptor socket; - try { - socket = Os.socket(domain, SOCK_DGRAM, IPPROTO_UDP); - } catch (ErrnoException e) { - return false; - } - try { - if (network != null) network.bindSocket(socket); - Os.connect(socket, addr); - } catch (IOException | ErrnoException e) { - return false; - } finally { - IoUtils.closeQuietly(socket); - } - return true; - } -} diff --git a/packages/Connectivity/framework/src/android/net/util/KeepaliveUtils.java b/packages/Connectivity/framework/src/android/net/util/KeepaliveUtils.java deleted file mode 100644 index 8d7a0b3d02edf..0000000000000 --- a/packages/Connectivity/framework/src/android/net/util/KeepaliveUtils.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.util; - -import android.annotation.NonNull; -import android.content.Context; -import android.content.res.Resources; -import android.net.ConnectivityResources; -import android.net.NetworkCapabilities; -import android.text.TextUtils; -import android.util.AndroidRuntimeException; - -/** - * Collection of utilities for socket keepalive offload. - * - * @hide - */ -public final class KeepaliveUtils { - - public static final String TAG = "KeepaliveUtils"; - - public static class KeepaliveDeviceConfigurationException extends AndroidRuntimeException { - public KeepaliveDeviceConfigurationException(final String msg) { - super(msg); - } - } - - /** - * Read supported keepalive count for each transport type from overlay resource. This should be - * used to create a local variable store of resource customization, and use it as the input for - * {@link getSupportedKeepalivesForNetworkCapabilities}. - * - * @param context The context to read resource from. - * @return An array of supported keepalive count for each transport type. - */ - @NonNull - public static int[] getSupportedKeepalives(@NonNull Context context) { - String[] res = null; - try { - final ConnectivityResources connRes = new ConnectivityResources(context); - // TODO: use R.id.config_networkSupportedKeepaliveCount directly - final int id = connRes.get().getIdentifier("config_networkSupportedKeepaliveCount", - "array", connRes.getResourcesContext().getPackageName()); - res = new ConnectivityResources(context).get().getStringArray(id); - } catch (Resources.NotFoundException unused) { - } - if (res == null) throw new KeepaliveDeviceConfigurationException("invalid resource"); - - final int[] ret = new int[NetworkCapabilities.MAX_TRANSPORT + 1]; - for (final String row : res) { - if (TextUtils.isEmpty(row)) { - throw new KeepaliveDeviceConfigurationException("Empty string"); - } - final String[] arr = row.split(","); - if (arr.length != 2) { - throw new KeepaliveDeviceConfigurationException("Invalid parameter length"); - } - - int transport; - int supported; - try { - transport = Integer.parseInt(arr[0]); - supported = Integer.parseInt(arr[1]); - } catch (NumberFormatException e) { - throw new KeepaliveDeviceConfigurationException("Invalid number format"); - } - - if (!NetworkCapabilities.isValidTransport(transport)) { - throw new KeepaliveDeviceConfigurationException("Invalid transport " + transport); - } - - if (supported < 0) { - throw new KeepaliveDeviceConfigurationException( - "Invalid supported count " + supported + " for " - + NetworkCapabilities.transportNameOf(transport)); - } - ret[transport] = supported; - } - return ret; - } - - /** - * Get supported keepalive count for the given {@link NetworkCapabilities}. - * - * @param supportedKeepalives An array of supported keepalive count for each transport type. - * @param nc The {@link NetworkCapabilities} of the network the socket keepalive is on. - * - * @return Supported keepalive count for the given {@link NetworkCapabilities}. - */ - public static int getSupportedKeepalivesForNetworkCapabilities( - @NonNull int[] supportedKeepalives, @NonNull NetworkCapabilities nc) { - final int[] transports = nc.getTransportTypes(); - if (transports.length == 0) return 0; - int supportedCount = supportedKeepalives[transports[0]]; - // Iterate through transports and return minimum supported value. - for (final int transport : transports) { - if (supportedCount > supportedKeepalives[transport]) { - supportedCount = supportedKeepalives[transport]; - } - } - return supportedCount; - } -} diff --git a/packages/Connectivity/framework/src/android/net/util/MultinetworkPolicyTracker.java b/packages/Connectivity/framework/src/android/net/util/MultinetworkPolicyTracker.java deleted file mode 100644 index 0b42a0036925f..0000000000000 --- a/packages/Connectivity/framework/src/android/net/util/MultinetworkPolicyTracker.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.util; - -import static android.net.ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI; -import static android.net.ConnectivitySettingsManager.NETWORK_METERED_MULTIPATH_PREFERENCE; - -import android.annotation.NonNull; -import android.content.BroadcastReceiver; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.res.Resources; -import android.database.ContentObserver; -import android.net.ConnectivityResources; -import android.net.Uri; -import android.os.Handler; -import android.provider.Settings; -import android.telephony.SubscriptionManager; -import android.telephony.TelephonyCallback; -import android.telephony.TelephonyManager; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; - -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.Executor; -import java.util.concurrent.RejectedExecutionException; - -/** - * A class to encapsulate management of the "Smart Networking" capability of - * avoiding bad Wi-Fi when, for example upstream connectivity is lost or - * certain critical link failures occur. - * - * This enables the device to switch to another form of connectivity, like - * mobile, if it's available and working. - * - * The Runnable |avoidBadWifiCallback|, if given, is posted to the supplied - * Handler' whenever the computed "avoid bad wifi" value changes. - * - * Disabling this reverts the device to a level of networking sophistication - * circa 2012-13 by disabling disparate code paths each of which contribute to - * maintaining continuous, working Internet connectivity. - * - * @hide - */ -public class MultinetworkPolicyTracker { - private static String TAG = MultinetworkPolicyTracker.class.getSimpleName(); - - private final Context mContext; - private final ConnectivityResources mResources; - private final Handler mHandler; - private final Runnable mAvoidBadWifiCallback; - private final List mSettingsUris; - private final ContentResolver mResolver; - private final SettingObserver mSettingObserver; - private final BroadcastReceiver mBroadcastReceiver; - - private volatile boolean mAvoidBadWifi = true; - private volatile int mMeteredMultipathPreference; - private int mActiveSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; - - // Mainline module can't use internal HandlerExecutor, so add an identical executor here. - private static class HandlerExecutor implements Executor { - @NonNull - private final Handler mHandler; - - HandlerExecutor(@NonNull Handler handler) { - mHandler = handler; - } - @Override - public void execute(Runnable command) { - if (!mHandler.post(command)) { - throw new RejectedExecutionException(mHandler + " is shutting down"); - } - } - } - - @VisibleForTesting - protected class ActiveDataSubscriptionIdListener extends TelephonyCallback - implements TelephonyCallback.ActiveDataSubscriptionIdListener { - @Override - public void onActiveDataSubscriptionIdChanged(int subId) { - mActiveSubId = subId; - reevaluateInternal(); - } - } - - public MultinetworkPolicyTracker(Context ctx, Handler handler) { - this(ctx, handler, null); - } - - public MultinetworkPolicyTracker(Context ctx, Handler handler, Runnable avoidBadWifiCallback) { - mContext = ctx; - mResources = new ConnectivityResources(ctx); - mHandler = handler; - mAvoidBadWifiCallback = avoidBadWifiCallback; - mSettingsUris = Arrays.asList( - Settings.Global.getUriFor(NETWORK_AVOID_BAD_WIFI), - Settings.Global.getUriFor(NETWORK_METERED_MULTIPATH_PREFERENCE)); - mResolver = mContext.getContentResolver(); - mSettingObserver = new SettingObserver(); - mBroadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - reevaluateInternal(); - } - }; - - ctx.getSystemService(TelephonyManager.class).registerTelephonyCallback( - new HandlerExecutor(handler), new ActiveDataSubscriptionIdListener()); - - updateAvoidBadWifi(); - updateMeteredMultipathPreference(); - } - - public void start() { - for (Uri uri : mSettingsUris) { - mResolver.registerContentObserver(uri, false, mSettingObserver); - } - - final IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); - mContext.registerReceiverForAllUsers(mBroadcastReceiver, intentFilter, - null /* broadcastPermission */, mHandler); - - reevaluate(); - } - - public void shutdown() { - mResolver.unregisterContentObserver(mSettingObserver); - - mContext.unregisterReceiver(mBroadcastReceiver); - } - - public boolean getAvoidBadWifi() { - return mAvoidBadWifi; - } - - // TODO: move this to MultipathPolicyTracker. - public int getMeteredMultipathPreference() { - return mMeteredMultipathPreference; - } - - /** - * Whether the device or carrier configuration disables avoiding bad wifi by default. - */ - public boolean configRestrictsAvoidBadWifi() { - // TODO: use R.integer.config_networkAvoidBadWifi directly - final int id = mResources.get().getIdentifier("config_networkAvoidBadWifi", - "integer", mResources.getResourcesContext().getPackageName()); - return (getResourcesForActiveSubId().getInteger(id) == 0); - } - - @NonNull - private Resources getResourcesForActiveSubId() { - return SubscriptionManager.getResourcesForSubId( - mResources.getResourcesContext(), mActiveSubId); - } - - /** - * Whether we should display a notification when wifi becomes unvalidated. - */ - public boolean shouldNotifyWifiUnvalidated() { - return configRestrictsAvoidBadWifi() && getAvoidBadWifiSetting() == null; - } - - public String getAvoidBadWifiSetting() { - return Settings.Global.getString(mResolver, NETWORK_AVOID_BAD_WIFI); - } - - @VisibleForTesting - public void reevaluate() { - mHandler.post(this::reevaluateInternal); - } - - /** - * Reevaluate the settings. Must be called on the handler thread. - */ - private void reevaluateInternal() { - if (updateAvoidBadWifi() && mAvoidBadWifiCallback != null) { - mAvoidBadWifiCallback.run(); - } - updateMeteredMultipathPreference(); - } - - public boolean updateAvoidBadWifi() { - final boolean settingAvoidBadWifi = "1".equals(getAvoidBadWifiSetting()); - final boolean prev = mAvoidBadWifi; - mAvoidBadWifi = settingAvoidBadWifi || !configRestrictsAvoidBadWifi(); - return mAvoidBadWifi != prev; - } - - /** - * The default (device and carrier-dependent) value for metered multipath preference. - */ - public int configMeteredMultipathPreference() { - // TODO: use R.integer.config_networkMeteredMultipathPreference directly - final int id = mResources.get().getIdentifier("config_networkMeteredMultipathPreference", - "integer", mResources.getResourcesContext().getPackageName()); - return mResources.get().getInteger(id); - } - - public void updateMeteredMultipathPreference() { - String setting = Settings.Global.getString(mResolver, NETWORK_METERED_MULTIPATH_PREFERENCE); - try { - mMeteredMultipathPreference = Integer.parseInt(setting); - } catch (NumberFormatException e) { - mMeteredMultipathPreference = configMeteredMultipathPreference(); - } - } - - private class SettingObserver extends ContentObserver { - public SettingObserver() { - super(null); - } - - @Override - public void onChange(boolean selfChange) { - Log.wtf(TAG, "Should never be reached."); - } - - @Override - public void onChange(boolean selfChange, Uri uri) { - if (!mSettingsUris.contains(uri)) { - Log.wtf(TAG, "Unexpected settings observation: " + uri); - } - reevaluate(); - } - } -} diff --git a/packages/Connectivity/service/Android.bp b/packages/Connectivity/service/Android.bp deleted file mode 100644 index 72654260aeffe..0000000000000 --- a/packages/Connectivity/service/Android.bp +++ /dev/null @@ -1,119 +0,0 @@ -// -// Copyright (C) 2020 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_base_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_base_license"], -} - -cc_library_shared { - name: "libservice-connectivity", - min_sdk_version: "30", - cflags: [ - "-Wall", - "-Werror", - "-Wno-unused-parameter", - "-Wthread-safety", - ], - srcs: [ - "jni/com_android_server_TestNetworkService.cpp", - "jni/onload.cpp", - ], - stl: "libc++_static", - header_libs: [ - "libbase_headers", - ], - shared_libs: [ - "liblog", - "libnativehelper", - ], - apex_available: [ - "com.android.tethering", - ], -} - -java_library { - name: "service-connectivity-pre-jarjar", - sdk_version: "system_server_current", - min_sdk_version: "30", - srcs: [ - "src/**/*.java", - ":framework-connectivity-shared-srcs", - ":services-connectivity-shared-srcs", - // TODO: move to net-utils-device-common, enable shrink optimization to avoid extra classes - ":net-module-utils-srcs", - ], - libs: [ - // TODO (b/183097033) remove once system_server_current includes core_current - "stable.core.platform.api.stubs", - "android_system_server_stubs_current", - "framework-annotations-lib", - "framework-connectivity-annotations", - "framework-connectivity.impl", - "framework-tethering.stubs.module_lib", - "framework-wifi.stubs.module_lib", - "unsupportedappusage", - "ServiceConnectivityResources", - ], - static_libs: [ - "dnsresolver_aidl_interface-V8-java", - "modules-utils-os", - "net-utils-device-common", - "net-utils-framework-common", - "netd-client", - "netlink-client", - "networkstack-client", - "PlatformProperties", - "service-connectivity-protos", - ], - apex_available: [ - "com.android.tethering", - ], -} - -java_library { - name: "service-connectivity-protos", - sdk_version: "system_current", - min_sdk_version: "30", - proto: { - type: "nano", - }, - srcs: [ - ":system-messages-proto-src", - ], - libs: ["libprotobuf-java-nano"], - apex_available: [ - "com.android.tethering", - ], -} - -java_library { - name: "service-connectivity", - sdk_version: "system_server_current", - min_sdk_version: "30", - installable: true, - static_libs: [ - "service-connectivity-pre-jarjar", - ], - jarjar_rules: "jarjar-rules.txt", - apex_available: [ - "com.android.tethering", - ], -} diff --git a/packages/Connectivity/service/ServiceConnectivityResources/Android.bp b/packages/Connectivity/service/ServiceConnectivityResources/Android.bp deleted file mode 100644 index f491cc762b3cf..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/Android.bp +++ /dev/null @@ -1,40 +0,0 @@ -// -// 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. -// - -// APK to hold all the wifi overlayable resources. -package { - default_applicable_licenses: ["Android-Apache-2.0"], -} - -android_app { - name: "ServiceConnectivityResources", - sdk_version: "module_30", - min_sdk_version: "30", - resource_dirs: [ - "res", - ], - privileged: true, - export_package_resources: true, - apex_available: [ - "com.android.tethering", - ], - certificate: ":com.android.connectivity.resources.certificate", -} - -android_app_certificate { - name: "com.android.connectivity.resources.certificate", - certificate: "resources-certs/com.android.connectivity.resources", -} diff --git a/packages/Connectivity/service/ServiceConnectivityResources/AndroidManifest.xml b/packages/Connectivity/service/ServiceConnectivityResources/AndroidManifest.xml deleted file mode 100644 index 2c303026158ef..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/AndroidManifest.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-hdpi/stat_notify_rssi_in_range.png b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-hdpi/stat_notify_rssi_in_range.png deleted file mode 100644 index 74977e6aefffb..0000000000000 Binary files a/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-hdpi/stat_notify_rssi_in_range.png and /dev/null differ diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-mdpi/stat_notify_rssi_in_range.png b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-mdpi/stat_notify_rssi_in_range.png deleted file mode 100644 index 62e4fe94a35c1..0000000000000 Binary files a/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-mdpi/stat_notify_rssi_in_range.png and /dev/null differ diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-xhdpi/stat_notify_rssi_in_range.png b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-xhdpi/stat_notify_rssi_in_range.png deleted file mode 100644 index c0586d8bc21ee..0000000000000 Binary files a/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-xhdpi/stat_notify_rssi_in_range.png and /dev/null differ diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-xxhdpi/stat_notify_rssi_in_range.png b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-xxhdpi/stat_notify_rssi_in_range.png deleted file mode 100644 index 86c34ed18d736..0000000000000 Binary files a/packages/Connectivity/service/ServiceConnectivityResources/res/drawable-xxhdpi/stat_notify_rssi_in_range.png and /dev/null differ diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/drawable/stat_notify_wifi_in_range.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/drawable/stat_notify_wifi_in_range.xml deleted file mode 100644 index a271ca5224c7a..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/drawable/stat_notify_wifi_in_range.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-af/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-af/strings.xml deleted file mode 100644 index 550ab8a65d0a5..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-af/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Stelselkonnektiwiteithulpbronne" - "Meld aan by Wi-Fi-netwerk" - "Meld by netwerk aan" - - - "%1$s het geen internettoegang nie" - "Tik vir opsies" - "Selnetwerk het nie internettoegang nie" - "Netwerk het nie internettoegang nie" - "Daar kan nie by private DNS-bediener ingegaan word nie" - "%1$s het beperkte konnektiwiteit" - "Tik om in elk geval te koppel" - "Het oorgeskakel na %1$s" - "Toestel gebruik %1$s wanneer %2$s geen internettoegang het nie. Heffings kan geld." - "Het oorgeskakel van %1$s na %2$s" - - "mobiele data" - "Wi-fi" - "Bluetooth" - "Ethernet" - "VPN" - - "\'n onbekende netwerktipe" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-am/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-am/strings.xml deleted file mode 100644 index 7f1a9dbe51ef1..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-am/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "የስርዓት ግንኙነት መርጃዎች" - "ወደ Wi-Fi አውታረ መረብ በመለያ ግባ" - "ወደ አውታረ መረብ በመለያ ይግቡ" - - - "%1$s ምንም የበይነ መረብ መዳረሻ የለም" - "ለአማራጮች መታ ያድርጉ" - "የተንቀሳቃሽ ስልክ አውታረ መረብ የበይነመረብ መዳረሻ የለውም" - "አውታረ መረብ የበይነመረብ መዳረሻ የለውም" - "የግል ዲኤንኤስ አገልጋይ ሊደረስበት አይችልም" - "%1$s የተገደበ ግንኙነት አለው" - "ለማንኛውም ለማገናኘት መታ ያድርጉ" - "ወደ %1$s ተቀይሯል" - "%2$s ምንም ዓይነት የበይነመረብ ግንኙነት በማይኖረው ጊዜ መሣሪያዎች %1$sን ይጠቀማሉ። ክፍያዎች ተፈጻሚ ሊሆኑ ይችላሉ።" - "ከ%1$s ወደ %2$s ተቀይሯል" - - "የተንቀሳቃሽ ስልክ ውሂብ" - "Wi-Fi" - "ብሉቱዝ" - "ኢተርኔት" - "VPN" - - "አንድ ያልታወቀ አውታረ መረብ ዓይነት" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ar/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ar/strings.xml deleted file mode 100644 index b7a62c5e1df0c..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ar/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "مصادر إمكانية اتصال الخادم" - "‏تسجيل الدخول إلى شبكة Wi-Fi" - "تسجيل الدخول إلى الشبكة" - - - "لا يتوفّر في %1$s إمكانية الاتصال بالإنترنت." - "انقر للحصول على الخيارات." - "شبكة الجوّال هذه غير متصلة بالإنترنت" - "الشبكة غير متصلة بالإنترنت" - "لا يمكن الوصول إلى خادم أسماء نظام نطاقات خاص" - "إمكانية اتصال %1$s محدودة." - "يمكنك النقر للاتصال على أي حال." - "تم التبديل إلى %1$s" - "يستخدم الجهاز %1$s عندما لا يتوفر اتصال بالإنترنت في شبكة %2$s، ويمكن أن يتم فرض رسوم مقابل ذلك." - "تم التبديل من %1$s إلى %2$s" - - "بيانات الجوّال" - "Wi-Fi" - "بلوتوث" - "إيثرنت" - "‏شبكة افتراضية خاصة (VPN)" - - "نوع شبكة غير معروف" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-as/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-as/strings.xml deleted file mode 100644 index cf8e6ac9d4092..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-as/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "ছিষ্টেম সংযোগৰ উৎস" - "ৱাই-ফাই নেটৱৰ্কত ছাইন ইন কৰক" - "নেটৱৰ্কত ছাইন ইন কৰক" - - - "%1$sৰ ইণ্টাৰনেটৰ এক্সেছ নাই" - "অধিক বিকল্পৰ বাবে টিপক" - "ম’বাইল নেটৱৰ্কৰ কোনো ইণ্টাৰনেটৰ এক্সেছ নাই" - "নেটৱৰ্কৰ কোনো ইণ্টাৰনেটৰ এক্সেছ নাই" - "ব্যক্তিগত DNS ছাৰ্ভাৰ এক্সেছ কৰিব নোৱাৰি" - "%1$sৰ সকলো সেৱাৰ এক্সেছ নাই" - "যিকোনো প্ৰকাৰে সংযোগ কৰিবলৈ টিপক" - "%1$sলৈ সলনি কৰা হ’ল" - "যেতিয়া %2$sত ইণ্টাৰনেট নাথাকে, তেতিয়া ডিভাইচে %1$sক ব্যৱহাৰ কৰে। মাচুল প্ৰযোজ্য হ\'ব পাৰে।" - "%1$sৰ পৰা %2$s লৈ সলনি কৰা হ’ল" - - "ম’বাইল ডেটা" - "ৱাই-ফাই" - "ব্লুটুথ" - "ইথাৰনেট" - "ভিপিএন" - - "অজ্ঞাত প্ৰকাৰৰ নেটৱৰ্ক" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-az/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-az/strings.xml deleted file mode 100644 index 7e927ed41b5c8..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-az/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Sistem Bağlantı Resursları" - "Wi-Fi şəbəkəsinə daxil ol" - "Şəbəkəyə daxil olun" - - - "%1$s üçün internet girişi əlçatan deyil" - "Seçimlər üçün tıklayın" - "Mobil şəbəkənin internetə girişi yoxdur" - "Şəbəkənin internetə girişi yoxdur" - "Özəl DNS serverinə giriş mümkün deyil" - "%1$s bağlantını məhdudlaşdırdı" - "İstənilən halda klikləyin" - "%1$s şəbəkə növünə keçirildi" - "%2$s şəbəkəsinin internetə girişi olmadıqda, cihaz %1$s şəbəkəsini istifadə edir. Xidmət haqqı tutula bilər." - "%1$s şəbəkəsindən %2$s şəbəkəsinə keçirildi" - - "mobil data" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "naməlum şəbəkə növü" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-b+sr+Latn/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-b+sr+Latn/strings.xml deleted file mode 100644 index 3f1b976fb9398..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-b+sr+Latn/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Resursi za povezivanje sa sistemom" - "Prijavljivanje na WiFi mrežu" - "Prijavite se na mrežu" - - - "%1$s nema pristup internetu" - "Dodirnite za opcije" - "Mobilna mreža nema pristup internetu" - "Mreža nema pristup internetu" - "Pristup privatnom DNS serveru nije uspeo" - "%1$s ima ograničenu vezu" - "Dodirnite da biste se ipak povezali" - "Prešli ste na tip mreže %1$s" - "Uređaj koristi tip mreže %1$s kada tip mreže %2$s nema pristup internetu. Možda će se naplaćivati troškovi." - "Prešli ste sa tipa mreže %1$s na tip mreže %2$s" - - "mobilni podaci" - "WiFi" - "Bluetooth" - "Eternet" - "VPN" - - "nepoznat tip mreže" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-be/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-be/strings.xml deleted file mode 100644 index 21edf24054817..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-be/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Рэсурсы для падключэння да сістэмы" - "Уваход у сетку Wi-Fi" - "Увайдзіце ў сетку" - - - "%1$s не мае доступу ў інтэрнэт" - "Дакраніцеся, каб убачыць параметры" - "Мабільная сетка не мае доступу ў інтэрнэт" - "Сетка не мае доступу ў інтэрнэт" - "Не ўдалося атрымаць доступ да прыватнага DNS-сервера" - "%1$s мае абмежаваную магчымасць падключэння" - "Націсніце, каб падключыцца" - "Выкананы пераход да %1$s" - "Прылада выкарыстоўвае сетку %1$s, калі ў сетцы %2$s няма доступу да інтэрнэту. Можа спаганяцца плата." - "Выкананы пераход з %1$s да %2$s" - - "мабільная перадача даных" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "невядомы тып сеткі" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-bg/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-bg/strings.xml deleted file mode 100644 index c3c2d722f42bd..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-bg/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Ресурси за свързаността на системата" - "Влизане в Wi-Fi мрежа" - "Вход в мрежата" - - - "%1$s няма достъп до интернет" - "Докоснете за опции" - "Мобилната мрежа няма достъп до интернет" - "Мрежата няма достъп до интернет" - "Не може да се осъществи достъп до частния DNS сървър" - "%1$s има ограничена свързаност" - "Докоснете, за да се свържете въпреки това" - "Превключи се към %1$s" - "Устройството използва %1$s, когато %2$s няма достъп до интернет. Възможно е да бъдете таксувани." - "Превключи се от %1$s към %2$s" - - "мобилни данни" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "неизвестен тип мрежа" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-bn/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-bn/strings.xml deleted file mode 100644 index 0f693bd60c629..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-bn/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "সিস্টেম কানেক্টিভিটি রিসোর্সেস" - "ওয়াই-ফাই নেটওয়ার্কে সাইন-ইন করুন" - "নেটওয়ার্কে সাইন-ইন করুন" - - - "%1$s-এর ইন্টারনেটে অ্যাক্সেস নেই" - "বিকল্পগুলির জন্য আলতো চাপুন" - "মোবাইল নেটওয়ার্কে কোনও ইন্টারনেট অ্যাক্সেস নেই" - "নেটওয়ার্কে কোনও ইন্টারনেট অ্যাক্সেস নেই" - "ব্যক্তিগত ডিএনএস সার্ভার অ্যাক্সেস করা যাবে না" - "%1$s-এর সীমিত কানেক্টিভিটি আছে" - "তবুও কানেক্ট করতে ট্যাপ করুন" - "%1$s এ পাল্টানো হয়েছে" - "%2$s এ ইন্টারনেট অ্যাক্সেস না থাকলে %1$s ব্যবহার করা হয়৷ ডেটা চার্জ প্রযোজ্য৷" - "%1$s থেকে %2$s এ পাল্টানো হয়েছে" - - "মোবাইল ডেটা" - "ওয়াই-ফাই" - "ব্লুটুথ" - "ইথারনেট" - "VPN" - - "এই নেটওয়ার্কের ধরন অজানা" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-bs/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-bs/strings.xml deleted file mode 100644 index 33d6ed9147280..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-bs/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Izvori povezivosti sistema" - "Prijavljivanje na WiFi mrežu" - "Prijava na mrežu" - - - "Mreža %1$s nema pristup internetu" - "Dodirnite za opcije" - "Mobilna mreža nema pristup internetu" - "Mreža nema pristup internetu" - "Nije moguće pristupiti privatnom DNS serveru" - "Mreža %1$s ima ograničenu povezivost" - "Dodirnite da se ipak povežete" - "Prebačeno na: %1$s" - "Kada %2$s nema pristup internetu, uređaj koristi mrežu %1$s. Moguća je naplata usluge." - "Prebačeno iz mreže %1$s u %2$s mrežu" - - "prijenos podataka na mobilnoj mreži" - "WiFi" - "Bluetooth" - "Ethernet" - "VPN" - - "nepoznata vrsta mreže" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ca/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ca/strings.xml deleted file mode 100644 index 04f6bd211c833..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ca/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Recursos de connectivitat del sistema" - "Inicia la sessió a la xarxa Wi-Fi" - "Inicia la sessió a la xarxa" - - - "%1$s no té accés a Internet" - "Toca per veure les opcions" - "La xarxa mòbil no té accés a Internet" - "La xarxa no té accés a Internet" - "No es pot accedir al servidor DNS privat" - "%1$s té una connectivitat limitada" - "Toca per connectar igualment" - "Actualment en ús: %1$s" - "El dispositiu utilitza %1$s en cas que %2$s no tingui accés a Internet. És possible que s\'hi apliquin càrrecs." - "Abans es feia servir la xarxa %1$s; ara s\'utilitza %2$s" - - "dades mòbils" - "Wi‑Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "un tipus de xarxa desconegut" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-cs/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-cs/strings.xml deleted file mode 100644 index 6309e788e6317..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-cs/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Zdroje pro připojení systému" - "Přihlásit se k síti Wi-Fi" - "Přihlásit se k síti" - - - "Síť %1$s nemá přístup k internetu" - "Klepnutím zobrazíte možnosti" - "Mobilní síť nemá přístup k internetu" - "Síť nemá přístup k internetu" - "Nelze získat přístup k soukromému serveru DNS" - "Síť %1$s umožňuje jen omezené připojení" - "Klepnutím se i přesto připojíte" - "Přechod na síť %1$s" - "Když síť %2$s nebude mít přístup k internetu, zařízení použije síť %1$s. Mohou být účtovány poplatky." - "Přechod ze sítě %1$s na síť %2$s" - - "mobilní data" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "neznámý typ sítě" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-da/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-da/strings.xml deleted file mode 100644 index 57c58afc41473..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-da/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Systemets forbindelsesressourcer" - "Log ind på Wi-Fi-netværk" - "Log ind på netværk" - - - "%1$s har ingen internetforbindelse" - "Tryk for at se valgmuligheder" - "Mobilnetværket har ingen internetadgang" - "Netværket har ingen internetadgang" - "Der er ikke adgang til den private DNS-server" - "%1$s har begrænset forbindelse" - "Tryk for at oprette forbindelse alligevel" - "Der blev skiftet til %1$s" - "Enheden benytter %1$s, når der ikke er internetadgang via %2$s. Der opkræves muligvis betaling." - "Der blev skiftet fra %1$s til %2$s" - - "mobildata" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "en ukendt netværkstype" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-de/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-de/strings.xml deleted file mode 100644 index d0c255197ac8f..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-de/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Systemverbindungsressourcen" - "In WLAN anmelden" - "Im Netzwerk anmelden" - - - "%1$s hat keinen Internetzugriff" - "Für Optionen tippen" - "Mobiles Netzwerk hat keinen Internetzugriff" - "Netzwerk hat keinen Internetzugriff" - "Auf den privaten DNS-Server kann nicht zugegriffen werden" - "Schlechte Verbindung mit %1$s" - "Tippen, um die Verbindung trotzdem herzustellen" - "Zu %1$s gewechselt" - "Auf dem Gerät werden %1$s genutzt, wenn über %2$s kein Internet verfügbar ist. Eventuell fallen Gebühren an." - "Von \"%1$s\" zu \"%2$s\" gewechselt" - - "Mobile Daten" - "WLAN" - "Bluetooth" - "Ethernet" - "VPN" - - "ein unbekannter Netzwerktyp" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-el/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-el/strings.xml deleted file mode 100644 index 1c2838dfd4700..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-el/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Πόροι συνδεσιμότητας συστήματος" - "Συνδεθείτε στο δίκτυο Wi-Fi" - "Σύνδεση στο δίκτυο" - - - "Η εφαρμογή %1$s δεν έχει πρόσβαση στο διαδίκτυο" - "Πατήστε για να δείτε τις επιλογές" - "Το δίκτυο κινητής τηλεφωνίας δεν έχει πρόσβαση στο διαδίκτυο." - "Το δίκτυο δεν έχει πρόσβαση στο διαδίκτυο." - "Δεν είναι δυνατή η πρόσβαση στον ιδιωτικό διακομιστή DNS." - "Το δίκτυο %1$s έχει περιορισμένη συνδεσιμότητα" - "Πατήστε για σύνδεση ούτως ή άλλως" - "Μετάβαση σε δίκτυο %1$s" - "Η συσκευή χρησιμοποιεί το δίκτυο %1$s όταν το δίκτυο %2$s δεν έχει πρόσβαση στο διαδίκτυο. Μπορεί να ισχύουν χρεώσεις." - "Μετάβαση από το δίκτυο %1$s στο δίκτυο %2$s" - - "δεδομένα κινητής τηλεφωνίας" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "άγνωστος τύπος δικτύου" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rAU/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rAU/strings.xml deleted file mode 100644 index db5ad7029b6f0..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rAU/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "System connectivity resources" - "Sign in to a Wi-Fi network" - "Sign in to network" - - - "%1$s has no Internet access" - "Tap for options" - "Mobile network has no Internet access" - "Network has no Internet access" - "Private DNS server cannot be accessed" - "%1$s has limited connectivity" - "Tap to connect anyway" - "Switched to %1$s" - "Device uses %1$s when %2$s has no Internet access. Charges may apply." - "Switched from %1$s to %2$s" - - "mobile data" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "an unknown network type" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rCA/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rCA/strings.xml deleted file mode 100644 index db5ad7029b6f0..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rCA/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "System connectivity resources" - "Sign in to a Wi-Fi network" - "Sign in to network" - - - "%1$s has no Internet access" - "Tap for options" - "Mobile network has no Internet access" - "Network has no Internet access" - "Private DNS server cannot be accessed" - "%1$s has limited connectivity" - "Tap to connect anyway" - "Switched to %1$s" - "Device uses %1$s when %2$s has no Internet access. Charges may apply." - "Switched from %1$s to %2$s" - - "mobile data" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "an unknown network type" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rGB/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rGB/strings.xml deleted file mode 100644 index db5ad7029b6f0..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rGB/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "System connectivity resources" - "Sign in to a Wi-Fi network" - "Sign in to network" - - - "%1$s has no Internet access" - "Tap for options" - "Mobile network has no Internet access" - "Network has no Internet access" - "Private DNS server cannot be accessed" - "%1$s has limited connectivity" - "Tap to connect anyway" - "Switched to %1$s" - "Device uses %1$s when %2$s has no Internet access. Charges may apply." - "Switched from %1$s to %2$s" - - "mobile data" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "an unknown network type" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rIN/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rIN/strings.xml deleted file mode 100644 index db5ad7029b6f0..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rIN/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "System connectivity resources" - "Sign in to a Wi-Fi network" - "Sign in to network" - - - "%1$s has no Internet access" - "Tap for options" - "Mobile network has no Internet access" - "Network has no Internet access" - "Private DNS server cannot be accessed" - "%1$s has limited connectivity" - "Tap to connect anyway" - "Switched to %1$s" - "Device uses %1$s when %2$s has no Internet access. Charges may apply." - "Switched from %1$s to %2$s" - - "mobile data" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "an unknown network type" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rXC/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rXC/strings.xml deleted file mode 100644 index 2602bfa065314..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-en-rXC/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‏‏‏‎‏‏‎‎‎‏‎‎‎‎‎‎‎‎‏‏‎‏‏‏‏‎‎‎‎‏‏‏‎‎‏‏‎‏‏‏‎‏‎‏‏‏‎‎‎‏‎‏‏‎System Connectivity Resources‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‏‏‎‏‎‏‎‏‎‎‎‎‎‏‏‎‏‏‏‏‎‏‎‏‎‏‎‎‎‎‏‏‏‏‎‎‏‎‎‎‏‏‎‎‏‎‏‎‏‎‏‏‎‎‏‎Sign in to Wi-Fi network‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‏‎‏‏‎‎‏‎‏‎‎‏‏‎‎‏‏‎‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‏‏‏‎‎‎‎‎‏‏‎‏‎‎‏‏‎‎‎‎Sign in to network‎‏‎‎‏‎" - - - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‏‏‏‎‏‎‏‏‎‎‎‏‏‎‏‎‏‏‏‎‎‏‎‎‏‏‎‏‏‎‎‏‏‎‏‏‏‎‏‏‏‏‎‎‎‏‏‏‏‏‎‎‏‎‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ has no internet access‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‎‏‏‏‎‏‎‎‎‎‏‎‏‏‏‏‎‏‏‎‏‎‎‏‏‏‏‎‏‏‎‎‏‏‏‏‎‏‏‏‏‏‎‎‏‎‎‏‎‏‎‎‎‎Tap for options‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‎‎‏‏‎‎‏‏‎‎‏‏‎‎‎‎‏‎‏‏‏‏‎‏‎‏‎‏‎‎‏‎‎‏‎‎‏‎‎‏‏‎‏‎‏‏‏‎Mobile network has no internet access‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‎‏‎‎‎‏‎‏‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‏‏‎‏‎‏‎‎‎‏‎‎‎‏‏‎‎‏‏‏‏‏‏‎‏‎‏‏‎Network has no internet access‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‎‎‎‏‏‏‎‏‏‎‏‎‏‎‎‎‎‏‎‏‎‏‏‎‎‏‏‏‎‎‎‎‎‏‎Private DNS server cannot be accessed‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‏‎‏‎‏‏‏‎‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‏‏‎‎‎‏‏‏‎‏‎‏‏‏‎‏‎‎‏‎‏‎‏‎‎‎‎‏‎‎‏‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ has limited connectivity‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‎‏‏‏‎‏‏‎‏‏‎‎‏‏‏‏‏‏‎‎‏‏‎‏‏‏‎‏‎‏‎‎‎‎‎‎‎‎‏‎‏‎‎‏‎‏‎‏‎‏‎‏‎‎Tap to connect anyway‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‎‏‎‎‎‎‎‎‏‎‏‏‎‎‏‎‏‎‎‏‎‎‏‎‏‎‏‏‎‎‎‏‎‎‎‏‏‎‎‏‏‏‎‏‏‏‎‎‏‏‎‎‎‎‎Switched to ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‏‏‎‎‏‏‏‎‏‎‏‎‏‎‏‏‎‏‏‏‎‎‏‏‎‏‏‏‎‎‏‏‎‏‎‎‎‏‎‎‎‏‏‏‎‎‏‎‏‎‎‎‏‎‏‎Device uses ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ when ‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎ has no internet access. Charges may apply.‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‏‏‎‎‏‎‏‎‏‏‏‏‎‎‎‎‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‎‎‏‎‎‏‎‏‏‎‎‎‎‏‎‎‎‏‎Switched from ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ to ‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" - - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‏‏‎‎‎‎‏‎‎‎‏‏‎‎‏‎‎‎‎‎‏‏‎‏‏‏‏‎‎‎‎‏‎‎‏‏‏‎‏‎‏‏‏‎‏‏‎‎‏‎‏‎‏‏‎mobile data‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‎‎‎‏‎‎‏‎‏‎‎‎‎‎‎‏‏‏‎‎‏‎‎‎‎‎‎‎‎‎‎‎‎‎‏‎‏‎‎‏‎‎‏‎‎‎‎‏‎‏‎‎‏‎Wi-Fi‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‎‎‎‏‎‎‏‏‏‎‎‏‏‏‏‎‎‎‏‏‎‎‎‎‏‎‏‏‎‎‎‎‎‎‎‏‏‏‎‏‎‏‎‎‏‏‏‏‎‎‏‎‎‎‎Bluetooth‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‎‎‎‏‏‎‏‏‏‏‎‎‎‎‏‏‎‏‏‎‎‏‎‎‏‏‎‏‏‏‏‎‏‎‏‎‎‏‎‎‏‎‎‎‎‎‎‎‏‏‏‎‎‏‏‏‎Ethernet‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‏‏‎‏‏‎‏‎‏‏‎‏‏‎‎‏‎‎‎‏‎‎‏‏‎‏‏‏‎‎‏‏‎‏‎VPN‎‏‎‎‏‎" - - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‏‏‎‎‏‎‏‏‎‏‎‏‏‏‏‎‏‎‏‏‎‎‏‏‏‎‏‎‏‎‏‎‎‏‎‏‏‎‎‏‎‏‎‏‏‎‏‏‏‏‎‎‎an unknown network type‎‏‎‎‏‎" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-es-rUS/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-es-rUS/strings.xml deleted file mode 100644 index e5f1833fdd6b5..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-es-rUS/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Recursos de conectividad del sistema" - "Accede a una red Wi-Fi." - "Acceder a la red" - - - "%1$sno tiene acceso a Internet" - "Presiona para ver opciones" - "La red móvil no tiene acceso a Internet" - "La red no tiene acceso a Internet" - "No se puede acceder al servidor DNS privado" - "%1$s tiene conectividad limitada" - "Presiona para conectarte de todas formas" - "Se cambió a %1$s" - "El dispositivo usa %1$s cuando %2$s no tiene acceso a Internet. Es posible que se apliquen cargos." - "Se cambió de %1$s a %2$s" - - "Datos móviles" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "un tipo de red desconocido" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-es/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-es/strings.xml deleted file mode 100644 index e4f4307f33820..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-es/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Recursos de conectividad del sistema" - "Iniciar sesión en red Wi-Fi" - "Iniciar sesión en la red" - - - "%1$s no tiene acceso a Internet" - "Toca para ver opciones" - "La red móvil no tiene acceso a Internet" - "La red no tiene acceso a Internet" - "No se ha podido acceder al servidor DNS privado" - "%1$s tiene una conectividad limitada" - "Toca para conectarte de todas formas" - "Se ha cambiado a %1$s" - "El dispositivo utiliza %1$s cuando %2$s no tiene acceso a Internet. Es posible que se apliquen cargos." - "Se ha cambiado de %1$s a %2$s" - - "datos móviles" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "un tipo de red desconocido" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-et/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-et/strings.xml deleted file mode 100644 index cec408fd94836..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-et/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Süsteemi ühenduvuse allikad" - "Logi sisse WiFi-võrku" - "Võrku sisselogimine" - - - "Võrgul %1$s puudub Interneti-ühendus" - "Puudutage valikute nägemiseks" - "Mobiilsidevõrgul puudub Interneti-ühendus" - "Võrgul puudub Interneti-ühendus" - "Privaatsele DNS-serverile ei pääse juurde" - "Võrgu %1$s ühendus on piiratud" - "Puudutage, kui soovite siiski ühenduse luua" - "Lülitati võrgule %1$s" - "Seade kasutab võrku %1$s, kui võrgul %2$s puudub juurdepääs Internetile. Rakenduda võivad tasud." - "Lülitati võrgult %1$s võrgule %2$s" - - "mobiilne andmeside" - "WiFi" - "Bluetooth" - "Ethernet" - "VPN" - - "tundmatu võrgutüüp" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-eu/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-eu/strings.xml deleted file mode 100644 index f3ee9b1287c25..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-eu/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Sistemaren konexio-baliabideak" - "Hasi saioa Wi-Fi sarean" - "Hasi saioa sarean" - - - "Ezin da konektatu Internetera %1$s sarearen bidez" - "Sakatu aukerak ikusteko" - "Sare mugikorra ezin da konektatu Internetera" - "Sarea ezin da konektatu Internetera" - "Ezin da atzitu DNS zerbitzari pribatua" - "%1$s sareak konektagarritasun murriztua du" - "Sakatu hala ere konektatzeko" - "%1$s erabiltzen ari zara orain" - "%2$s Internetera konektatzeko gauza ez denean, %1$s erabiltzen du gailuak. Agian kostuak ordaindu beharko dituzu." - "%1$s erabiltzen ari zinen, baina %2$s erabiltzen ari zara orain" - - "datu-konexioa" - "Wifia" - "Bluetooth-a" - "Ethernet-a" - "VPNa" - - "sare mota ezezaguna" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-fa/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-fa/strings.xml deleted file mode 100644 index 0c5b147e5afef..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-fa/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "منابع اتصال سیستم" - "‏ورود به شبکه Wi-Fi" - "ورود به سیستم شبکه" - - - "%1$s به اینترنت دسترسی ندارد" - "برای گزینه‌ها ضربه بزنید" - "شبکه تلفن همراه به اینترنت دسترسی ندارد" - "شبکه به اینترنت دسترسی ندارد" - "‏سرور DNS خصوصی قابل دسترسی نیست" - "%1$s اتصال محدودی دارد" - "به‌هرصورت، برای اتصال ضربه بزنید" - "به %1$s تغییر کرد" - "وقتی %2$s به اینترنت دسترسی نداشته باشد، دستگاه از %1$s استفاده می‌کند. ممکن است هزینه‌هایی اعمال شود." - "از %1$s به %2$s تغییر کرد" - - "داده تلفن همراه" - "Wi-Fi" - "بلوتوث" - "اترنت" - "VPN" - - "نوع شبکه نامشخص" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-fi/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-fi/strings.xml deleted file mode 100644 index 84c0034f8b2e5..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-fi/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Järjestelmän yhteysresurssit" - "Kirjaudu Wi-Fi-verkkoon" - "Kirjaudu verkkoon" - - - "%1$s ei ole yhteydessä internetiin" - "Näytä vaihtoehdot napauttamalla." - "Mobiiliverkko ei ole yhteydessä internetiin" - "Verkko ei ole yhteydessä internetiin" - "Ei pääsyä yksityiselle DNS-palvelimelle" - "%1$s toimii rajoitetulla yhteydellä" - "Yhdistä napauttamalla" - "%1$s otettiin käyttöön" - "%1$s otetaan käyttöön, kun %2$s ei voi muodostaa yhteyttä internetiin. Veloitukset ovat mahdollisia." - "%1$s poistettiin käytöstä ja %2$s otettiin käyttöön." - - "mobiilidata" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "tuntematon verkon tyyppi" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-fr-rCA/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-fr-rCA/strings.xml deleted file mode 100644 index 0badf1be0f9b1..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-fr-rCA/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Ressources de connectivité système" - "Connectez-vous au réseau Wi-Fi" - "Connectez-vous au réseau" - - - "Le réseau %1$s n\'offre aucun accès à Internet" - "Touchez pour afficher les options" - "Le réseau cellulaire n\'offre aucun accès à Internet" - "Le réseau n\'offre aucun accès à Internet" - "Impossible d\'accéder au serveur DNS privé" - "Le réseau %1$s offre une connectivité limitée" - "Touchez pour vous connecter quand même" - "Passé au réseau %1$s" - "L\'appareil utilise %1$s quand %2$s n\'a pas d\'accès à Internet. Des frais peuvent s\'appliquer." - "Passé du réseau %1$s au %2$s" - - "données cellulaires" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "RPV" - - "un type de réseau inconnu" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-fr/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-fr/strings.xml deleted file mode 100644 index b4835258d9e32..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-fr/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Ressources de connectivité système" - "Connectez-vous au réseau Wi-Fi" - "Se connecter au réseau" - - - "Aucune connexion à Internet pour %1$s" - "Appuyez ici pour afficher des options." - "Le réseau mobile ne dispose d\'aucun accès à Internet" - "Le réseau ne dispose d\'aucun accès à Internet" - "Impossible d\'accéder au serveur DNS privé" - "La connectivité de %1$s est limitée" - "Appuyer pour se connecter quand même" - "Nouveau réseau : %1$s" - "L\'appareil utilise %1$s lorsque %2$s n\'a pas de connexion Internet. Des frais peuvent s\'appliquer." - "Ancien réseau : %1$s. Nouveau réseau : %2$s" - - "données mobiles" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "type de réseau inconnu" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-gl/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-gl/strings.xml deleted file mode 100644 index dfe813746e81b..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-gl/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Recursos de conectividade do sistema" - "Inicia sesión na rede wifi" - "Inicia sesión na rede" - - - "%1$s non ten acceso a Internet" - "Toca para ver opcións." - "A rede de telefonía móbil non ten acceso a Internet" - "A rede non ten acceso a Internet" - "Non se puido acceder ao servidor DNS privado" - "A conectividade de %1$s é limitada" - "Toca para conectarte de todas formas" - "Cambiouse a: %1$s" - "O dispositivo utiliza %1$s cando %2$s non ten acceso a Internet. Pódense aplicar cargos." - "Cambiouse de %1$s a %2$s" - - "datos móbiles" - "wifi" - "Bluetooth" - "Ethernet" - "VPN" - - "un tipo de rede descoñecido" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-gu/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-gu/strings.xml deleted file mode 100644 index e49b11d21ecf5..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-gu/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "સિસ્ટમની કનેક્ટિવિટીનાં સાધનો" - "વાઇ-ફાઇ નેટવર્ક પર સાઇન ઇન કરો" - "નેટવર્ક પર સાઇન ઇન કરો" - - - "%1$s ઇન્ટરનેટ ઍક્સેસ ધરાવતું નથી" - "વિકલ્પો માટે ટૅપ કરો" - "મોબાઇલ નેટવર્ક કોઈ ઇન્ટરનેટ ઍક્સેસ ધરાવતું નથી" - "નેટવર્ક કોઈ ઇન્ટરનેટ ઍક્સેસ ધરાવતું નથી" - "ખાનગી DNS સર્વર ઍક્સેસ કરી શકાતા નથી" - "%1$s મર્યાદિત કનેક્ટિવિટી ધરાવે છે" - "છતાં કનેક્ટ કરવા માટે ટૅપ કરો" - "%1$s પર સ્વિચ કર્યું" - "જ્યારે %2$s પાસે કોઈ ઇન્ટરનેટ ઍક્સેસ ન હોય ત્યારે ઉપકરણ %1$sનો ઉપયોગ કરે છે. શુલ્ક લાગુ થઈ શકે છે." - "%1$s પરથી %2$s પર સ્વિચ કર્યું" - - "મોબાઇલ ડેટા" - "વાઇ-ફાઇ" - "બ્લૂટૂથ" - "ઇથરનેટ" - "VPN" - - "કોઈ અજાણ્યો નેટવર્કનો પ્રકાર" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-hi/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-hi/strings.xml deleted file mode 100644 index 80ed699768e8b..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-hi/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "सिस्टम कनेक्टिविटी के संसाधन" - "वाई-फ़ाई नेटवर्क में साइन इन करें" - "नेटवर्क में साइन इन करें" - - - "%1$s का इंटरनेट नहीं चल रहा है" - "विकल्पों के लिए टैप करें" - "मोबाइल नेटवर्क पर इंटरनेट ऐक्सेस नहीं है" - "इस नेटवर्क पर इंटरनेट ऐक्सेस नहीं है" - "निजी डीएनएस सर्वर को ऐक्सेस नहीं किया जा सकता" - "%1$s की कनेक्टिविटी सीमित है" - "फिर भी कनेक्ट करने के लिए टैप करें" - "%1$s पर ले जाया गया" - "%2$s में इंटरनेट की सुविधा नहीं होने पर डिवाइस %1$s का इस्तेमाल करता है. इसके लिए शुल्क लिया जा सकता है." - "%1$s से %2$s पर ले जाया गया" - - "मोबाइल डेटा" - "वाई-फ़ाई" - "ब्लूटूथ" - "ईथरनेट" - "वीपीएन" - - "अज्ञात नेटवर्क टाइप" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-hr/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-hr/strings.xml deleted file mode 100644 index 24bb22fd69210..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-hr/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Resursi za povezivost sustava" - "Prijava na Wi-Fi mrežu" - "Prijava na mrežu" - - - "%1$s nema pristup internetu" - "Dodirnite za opcije" - "Mobilna mreža nema pristup internetu" - "Mreža nema pristup internetu" - "Nije moguće pristupiti privatnom DNS poslužitelju" - "%1$s ima ograničenu povezivost" - "Dodirnite da biste se ipak povezali" - "Prelazak na drugu mrežu: %1$s" - "Kada %2$s nema pristup internetu, na uređaju se upotrebljava %1$s. Moguća je naplata naknade." - "Mreža je promijenjena: %1$s > %2$s" - - "mobilni podaci" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "nepoznata vrsta mreže" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-hu/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-hu/strings.xml deleted file mode 100644 index 47a1142ac32fe..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-hu/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Rendszerkapcsolat erőforrásai" - "Bejelentkezés Wi-Fi hálózatba" - "Bejelentkezés a hálózatba" - - - "A(z) %1$s hálózaton nincs internet-hozzáférés" - "Koppintson a beállítások megjelenítéséhez" - "A mobilhálózaton nincs internet-hozzáférés" - "A hálózaton nincs internet-hozzáférés" - "A privát DNS-kiszolgálóhoz nem lehet hozzáférni" - "A(z) %1$s hálózat korlátozott kapcsolatot biztosít" - "Koppintson, ha mindenképpen csatlakozni szeretne" - "Átváltva erre: %1$s" - "%1$s használata, ha nincs internet-hozzáférés %2$s-kapcsolaton keresztül. A szolgáltató díjat számíthat fel." - "Átváltva %1$s-hálózatról erre: %2$s" - - "mobiladatok" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "ismeretlen hálózati típus" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-hy/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-hy/strings.xml deleted file mode 100644 index dd951e8182740..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-hy/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "System Connectivity Resources" - "Մուտք գործեք Wi-Fi ցանց" - "Մուտք գործեք ցանց" - - - "%1$s ցանցը չունի մուտք ինտերնետին" - "Հպեք՝ ընտրանքները տեսնելու համար" - "Բջջային ցանցը չի ապահովում ինտերնետ կապ" - "Ցանցը միացված չէ ինտերնետին" - "Մասնավոր DNS սերվերն անհասանելի է" - "%1$s ցանցի կապը սահմանափակ է" - "Հպեք՝ միանալու համար" - "Անցել է %1$s ցանցի" - "Երբ %2$s ցանցում ինտերնետ կապ չի լինում, սարքն անցնում է %1$s ցանցի: Նման դեպքում կարող են վճարներ գանձվել:" - "%1$s ցանցից անցել է %2$s ցանցի" - - "բջջային ինտերնետ" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "ցանցի անհայտ տեսակ" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-in/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-in/strings.xml deleted file mode 100644 index d559f6b11e896..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-in/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Resource Konektivitas Sistem" - "Login ke jaringan Wi-Fi" - "Login ke jaringan" - - - "%1$s tidak memiliki akses internet" - "Ketuk untuk melihat opsi" - "Jaringan seluler tidak memiliki akses internet" - "Jaringan tidak memiliki akses internet" - "Server DNS pribadi tidak dapat diakses" - "%1$s memiliki konektivitas terbatas" - "Ketuk untuk tetap menyambungkan" - "Dialihkan ke %1$s" - "Perangkat menggunakan %1$s jika %2$s tidak memiliki akses internet. Tarif mungkin berlaku." - "Dialihkan dari %1$s ke %2$s" - - "data seluler" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "jenis jaringan yang tidak dikenal" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-is/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-is/strings.xml deleted file mode 100644 index 877c85f147928..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-is/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Tengigögn kerfis" - "Skrá inn á Wi-Fi net" - "Skrá inn á net" - - - "%1$s er ekki með internetaðgang" - "Ýttu til að sjá valkosti" - "Farsímakerfið er ekki tengt við internetið" - "Netkerfið er ekki tengt við internetið" - "Ekki næst í DNS-einkaþjón" - "Tengigeta %1$s er takmörkuð" - "Ýttu til að tengjast samt" - "Skipt yfir á %1$s" - "Tækið notar %1$s þegar %2$s er ekki með internetaðgang. Gjöld kunna að eiga við." - "Skipt úr %1$s yfir í %2$s" - - "farsímagögn" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "óþekkt tegund netkerfis" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-it/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-it/strings.xml deleted file mode 100644 index bcac393c9c57d..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-it/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Risorse per connettività di sistema" - "Accedi a rete Wi-Fi" - "Accedi alla rete" - - - "%1$s non ha accesso a Internet" - "Tocca per le opzioni" - "La rete mobile non ha accesso a Internet" - "La rete non ha accesso a Internet" - "Non è possibile accedere al server DNS privato" - "%1$s ha una connettività limitata" - "Tocca per connettere comunque" - "Passato a %1$s" - "Il dispositivo utilizza %1$s quando %2$s non ha accesso a Internet. Potrebbero essere applicati costi." - "Passato da %1$s a %2$s" - - "dati mobili" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "tipo di rete sconosciuto" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-iw/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-iw/strings.xml deleted file mode 100644 index d6684ce1062e6..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-iw/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "משאבי קישוריות מערכת" - "‏היכנס לרשת Wi-Fi" - "היכנס לרשת" - - - "ל-%1$s אין גישה לאינטרנט" - "הקש לקבלת אפשרויות" - "לרשת הסלולרית אין גישה לאינטרנט" - "לרשת אין גישה לאינטרנט" - "‏לא ניתן לגשת לשרת DNS הפרטי" - "הקישוריות של %1$s מוגבלת" - "כדי להתחבר למרות זאת יש להקיש" - "מעבר אל %1$s" - "המכשיר משתמש ברשת %1$s כשלרשת %2$s אין גישה לאינטרנט. עשויים לחול חיובים." - "עבר מרשת %1$s לרשת %2$s" - - "חבילת גלישה" - "Wi-Fi" - "Bluetooth" - "אתרנט" - "VPN" - - "סוג רשת לא מזוהה" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ja/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ja/strings.xml deleted file mode 100644 index fa4a30aedb225..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ja/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "システム接続リソース" - "Wi-Fiネットワークにログイン" - "ネットワークにログインしてください" - - - "%1$s はインターネットにアクセスできません" - "タップしてその他のオプションを表示" - "モバイル ネットワークがインターネットに接続されていません" - "ネットワークがインターネットに接続されていません" - "プライベート DNS サーバーにアクセスできません" - "%1$s の接続が制限されています" - "接続するにはタップしてください" - "「%1$s」に切り替えました" - "デバイスで「%2$s」によるインターネット接続ができない場合に「%1$s」を使用します。通信料が発生することがあります。" - "「%1$s」から「%2$s」に切り替えました" - - "モバイルデータ" - "Wi-Fi" - "Bluetooth" - "イーサネット" - "VPN" - - "不明なネットワーク タイプ" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ka/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ka/strings.xml deleted file mode 100644 index 418331036efcb..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ka/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "სისტემის კავშირის რესურსები" - "Wi-Fi ქსელთან დაკავშირება" - "ქსელში შესვლა" - - - "%1$s-ს არ აქვს ინტერნეტზე წვდომა" - "შეეხეთ ვარიანტების სანახავად" - "მობილურ ქსელს არ აქვს ინტერნეტზე წვდომა" - "ქსელს არ აქვს ინტერნეტზე წვდომა" - "პირად DNS სერვერზე წვდომა შეუძლებელია" - "%1$s-ის კავშირები შეზღუდულია" - "შეეხეთ, თუ მაინც გსურთ დაკავშირება" - "ახლა გამოიყენება %1$s" - "თუ %2$s ინტერნეტთან კავშირს დაკარგავს, მოწყობილობის მიერ %1$s იქნება გამოყენებული, რამაც შეიძლება დამატებითი ხარჯები გამოიწვიოს." - "ახლა გამოიყენება %1$s (გამოიყენებოდა %2$s)" - - "მობილური ინტერნეტი" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "უცნობი ტიპის ქსელი" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-kk/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-kk/strings.xml deleted file mode 100644 index 54d5eb30cd1d9..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-kk/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Жүйе байланысы ресурстары" - "Wi-Fi желісіне кіру" - "Желіге кіру" - - - "%1$s желісінің интернетті пайдалану мүмкіндігі шектеулі." - "Опциялар үшін түртіңіз" - "Мобильдік желі интернетке қосылмаған." - "Желі интернетке қосылмаған." - "Жеке DNS серверіне кіру мүмкін емес." - "%1$s желісінің қосылу мүмкіндігі шектеулі." - "Бәрібір жалғау үшін түртіңіз." - "%1$s желісіне ауысты" - "Құрылғы %2$s желісінде интернетпен байланыс жоғалған жағдайда %1$s желісін пайдаланады. Деректер ақысы алынуы мүмкін." - "%1$s желісінен %2$s желісіне ауысты" - - "мобильдік деректер" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "желі түрі белгісіз" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-km/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-km/strings.xml deleted file mode 100644 index bd778a1623b05..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-km/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "ធនធាន​តភ្ជាប់​ប្រព័ន្ធ" - "ចូល​បណ្ដាញ​វ៉ាយហ្វាយ" - "ចូលទៅបណ្តាញ" - - - "%1$s មិនមាន​ការតភ្ជាប់អ៊ីនធឺណិត​ទេ" - "ប៉ះសម្រាប់ជម្រើស" - "បណ្ដាញ​ទូរសព្ទ​ចល័ត​មិនមានការតភ្ជាប់​អ៊ីនធឺណិតទេ" - "បណ្ដាញ​មិនមាន​ការតភ្ជាប់​អ៊ីនធឺណិតទេ" - "មិនអាច​ចូលប្រើ​ម៉ាស៊ីនមេ DNS ឯកជន​បានទេ" - "%1$s មានការតភ្ជាប់​មានកម្រិត" - "មិន​អី​ទេ ចុច​​ភ្ជាប់​ចុះ" - "បានប្តូរទៅ %1$s" - "ឧបករណ៍​ប្រើ %1$s នៅ​ពេល​ដែល %2$s មិនមាន​ការ​តភ្ជាប់​អ៊ីនធឺណិត។ អាច​គិតថ្លៃ​លើការ​ប្រើប្រាស់​ទិន្នន័យ។" - "បានប្តូរពី %1$s ទៅ %2$s" - - "ទិន្នន័យ​ទូរសព្ទចល័ត" - "Wi-Fi" - "ប៊្លូធូស" - "អ៊ីសឺរណិត" - "VPN" - - "ប្រភេទបណ្តាញដែលមិនស្គាល់" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-kn/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-kn/strings.xml deleted file mode 100644 index 7f3a420dac786..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-kn/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "ಸಿಸ್ಟಂ ಸಂಪರ್ಕ ಕಲ್ಪಿಸುವಿಕೆ ಮಾಹಿತಿಯ ಮೂಲಗಳು" - "ವೈ-ಫೈ ನೆಟ್‍ವರ್ಕ್‌ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ" - "ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ" - - - "%1$s ಯಾವುದೇ ಇಂಟರ್ನೆಟ್ ಸಂಪರ್ಕವನ್ನು ಹೊಂದಿಲ್ಲ" - "ಆಯ್ಕೆಗಳಿಗೆ ಟ್ಯಾಪ್ ಮಾಡಿ" - "ಮೊಬೈಲ್ ನೆಟ್‌ವರ್ಕ್‌ ಯಾವುದೇ ಇಂಟರ್ನೆಟ್ ಪ್ರವೇಶವನ್ನು ಹೊಂದಿಲ್ಲ" - "ನೆಟ್‌ವರ್ಕ್‌ ಇಂಟರ್ನೆಟ್‌ ಪ್ರವೇಶವನ್ನು ಹೊಂದಿಲ್ಲ" - "ಖಾಸಗಿ DNS ಸರ್ವರ್ ಅನ್ನು ಪ್ರವೇಶಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ" - "%1$s ಸೀಮಿತ ಸಂಪರ್ಕ ಕಲ್ಪಿಸುವಿಕೆಯನ್ನು ಹೊಂದಿದೆ" - "ಹೇಗಾದರೂ ಸಂಪರ್ಕಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ" - "%1$s ಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ" - "%2$s ಇಂಟರ್ನೆಟ್ ಪ್ರವೇಶ ಹೊಂದಿಲ್ಲದಿರುವಾಗ, ಸಾಧನವು %1$s ಬಳಸುತ್ತದೆ. ಶುಲ್ಕಗಳು ಅನ್ವಯವಾಗಬಹುದು." - "%1$s ರಿಂದ %2$s ಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ" - - "ಮೊಬೈಲ್ ಡೇಟಾ" - "ವೈ-ಫೈ" - "ಬ್ಲೂಟೂತ್" - "ಇಥರ್ನೆಟ್" - "VPN" - - "ಅಪರಿಚಿತ ನೆಟ್‌ವರ್ಕ್ ಪ್ರಕಾರ" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ko/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ko/strings.xml deleted file mode 100644 index a763cc5e9cb2e..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ko/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "시스템 연결 리소스" - "Wi-Fi 네트워크에 로그인" - "네트워크에 로그인" - - - "%1$s이(가) 인터넷에 액세스할 수 없습니다." - "탭하여 옵션 보기" - "모바일 네트워크에 인터넷이 연결되어 있지 않습니다." - "네트워크에 인터넷이 연결되어 있지 않습니다." - "비공개 DNS 서버에 액세스할 수 없습니다." - "%1$s에서 연결을 제한했습니다." - "계속 연결하려면 탭하세요." - "%1$s(으)로 전환" - "%2$s(으)로 인터넷에 연결할 수 없는 경우 기기에서 %1$s이(가) 사용됩니다. 요금이 부과될 수 있습니다." - "%1$s에서 %2$s(으)로 전환" - - "모바일 데이터" - "Wi-Fi" - "블루투스" - "이더넷" - "VPN" - - "알 수 없는 네트워크 유형" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ky/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ky/strings.xml deleted file mode 100644 index 3550af80cdf9a..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ky/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Тутумдун байланыш булагы" - "Wi-Fi түйүнүнө кирүү" - "Тармакка кирүү" - - - "%1$s Интернетке туташуусу жок" - "Параметрлерди ачуу үчүн таптап коюңуз" - "Мобилдик Интернет жок" - "Тармактын Интернет жок" - "Жеке DNS сервери жеткиликсиз" - "%1$s байланышы чектелген" - "Баары бир туташуу үчүн таптаңыз" - "%1$s тармагына которуштурулду" - "%2$s тармагы Интернетке туташпай турганда, түзмөгүңүз %1$s тармагын колдонот. Акы алынышы мүмкүн." - "%1$s дегенден %2$s тармагына которуштурулду" - - "мобилдик трафик" - "Wi‑Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "белгисиз тармак түрү" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-lo/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-lo/strings.xml deleted file mode 100644 index 4b3056f540489..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-lo/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "ແຫຼ່ງຂໍ້ມູນການເຊື່ອມຕໍ່ລະບົບ" - "ເຂົ້າສູ່ລະບົບເຄືອຂ່າຍ Wi-Fi" - "ລົງຊື່ເຂົ້າເຄືອຂ່າຍ" - - - "%1$s ບໍ່ມີການເຊື່ອມຕໍ່ອິນເຕີເນັດ" - "ແຕະເພື່ອເບິ່ງຕົວເລືອກ" - "ເຄືອຂ່າຍມືຖືບໍ່ສາມາດເຂົ້າເຖິງອິນເຕີເນັດໄດ້" - "ເຄືອຂ່າຍບໍ່ສາມາດເຂົ້າເຖິງອິນເຕີເນັດໄດ້" - "ບໍ່ສາມາດເຂົ້າເຖິງເຊີບເວີ DNS ສ່ວນຕົວໄດ້" - "%1$s ມີການເຊື່ອມຕໍ່ທີ່ຈຳກັດ" - "ແຕະເພື່ອຢືນຢັນການເຊື່ອມຕໍ່" - "ສະຫຼັບໄປໃຊ້ %1$s ແລ້ວ" - "ອຸປະກອນຈະໃຊ້ %1$s ເມື່ອ %2$s ບໍ່ມີການເຊື່ອມຕໍ່ອິນເຕີເນັດ. ອາດມີການຮຽກເກັບຄ່າບໍລິການ." - "ສະຫຼັບຈາກ %1$s ໄປໃຊ້ %2$s ແລ້ວ" - - "ອິນເຕີເນັດມືຖື" - "Wi-Fi" - "Bluetooth" - "ອີເທີເນັດ" - "VPN" - - "ບໍ່ຮູ້ຈັກປະເພດເຄືອຂ່າຍ" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-lt/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-lt/strings.xml deleted file mode 100644 index 8eb41f1efa279..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-lt/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "System Connectivity Resources" - "Prisijungti prie „Wi-Fi“ tinklo" - "Prisijungti prie tinklo" - - - "„%1$s“ negali pasiekti interneto" - "Palieskite, kad būtų rodomos parinktys." - "Mobiliojo ryšio tinkle nėra prieigos prie interneto" - "Tinkle nėra prieigos prie interneto" - "Privataus DNS serverio negalima pasiekti" - "„%1$s“ ryšys apribotas" - "Palieskite, jei vis tiek norite prisijungti" - "Perjungta į tinklą %1$s" - "Įrenginyje naudojamas kitas tinklas (%1$s), kai dabartiniame tinkle (%2$s) nėra interneto ryšio. Gali būti taikomi mokesčiai." - "Perjungta iš tinklo %1$s į tinklą %2$s" - - "mobiliojo ryšio duomenys" - "Wi-Fi" - "Bluetooth" - "Eternetas" - "VPN" - - "nežinomas tinklo tipas" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-lv/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-lv/strings.xml deleted file mode 100644 index 0647a4fb077e0..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-lv/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Sistēmas savienojamības resursi" - "Pierakstieties Wi-Fi tīklā" - "Pierakstīšanās tīklā" - - - "Tīklā %1$s nav piekļuves internetam" - "Pieskarieties, lai skatītu iespējas." - "Mobilajā tīklā nav piekļuves internetam." - "Tīklā nav piekļuves internetam." - "Nevar piekļūt privātam DNS serverim." - "Tīklā %1$s ir ierobežota savienojamība" - "Lai tik un tā izveidotu savienojumu, pieskarieties" - "Pārslēdzās uz tīklu %1$s" - "Kad vienā tīklā (%2$s) nav piekļuves internetam, ierīcē tiek izmantots cits tīkls (%1$s). Var tikt piemērota maksa." - "Pārslēdzās no tīkla %1$s uz tīklu %2$s" - - "mobilie dati" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "nezināms tīkla veids" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-mcc204-mnc04/config.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-mcc204-mnc04/config.xml deleted file mode 100644 index 7e7025fb042f7..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-mcc204-mnc04/config.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - 0 - \ No newline at end of file diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-mcc310-mnc004/config.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-mcc310-mnc004/config.xml deleted file mode 100644 index 7e7025fb042f7..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-mcc310-mnc004/config.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - 0 - \ No newline at end of file diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-mcc311-mnc480/config.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-mcc311-mnc480/config.xml deleted file mode 100644 index 7e7025fb042f7..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-mcc311-mnc480/config.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - 0 - \ No newline at end of file diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-mk/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-mk/strings.xml deleted file mode 100644 index b0024e296cb37..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-mk/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "System Connectivity Resources" - "Најавете се на мрежа на Wi-Fi" - "Најавете се на мрежа" - - - "%1$s нема интернет-пристап" - "Допрете за опции" - "Мобилната мрежа нема интернет-пристап" - "Мрежата нема интернет-пристап" - "Не може да се пристапи до приватниот DNS-сервер" - "%1$s има ограничена поврзливост" - "Допрете за да се поврзете и покрај тоа" - "Префрлено на %1$s" - "Уредот користи %1$s кога %2$s нема пристап до интернет. Може да се наплатат трошоци." - "Префрлено од %1$s на %2$s" - - "мобилен интернет" - "Wi-Fi" - "Bluetooth" - "Етернет" - "VPN" - - "непознат тип мрежа" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ml/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ml/strings.xml deleted file mode 100644 index 8ce7667fbf963..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ml/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "സിസ്‌റ്റം കണക്‌റ്റിവിറ്റി ഉറവിടങ്ങൾ" - "വൈഫൈ നെറ്റ്‌വർക്കിലേക്ക് സൈൻ ഇൻ ചെയ്യുക" - "നെറ്റ്‌വർക്കിലേക്ക് സൈൻ ഇൻ ചെയ്യുക" - - - "%1$s എന്നതിന് ഇന്റർനെറ്റ് ആക്‌സസ് ഇല്ല" - "ഓപ്ഷനുകൾക്ക് ടാപ്പുചെയ്യുക" - "മൊബെെൽ നെറ്റ്‌വർക്കിന് ഇന്റർനെറ്റ് ആക്‌സസ് ഇല്ല" - "നെറ്റ്‌വർക്കിന് ഇന്റർനെറ്റ് ആക്‌സസ് ഇല്ല" - "സ്വകാര്യ DNS സെർവർ ആക്‌സസ് ചെയ്യാനാവില്ല" - "%1$s എന്നതിന് പരിമിതമായ കണക്റ്റിവിറ്റി ഉണ്ട്" - "ഏതുവിധേനയും കണക്‌റ്റ് ചെയ്യാൻ ടാപ്പ് ചെയ്യുക" - "%1$s എന്നതിലേക്ക് മാറി" - "%2$s-ന് ഇന്റർനെറ്റ് ആക്‌സസ് ഇല്ലാത്തപ്പോൾ ഉപകരണം %1$s ഉപയോഗിക്കുന്നു. നിരക്കുകൾ ബാധകമായേക്കാം." - "%1$s നെറ്റ്‌വർക്കിൽ നിന്ന് %2$s നെറ്റ്‌വർക്കിലേക്ക് മാറി" - - "മൊബൈൽ ഡാറ്റ" - "വൈഫൈ" - "Bluetooth" - "ഇതർനെറ്റ്" - "VPN" - - "അജ്ഞാതമായ നെറ്റ്‌വർക്ക് തരം" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-mn/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-mn/strings.xml deleted file mode 100644 index be8b59202baaa..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-mn/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Системийн холболтын нөөцүүд" - "Wi-Fi сүлжээнд нэвтэрнэ үү" - "Сүлжээнд нэвтэрнэ үү" - - - "%1$s-д интернэтийн хандалт алга" - "Сонголт хийхийн тулд товшино уу" - "Мобайл сүлжээнд интернэт хандалт байхгүй байна" - "Сүлжээнд интернэт хандалт байхгүй байна" - "Хувийн DNS серверт хандах боломжгүй байна" - "%1$s зарим үйлчилгээнд хандах боломжгүй байна" - "Ямар ч тохиолдолд холбогдохын тулд товших" - "%1$s руу шилжүүлсэн" - "%2$s интернет холболтгүй үед төхөөрөмж %1$s-г ашигладаг. Төлбөр гарч болзошгүй." - "%1$s-с %2$s руу шилжүүлсэн" - - "мобайл дата" - "Wi-Fi" - "Bluetooth" - "Этернэт" - "VPN" - - "үл мэдэгдэх сүлжээний төрөл" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-mr/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-mr/strings.xml deleted file mode 100644 index fe7df841b1474..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-mr/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "सिस्टम कनेक्टिव्हिटी चे स्रोत" - "वाय-फाय नेटवर्कमध्‍ये साइन इन करा" - "नेटवर्कवर साइन इन करा" - - - "%1$s ला इंटरनेट अ‍ॅक्सेस नाही" - "पर्यायांसाठी टॅप करा" - "मोबाइल नेटवर्कला इंटरनेट ॲक्सेस नाही" - "नेटवर्कला इंटरनेट ॲक्सेस नाही" - "खाजगी DNS सर्व्हर ॲक्सेस करू शकत नाही" - "%1$s ला मर्यादित कनेक्टिव्हिटी आहे" - "तरीही कनेक्ट करण्यासाठी टॅप करा" - "%1$s वर स्विच केले" - "%2$s कडे इंटरनेटचा अ‍ॅक्सेस नसताना डिव्हाइस %1$s वापरते. शुल्क लागू शकते." - "%1$s वरून %2$s वर स्विच केले" - - "मोबाइल डेटा" - "वाय-फाय" - "ब्लूटूथ" - "इथरनेट" - "VPN" - - "अज्ञात नेटवर्क प्रकार" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ms/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ms/strings.xml deleted file mode 100644 index 54b49a20f7eb4..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ms/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Sumber Kesambungan Sistem" - "Log masuk ke rangkaian Wi-Fi" - "Log masuk ke rangkaian" - - - "%1$s tiada akses Internet" - "Ketik untuk mendapatkan pilihan" - "Rangkaian mudah alih tiada akses Internet" - "Rangkaian tiada akses Internet" - "Pelayan DNS peribadi tidak boleh diakses" - "%1$s mempunyai kesambungan terhad" - "Ketik untuk menyambung juga" - "Beralih kepada %1$s" - "Peranti menggunakan %1$s apabila %2$s tiada akses Internet. Bayaran mungkin dikenakan." - "Beralih daripada %1$s kepada %2$s" - - "data mudah alih" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "jenis rangkaian tidak diketahui" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-my/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-my/strings.xml deleted file mode 100644 index 15b75f0fc3a15..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-my/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "စနစ်ချိတ်ဆက်နိုင်မှု ရင်းမြစ်များ" - "ဝိုင်ဖိုင်ကွန်ရက်သို့ လက်မှတ်ထိုးဝင်ပါ" - "ကွန်ယက်သို့ လက်မှတ်ထိုးဝင်ရန်" - - - "%1$s တွင် အင်တာနက်အသုံးပြုခွင့် မရှိပါ" - "အခြားရွေးချယ်စရာများကိုကြည့်ရန် တို့ပါ" - "မိုဘိုင်းကွန်ရက်တွင် အင်တာနက်ချိတ်ဆက်မှု မရှိပါ" - "ကွန်ရက်တွင် အင်တာနက်အသုံးပြုခွင့် မရှိပါ" - "သီးသန့် ဒီအန်အက်စ် (DNS) ဆာဗာကို သုံး၍မရပါ။" - "%1$s တွင် ချိတ်ဆက်မှုကို ကန့်သတ်ထားသည်" - "မည်သို့ပင်ဖြစ်စေ ချိတ်ဆက်ရန် တို့ပါ" - "%1$s သို့ ပြောင်းလိုက်ပြီ" - "%2$s ဖြင့် အင်တာနက် အသုံးမပြုနိုင်သည့်အချိန်တွင် စက်ပစ္စည်းသည် %1$s ကို သုံးပါသည်။ ဒေတာသုံးစွဲခ ကျသင့်နိုင်ပါသည်။" - "%1$s မှ %2$s သို့ ပြောင်းလိုက်ပြီ" - - "မိုဘိုင်းဒေတာ" - "Wi-Fi" - "ဘလူးတုသ်" - "အီသာနက်" - "VPN" - - "အမည်မသိကွန်ရက်အမျိုးအစား" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-nb/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-nb/strings.xml deleted file mode 100644 index a561def65c50f..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-nb/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Ressurser for systemtilkobling" - "Logg på Wi-Fi-nettverket" - "Logg på nettverk" - - - "%1$s har ingen internettilkobling" - "Trykk for å få alternativer" - "Mobilnettverket har ingen internettilgang" - "Nettverket har ingen internettilgang" - "Den private DNS-tjeneren kan ikke nås" - "%1$s har begrenset tilkobling" - "Trykk for å koble til likevel" - "Byttet til %1$s" - "Enheten bruker %1$s når %2$s ikke har Internett-tilgang. Avgifter kan påløpe." - "Byttet fra %1$s til %2$s" - - "mobildata" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "en ukjent nettverkstype" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ne/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ne/strings.xml deleted file mode 100644 index f74542d9421f2..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ne/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "सिस्टम कनेक्टिभिटीका स्रोतहरू" - "Wi-Fi नेटवर्कमा साइन इन गर्नुहोस्" - "सञ्जालमा साइन इन गर्नुहोस्" - - - "%1$s को इन्टरनेटमाथि पहुँच छैन" - "विकल्पहरूका लागि ट्याप गर्नुहोस्" - "मोबाइल नेटवर्कको इन्टरनेटमाथि पहुँच छैन" - "नेटवर्कको इन्टरनेटमाथि पहुँच छैन" - "निजी DNS सर्भरमाथि पहुँच प्राप्त गर्न सकिँदैन" - "%1$s को जडान सीमित छ" - "जसरी भए पनि जडान गर्न ट्याप गर्नुहोस्" - "%1$s मा बदल्नुहोस्" - "%2$s मार्फत इन्टरनेटमाथि पहुँच राख्न नसकेको अवस्थामा यन्त्रले %1$s प्रयोग गर्दछ। शुल्क लाग्न सक्छ।" - "%1$s बाट %2$s मा परिवर्तन गरियो" - - "मोबाइल डेटा" - "Wi-Fi" - "ब्लुटुथ" - "इथरनेट" - "VPN" - - "नेटवर्कको कुनै अज्ञात प्रकार" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-nl/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-nl/strings.xml deleted file mode 100644 index 0f3203beb5b9c..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-nl/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Resources voor systeemconnectiviteit" - "Inloggen bij wifi-netwerk" - "Inloggen bij netwerk" - - - "%1$s heeft geen internettoegang" - "Tik voor opties" - "Mobiel netwerk heeft geen internettoegang" - "Netwerk heeft geen internettoegang" - "Geen toegang tot privé-DNS-server" - "%1$s heeft beperkte connectiviteit" - "Tik om toch verbinding te maken" - "Overgeschakeld naar %1$s" - "Apparaat gebruikt %1$s wanneer %2$s geen internetverbinding heeft. Er kunnen kosten in rekening worden gebracht." - "Overgeschakeld van %1$s naar %2$s" - - "mobiele data" - "Wifi" - "Bluetooth" - "Ethernet" - "VPN" - - "een onbekend netwerktype" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-or/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-or/strings.xml deleted file mode 100644 index ecf4d694d07da..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-or/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "ସିଷ୍ଟମର ସଂଯୋଗ ସମ୍ବନ୍ଧିତ ରିସୋର୍ସଗୁଡ଼ିକ" - "ୱାଇ-ଫାଇ ନେଟୱର୍କରେ ସାଇନ୍‍-ଇନ୍‍ କରନ୍ତୁ" - "ନେଟ୍‌ୱର୍କରେ ସାଇନ୍‍ ଇନ୍‍ କରନ୍ତୁ" - - - "%1$sର ଇଣ୍ଟର୍ନେଟ୍ ଆକ୍ସେସ୍ ନାହିଁ" - "ବିକଳ୍ପ ପାଇଁ ଟାପ୍‍ କରନ୍ତୁ" - "ମୋବାଇଲ୍ ନେଟ୍‌ୱାର୍କରେ ଇଣ୍ଟର୍ନେଟ୍ ଆକ୍ସେସ୍ ନାହିଁ" - "ନେଟ୍‌ୱାର୍କରେ ଇଣ୍ଟର୍ନେଟ୍ ଆକ୍ସେସ୍ ନାହିଁ" - "ବ୍ୟକ୍ତିଗତ DNS ସର୍ଭର୍ ଆକ୍ସେସ୍ କରିହେବ ନାହିଁ" - "%1$sର ସୀମିତ ସଂଯୋଗ ଅଛି" - "ତଥାପି ଯୋଗାଯୋଗ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ" - "%1$sକୁ ବଦଳାଗଲା" - "%2$sର ଇଣ୍ଟରନେଟ୍‍ ଆକ୍ସେସ୍ ନଥିବାବେଳେ ଡିଭାଇସ୍‍ %1$s ବ୍ୟବହାର କରିଥାଏ। ଶୁଳ୍କ ଲାଗୁ ହୋଇପାରେ।" - "%1$s ରୁ %2$sକୁ ବଦଳାଗଲା" - - "ମୋବାଇଲ ଡାଟା" - "ୱାଇ-ଫାଇ" - "ବ୍ଲୁଟୁଥ୍" - "ଇଥରନେଟ୍" - "VPN" - - "ଏକ ଅଜଣା ନେଟୱାର୍କ ପ୍ରକାର" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-pa/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-pa/strings.xml deleted file mode 100644 index 43280549e773d..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-pa/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "ਸਿਸਟਮ ਕਨੈਕਟੀਵਿਟੀ ਸਰੋਤ" - "ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ \'ਤੇ ਸਾਈਨ-ਇਨ ਕਰੋ" - "ਨੈੱਟਵਰਕ \'ਤੇ ਸਾਈਨ-ਇਨ ਕਰੋ" - - - "%1$s ਕੋਲ ਇੰਟਰਨੈੱਟ ਪਹੁੰਚ ਨਹੀਂ ਹੈ" - "ਵਿਕਲਪਾਂ ਲਈ ਟੈਪ ਕਰੋ" - "ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ ਕੋਲ ਇੰਟਰਨੈੱਟ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਹੈ" - "ਨੈੱਟਵਰਕ ਕੋਲ ਇੰਟਰਨੈੱਟ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਹੈ" - "ਨਿੱਜੀ ਡੋਮੇਨ ਨਾਮ ਪ੍ਰਣਾਲੀ (DNS) ਸਰਵਰ \'ਤੇ ਪਹੁੰਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕੀ" - "%1$s ਕੋਲ ਸੀਮਤ ਕਨੈਕਟੀਵਿਟੀ ਹੈ" - "ਫਿਰ ਵੀ ਕਨੈਕਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ" - "ਬਦਲਕੇ %1$s ਲਿਆਂਦਾ ਗਿਆ" - "%2$s ਦੀ ਇੰਟਰਨੈੱਟ \'ਤੇ ਪਹੁੰਚ ਨਾ ਹੋਣ \'ਤੇ ਡੀਵਾਈਸ %1$s ਦੀ ਵਰਤੋਂ ਕਰਦਾ ਹੈ। ਖਰਚੇ ਲਾਗੂ ਹੋ ਸਕਦੇ ਹਨ।" - "%1$s ਤੋਂ ਬਦਲਕੇ %2$s \'ਤੇ ਕੀਤਾ ਗਿਆ" - - "ਮੋਬਾਈਲ ਡਾਟਾ" - "ਵਾਈ-ਫਾਈ" - "ਬਲੂਟੁੱਥ" - "ਈਥਰਨੈੱਟ" - "VPN" - - "ਕੋਈ ਅਗਿਆਤ ਨੈੱਟਵਰਕ ਦੀ ਕਿਸਮ" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-pl/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-pl/strings.xml deleted file mode 100644 index e6b3a0cff6ee1..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-pl/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Zasoby systemowe dotyczące łączności" - "Zaloguj się w sieci Wi-Fi" - "Zaloguj się do sieci" - - - "%1$s nie ma dostępu do internetu" - "Kliknij, by wyświetlić opcje" - "Sieć komórkowa nie ma dostępu do internetu" - "Sieć nie ma dostępu do internetu" - "Brak dostępu do prywatnego serwera DNS" - "%1$s ma ograniczoną łączność" - "Kliknij, by mimo to nawiązać połączenie" - "Zmieniono na połączenie typu %1$s" - "Urządzenie korzysta z połączenia typu %1$s, gdy %2$s nie dostępu do internetu. Mogą zostać naliczone opłaty." - "Przełączono z połączenia typu %1$s na %2$s." - - "mobilna transmisja danych" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "nieznany typ sieci" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-pt-rBR/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-pt-rBR/strings.xml deleted file mode 100644 index f1d0bc0b0cd51..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-pt-rBR/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Recursos de conectividade do sistema" - "Fazer login na rede Wi-Fi" - "Fazer login na rede" - - - "%1$s não tem acesso à Internet" - "Toque para ver opções" - "A rede móvel não tem acesso à Internet" - "A rede não tem acesso à Internet" - "Não é possível acessar o servidor DNS privado" - "%1$s tem conectividade limitada" - "Toque para conectar mesmo assim" - "Alternado para %1$s" - "O dispositivo usa %1$s quando %2$s não tem acesso à Internet. Esse serviço pode ser cobrado." - "Alternado de %1$s para %2$s" - - "dados móveis" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "um tipo de rede desconhecido" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-pt-rPT/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-pt-rPT/strings.xml deleted file mode 100644 index 163d70b081899..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-pt-rPT/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Recursos de conetividade do sistema" - "Iniciar sessão na rede Wi-Fi" - "Início de sessão na rede" - - - "%1$s não tem acesso à Internet" - "Toque para obter mais opções" - "A rede móvel não tem acesso à Internet" - "A rede não tem acesso à Internet" - "Não é possível aceder ao servidor DNS." - "%1$s tem conetividade limitada." - "Toque para ligar mesmo assim." - "Mudou para %1$s" - "O dispositivo utiliza %1$s quando %2$s não tem acesso à Internet. Podem aplicar-se custos." - "Mudou de %1$s para %2$s" - - "dados móveis" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "um tipo de rede desconhecido" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-pt/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-pt/strings.xml deleted file mode 100644 index f1d0bc0b0cd51..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-pt/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Recursos de conectividade do sistema" - "Fazer login na rede Wi-Fi" - "Fazer login na rede" - - - "%1$s não tem acesso à Internet" - "Toque para ver opções" - "A rede móvel não tem acesso à Internet" - "A rede não tem acesso à Internet" - "Não é possível acessar o servidor DNS privado" - "%1$s tem conectividade limitada" - "Toque para conectar mesmo assim" - "Alternado para %1$s" - "O dispositivo usa %1$s quando %2$s não tem acesso à Internet. Esse serviço pode ser cobrado." - "Alternado de %1$s para %2$s" - - "dados móveis" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "um tipo de rede desconhecido" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ro/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ro/strings.xml deleted file mode 100644 index 221261c66c068..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ro/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Resurse pentru conectivitatea sistemului" - "Conectați-vă la rețeaua Wi-Fi" - "Conectați-vă la rețea" - - - "%1$s nu are acces la internet" - "Atingeți pentru opțiuni" - "Rețeaua mobilă nu are acces la internet" - "Rețeaua nu are acces la internet" - "Serverul DNS privat nu poate fi accesat" - "%1$s are conectivitate limitată" - "Atingeți pentru a vă conecta oricum" - "S-a comutat la %1$s" - "Dispozitivul folosește %1$s când %2$s nu are acces la internet. Se pot aplica taxe." - "S-a comutat de la %1$s la %2$s" - - "date mobile" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "un tip de rețea necunoscut" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ru/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ru/strings.xml deleted file mode 100644 index ba179b7394e6c..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ru/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "System Connectivity Resources" - "Подключение к Wi-Fi" - "Регистрация в сети" - - - "Сеть \"%1$s\" не подключена к Интернету" - "Нажмите, чтобы показать варианты." - "Мобильная сеть не подключена к Интернету" - "Сеть не подключена к Интернету" - "Доступа к частному DNS-серверу нет." - "Подключение к сети \"%1$s\" ограничено" - "Нажмите, чтобы подключиться" - "Новое подключение: %1$s" - "Устройство использует %1$s, если подключение к сети %2$s недоступно. Может взиматься плата за передачу данных." - "Устройство отключено от сети %2$s и теперь использует %1$s" - - "мобильный интернет" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "неизвестный тип сети" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-si/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-si/strings.xml deleted file mode 100644 index 1c493a78dc7b4..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-si/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "පද්ධති සබැඳුම් හැකියා සම්පත්" - "Wi-Fi ජාලයට පුරනය වන්න" - "ජාලයට පුරනය වන්න" - - - "%1$s හට අන්තර්ජාල ප්‍රවේශය නැත" - "විකල්ප සඳහා තට්ටු කරන්න" - "ජංගම ජාලවලට අන්තර්ජාල ප්‍රවේශය නැත" - "ජාලයට අන්තර්ජාල ප්‍රවේශය නැත" - "පුද්ගලික DNS සේවාදායකයට ප්‍රවේශ වීමට නොහැකිය" - "%1$s හට සීමිත සබැඳුම් හැකියාවක් ඇත" - "කෙසේ වෙතත් ඉදිරියට යාමට තට්ටු කරන්න" - "%1$s වෙත මාරු විය" - "උපාංගය %1$s %2$s සඳහා අන්තර්ජාල ප්‍රවේශය නැති විට භාවිත කරයි. ගාස්තු අදාළ විය හැකිය." - "%1$s සිට %2$s වෙත මාරු විය" - - "ජංගම දත්ත" - "Wi-Fi" - "බ්ලූටූත්" - "ඊතර්නෙට්" - "VPN" - - "නොදන්නා ජාල වර්ගයකි" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-sk/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sk/strings.xml deleted file mode 100644 index 1b9313af170fd..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-sk/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Zdroje možností pripojenia systému" - "Prihlásiť sa do siete Wi‑Fi" - "Prihlásenie do siete" - - - "%1$s nemá prístup k internetu" - "Klepnutím získate možnosti" - "Mobilná sieť nemá prístup k internetu" - "Sieť nemá prístup k internetu" - "K súkromnému serveru DNS sa nepodarilo získať prístup" - "%1$s má obmedzené pripojenie" - "Ak sa chcete aj napriek tomu pripojiť, klepnite" - "Prepnuté na sieť: %1$s" - "Keď %2$s nemá prístup k internetu, zariadenie používa %1$s. Môžu sa účtovať poplatky." - "Prepnuté zo siete %1$s na sieť %2$s" - - "mobilné dáta" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "neznámy typ siete" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-sl/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sl/strings.xml deleted file mode 100644 index 739fb8e49156a..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-sl/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Viri povezljivosti sistema" - "Prijavite se v omrežje Wi-Fi" - "Prijava v omrežje" - - - "Omrežje %1$s nima dostopa do interneta" - "Dotaknite se za možnosti" - "Mobilno omrežje nima dostopa do interneta" - "Omrežje nima dostopa do interneta" - "Do zasebnega strežnika DNS ni mogoče dostopati" - "Povezljivost omrežja %1$s je omejena" - "Dotaknite se, da kljub temu vzpostavite povezavo" - "Preklopljeno na omrežje vrste %1$s" - "Naprava uporabi omrežje vrste %1$s, ko omrežje vrste %2$s nima dostopa do interneta. Prenos podatkov se lahko zaračuna." - "Preklopljeno z omrežja vrste %1$s na omrežje vrste %2$s" - - "prenos podatkov v mobilnem omrežju" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "neznana vrsta omrežja" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-sq/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sq/strings.xml deleted file mode 100644 index cf8cf3b40e738..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-sq/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Burimet e lidhshmërisë së sistemit" - "Identifikohu në rrjetin Wi-Fi" - "Identifikohu në rrjet" - - - "%1$s nuk ka qasje në internet" - "Trokit për opsionet" - "Rrjeti celular nuk ka qasje në internet" - "Rrjeti nuk ka qasje në internet" - "Serveri privat DNS nuk mund të qaset" - "%1$s ka lidhshmëri të kufizuar" - "Trokit për t\'u lidhur gjithsesi" - "Kaloi te %1$s" - "Pajisja përdor %1$s kur %2$s nuk ka qasje në internet. Mund të zbatohen tarifa." - "Kaloi nga %1$s te %2$s" - - "të dhënat celulare" - "Wi-Fi" - "Bluetooth" - "Eternet" - "VPN" - - "një lloj rrjeti i panjohur" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-sr/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sr/strings.xml deleted file mode 100644 index 1f7c95c94d9e1..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-sr/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Ресурси за повезивање са системом" - "Пријављивање на WiFi мрежу" - "Пријавите се на мрежу" - - - "%1$s нема приступ интернету" - "Додирните за опције" - "Мобилна мрежа нема приступ интернету" - "Мрежа нема приступ интернету" - "Приступ приватном DNS серверу није успео" - "%1$s има ограничену везу" - "Додирните да бисте се ипак повезали" - "Прешли сте на тип мреже %1$s" - "Уређај користи тип мреже %1$s када тип мреже %2$s нема приступ интернету. Можда ће се наплаћивати трошкови." - "Прешли сте са типа мреже %1$s на тип мреже %2$s" - - "мобилни подаци" - "WiFi" - "Bluetooth" - "Етернет" - "VPN" - - "непознат тип мреже" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-sv/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sv/strings.xml deleted file mode 100644 index 57e74e95e90f3..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-sv/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Resurser för systemanslutning" - "Logga in på ett wifi-nätverk" - "Logga in på nätverket" - - - "%1$s har ingen internetanslutning" - "Tryck för alternativ" - "Mobilnätverket har ingen internetanslutning" - "Nätverket har ingen internetanslutning" - "Det går inte att komma åt den privata DNS-servern." - "%1$s har begränsad anslutning" - "Tryck för att ansluta ändå" - "Byte av nätverk till %1$s" - "%1$s används på enheten när det inte finns internetåtkomst via %2$s. Avgifter kan tillkomma." - "Byte av nätverk från %1$s till %2$s" - - "mobildata" - "Wifi" - "Bluetooth" - "Ethernet" - "VPN" - - "en okänd nätverkstyp" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-sw/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-sw/strings.xml deleted file mode 100644 index 5c4d59410de80..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-sw/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Nyenzo za Muunganisho wa Mfumo" - "Ingia kwa mtandao wa Wi-Fi" - "Ingia katika mtandao" - - - "%1$s haina uwezo wa kufikia intaneti" - "Gusa ili upate chaguo" - "Mtandao wa simu hauna uwezo wa kufikia intaneti" - "Mtandao hauna uwezo wa kufikia intaneti" - "Seva ya faragha ya DNS haiwezi kufikiwa" - "%1$s ina muunganisho unaofikia huduma chache." - "Gusa ili uunganishe tu" - "Sasa inatumia %1$s" - "Kifaa hutumia %1$s wakati %2$s haina intaneti. Huenda ukalipishwa." - "Imebadilisha mtandao kutoka %1$s na sasa inatumia %2$s" - - "data ya mtandao wa simu" - "Wi-Fi" - "Bluetooth" - "Ethaneti" - "VPN" - - "aina ya mtandao isiyojulikana" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ta/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ta/strings.xml deleted file mode 100644 index 90f89c988e21d..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ta/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "சிஸ்டம் இணைப்பு மூலங்கள்" - "வைஃபை நெட்வொர்க்கில் உள்நுழையவும்" - "நெட்வொர்க்கில் உள்நுழையவும்" - - - "%1$s நெட்வொர்க்கிற்கு இணைய அணுகல் இல்லை" - "விருப்பங்களுக்கு, தட்டவும்" - "மொபைல் நெட்வொர்க்கிற்கு இணைய அணுகல் இல்லை" - "நெட்வொர்க்கிற்கு இணைய அணுகல் இல்லை" - "தனிப்பட்ட DNS சேவையகத்தை அணுக இயலாது" - "%1$s வரம்பிற்கு உட்பட்ட இணைப்புநிலையைக் கொண்டுள்ளது" - "எப்படியேனும் இணைப்பதற்குத் தட்டவும்" - "%1$sக்கு மாற்றப்பட்டது" - "%2$s நெட்வொர்க்கில் இண்டர்நெட் அணுகல் இல்லாததால், சாதனமானது %1$s நெட்வொர்க்கைப் பயன்படுத்துகிறது. கட்டணங்கள் விதிக்கப்படலாம்." - "%1$s இலிருந்து %2$sக்கு மாற்றப்பட்டது" - - "மொபைல் டேட்டா" - "வைஃபை" - "புளூடூத்" - "ஈதர்நெட்" - "VPN" - - "தெரியாத நெட்வொர்க் வகை" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-te/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-te/strings.xml deleted file mode 100644 index c69b599e19008..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-te/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "సిస్టమ్ కనెక్టివిటీ రిసోర్స్‌లు" - "Wi-Fi నెట్‌వర్క్‌కి సైన్ ఇన్ చేయండి" - "నెట్‌వర్క్‌కి సైన్ ఇన్ చేయండి" - - - "%1$sకి ఇంటర్నెట్ యాక్సెస్ లేదు" - "ఎంపికల కోసం నొక్కండి" - "మొబైల్ నెట్‌వర్క్‌కు ఇంటర్నెట్ యాక్సెస్ లేదు" - "నెట్‌వర్క్‌కు ఇంటర్నెట్ యాక్సెస్ లేదు" - "ప్రైవేట్ DNS సర్వర్‌ను యాక్సెస్ చేయడం సాధ్యపడదు" - "%1$s పరిమిత కనెక్టివిటీని కలిగి ఉంది" - "ఏదేమైనా కనెక్ట్ చేయడానికి నొక్కండి" - "%1$sకి మార్చబడింది" - "పరికరం %2$sకి ఇంటర్నెట్ యాక్సెస్ లేనప్పుడు %1$sని ఉపయోగిస్తుంది. ఛార్జీలు వర్తించవచ్చు." - "%1$s నుండి %2$sకి మార్చబడింది" - - "మొబైల్ డేటా" - "Wi-Fi" - "బ్లూటూత్" - "ఈథర్‌నెట్" - "VPN" - - "తెలియని నెట్‌వర్క్ రకం" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-th/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-th/strings.xml deleted file mode 100644 index eee5a3520d673..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-th/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "ทรัพยากรการเชื่อมต่อของระบบ" - "ลงชื่อเข้าใช้เครือข่าย WiFi" - "ลงชื่อเข้าใช้เครือข่าย" - - - "%1$s เข้าถึงอินเทอร์เน็ตไม่ได้" - "แตะเพื่อดูตัวเลือก" - "เครือข่ายมือถือไม่มีการเข้าถึงอินเทอร์เน็ต" - "เครือข่ายไม่มีการเข้าถึงอินเทอร์เน็ต" - "เข้าถึงเซิร์ฟเวอร์ DNS ไม่ได้" - "%1$s มีการเชื่อมต่อจำกัด" - "แตะเพื่อเชื่อมต่อ" - "เปลี่ยนเป็น %1$s" - "อุปกรณ์จะใช้ %1$s เมื่อ %2$s เข้าถึงอินเทอร์เน็ตไม่ได้ โดยอาจมีค่าบริการ" - "เปลี่ยนจาก %1$s เป็น %2$s" - - "อินเทอร์เน็ตมือถือ" - "Wi-Fi" - "บลูทูธ" - "อีเทอร์เน็ต" - "VPN" - - "ประเภทเครือข่ายที่ไม่รู้จัก" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-tl/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-tl/strings.xml deleted file mode 100644 index 8d665fe5f98be..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-tl/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Mga Resource ng Pagkakonekta ng System" - "Mag-sign in sa Wi-Fi network" - "Mag-sign in sa network" - - - "Walang access sa internet ang %1$s" - "I-tap para sa mga opsyon" - "Walang access sa internet ang mobile network" - "Walang access sa internet ang network" - "Hindi ma-access ang pribadong DNS server" - "Limitado ang koneksyon ng %1$s" - "I-tap para kumonekta pa rin" - "Lumipat sa %1$s" - "Ginagamit ng device ang %1$s kapag walang access sa internet ang %2$s. Maaaring may mga malapat na singilin." - "Lumipat sa %2$s mula sa %1$s" - - "mobile data" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "isang hindi kilalang uri ng network" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-tr/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-tr/strings.xml deleted file mode 100644 index cfb76323ed416..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-tr/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Sistem Bağlantı Kaynakları" - "Kablosuz ağda oturum açın" - "Ağda oturum açın" - - - "%1$s ağının internet bağlantısı yok" - "Seçenekler için dokunun" - "Mobil ağın internet bağlantısı yok" - "Ağın internet bağlantısı yok" - "Gizli DNS sunucusuna erişilemiyor" - "%1$s sınırlı bağlantıya sahip" - "Yine de bağlanmak için dokunun" - "%1$s ağına geçildi" - "%2$s ağının internet erişimi olmadığında cihaz %1$s ağını kullanır. Bunun için ödeme alınabilir." - "%1$s ağından %2$s ağına geçildi" - - "mobil veri" - "Kablosuz" - "Bluetooth" - "Ethernet" - "VPN" - - "bilinmeyen ağ türü" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-uk/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-uk/strings.xml deleted file mode 100644 index c5da7460b3beb..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-uk/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Ресурси для підключення системи" - "Вхід у мережу Wi-Fi" - "Вхід у мережу" - - - "Мережа %1$s не має доступу до Інтернету" - "Торкніться, щоб відкрити опції" - "Мобільна мережа не має доступу до Інтернету" - "Мережа не має доступу до Інтернету" - "Немає доступу до приватного DNS-сервера" - "Підключення до мережі %1$s обмежено" - "Натисніть, щоб усе одно підключитися" - "Пристрій перейшов на мережу %1$s" - "Коли мережа %2$s не має доступу до Інтернету, використовується %1$s. Може стягуватися плата." - "Пристрій перейшов з мережі %1$s на мережу %2$s" - - "мобільний Інтернет" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "невідомий тип мережі" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ur/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-ur/strings.xml deleted file mode 100644 index bd2a228ab4304..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-ur/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "سسٹم کنیکٹوٹی کے وسائل" - "‏Wi-Fi نیٹ ورک میں سائن ان کریں" - "نیٹ ورک میں سائن ان کریں" - - - "%1$s کو انٹرنیٹ تک رسائی حاصل نہیں ہے" - "اختیارات کیلئے تھپتھپائیں" - "موبائل نیٹ ورک کو انٹرنیٹ تک رسائی حاصل نہیں ہے" - "نیٹ ورک کو انٹرنیٹ تک رسائی حاصل نہیں ہے" - "‏نجی DNS سرور تک رسائی حاصل نہیں کی جا سکی" - "%1$s کی کنیکٹوٹی محدود ہے" - "بہر حال منسلک کرنے کے لیے تھپتھپائیں" - "%1$s پر سوئچ ہو گیا" - "جب %2$s کو انٹرنیٹ تک رسائی نہیں ہوتی ہے تو آلہ %1$s کا استعمال کرتا ہے۔ چارجز لاگو ہو سکتے ہیں۔" - "%1$s سے %2$s پر سوئچ ہو گیا" - - "موبائل ڈیٹا" - "Wi-Fi" - "بلوٹوتھ" - "ایتھرنیٹ" - "VPN" - - "نامعلوم نیٹ ورک کی قسم" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-uz/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-uz/strings.xml deleted file mode 100644 index 567aa886b4a9d..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-uz/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Tizim aloqa resurslari" - "Wi-Fi tarmoqqa kirish" - "Tarmoqqa kirish" - - - "%1$s nomli tarmoqda internetga ruxsati yoʻq" - "Variantlarni ko‘rsatish uchun bosing" - "Mobil tarmoq internetga ulanmagan" - "Tarmoq internetga ulanmagan" - "Xususiy DNS server ishlamayapti" - "%1$s nomli tarmoqda aloqa cheklangan" - "Baribir ulash uchun bosing" - "Yangi ulanish: %1$s" - "Agar %2$s tarmoqda internet uzilsa, qurilma %1$sga ulanadi. Sarflangan trafik uchun haq olinishi mumkin." - "%1$s tarmog‘idan %2$s tarmog‘iga o‘tildi" - - "mobil internet" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "nomaʼlum tarmoq turi" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-vi/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-vi/strings.xml deleted file mode 100644 index 590b388c960fd..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-vi/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Tài nguyên kết nối hệ thống" - "Đăng nhập vào mạng Wi-Fi" - "Đăng nhập vào mạng" - - - "%1$s không có quyền truy cập Internet" - "Nhấn để biết tùy chọn" - "Mạng di động không có quyền truy cập Internet" - "Mạng không có quyền truy cập Internet" - "Không thể truy cập máy chủ DNS riêng tư" - "%1$s có khả năng kết nối giới hạn" - "Nhấn để tiếp tục kết nối" - "Đã chuyển sang %1$s" - "Thiết bị sử dụng %1$s khi %2$s không có quyền truy cập Internet. Bạn có thể phải trả phí." - "Đã chuyển từ %1$s sang %2$s" - - "dữ liệu di động" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" - - "loại mạng không xác định" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-zh-rCN/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-zh-rCN/strings.xml deleted file mode 100644 index 9d6cff90e2c34..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-zh-rCN/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "系统网络连接资源" - "登录到WLAN网络" - "登录到网络" - - - "%1$s 无法访问互联网" - "点按即可查看相关选项" - "此移动网络无法访问互联网" - "此网络无法访问互联网" - "无法访问私人 DNS 服务器" - "%1$s 的连接受限" - "点按即可继续连接" - "已切换至%1$s" - "设备会在%2$s无法访问互联网时使用%1$s(可能需要支付相应的费用)。" - "已从%1$s切换至%2$s" - - "移动数据" - "WLAN" - "蓝牙" - "以太网" - "VPN" - - "未知网络类型" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-zh-rHK/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-zh-rHK/strings.xml deleted file mode 100644 index c84241c8963e7..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-zh-rHK/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "系統連線資源" - "登入 Wi-Fi 網絡" - "登入網絡" - - - "%1$s未有連接至互聯網" - "輕按即可查看選項" - "流動網絡並未連接互聯網" - "網絡並未連接互聯網" - "無法存取私人 DNS 伺服器" - "%1$s連線受限" - "仍要輕按以連結至此網絡" - "已切換至%1$s" - "裝置會在 %2$s 無法連線至互聯網時使用%1$s (可能需要支付相關費用)。" - "已從%1$s切換至%2$s" - - "流動數據" - "Wi-Fi" - "藍牙" - "以太網絡" - "VPN" - - "不明網絡類型" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-zh-rTW/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-zh-rTW/strings.xml deleted file mode 100644 index 07540d18c0f95..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-zh-rTW/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "系統連線資源" - "登入 Wi-Fi 網路" - "登入網路" - - - "%1$s 沒有網際網路連線" - "輕觸即可查看選項" - "這個行動網路沒有網際網路連線" - "這個網路沒有網際網路連線" - "無法存取私人 DNS 伺服器" - "%1$s 的連線能力受限" - "輕觸即可繼續連線" - "已切換至%1$s" - "裝置會在無法連上「%2$s」時切換至「%1$s」(可能需要支付相關費用)。" - "已從 %1$s 切換至%2$s" - - "行動數據" - "Wi-Fi" - "藍牙" - "乙太網路" - "VPN" - - "不明的網路類型" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values-zu/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values-zu/strings.xml deleted file mode 100644 index 19f390ba61e0a..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values-zu/strings.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - "Izinsiza Zokuxhumeka Zesistimu" - "Ngena ngemvume kunethiwekhi ye-Wi-Fi" - "Ngena ngemvume kunethiwekhi" - - - "I-%1$s ayinakho ukufinyelela kwe-inthanethi" - "Thepha ukuze uthole izinketho" - "Inethiwekhi yeselula ayinakho ukufinyelela kwe-inthanethi" - "Inethiwekhi ayinakho ukufinyelela kwenethiwekhi" - "Iseva eyimfihlo ye-DNS ayikwazi ukufinyelelwa" - "I-%1$s inokuxhumeka okukhawulelwe" - "Thepha ukuze uxhume noma kunjalo" - "Kushintshelwe ku-%1$s" - "Idivayisi isebenzisa i-%1$s uma i-%2$s inganakho ukufinyelela kwe-inthanethi. Kungasebenza izindleko." - "Kushintshelewe kusuka ku-%1$s kuya ku-%2$s" - - "idatha yeselula" - "I-Wi-Fi" - "I-Bluetooth" - "I-Ethernet" - "I-VPN" - - "uhlobo olungaziwa lwenethiwekhi" - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values/config.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values/config.xml deleted file mode 100644 index 70ddb9a7e9faf..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values/config.xml +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - - - - - - - 60000 - - - - - - - - 2,60000 - 3,60000 - 4,60000 - 5,60000 - 10,60000 - 11,60000 - 12,60000 - - - - - - 0,1 - 1,3 - - - - 2 - - - 2 - - - 0 - - - 1 - - - - 10 - 11 - 12 - 14 - 15 - - - - false - - - - 0 - - - 0 - - - 0 - - - - - - - false - - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values/overlayable.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values/overlayable.xml deleted file mode 100644 index fd235661dc068..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values/overlayable.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/res/values/strings.xml b/packages/Connectivity/service/ServiceConnectivityResources/res/values/strings.xml deleted file mode 100644 index b2fa5f5b41298..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/res/values/strings.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - System Connectivity Resources - - - Sign in to Wi-Fi network - - - Sign in to network - - - %1$s - - - %1$s has no internet access - - - Tap for options - - - Mobile network has no internet access - - - Network has no internet access - - - Private DNS server cannot be accessed - - - %1$s has limited connectivity - - - Tap to connect anyway - - - Switched to %1$s - - - Device uses %1$s when %2$s has no internet access. Charges may apply. - - - Switched from %1$s to %2$s - - - - mobile data - Wi-Fi - Bluetooth - Ethernet - VPN - - - - an unknown network type - - diff --git a/packages/Connectivity/service/ServiceConnectivityResources/resources-certs/com.android.connectivity.resources.pk8 b/packages/Connectivity/service/ServiceConnectivityResources/resources-certs/com.android.connectivity.resources.pk8 deleted file mode 100644 index bfdc28b313ec1..0000000000000 Binary files a/packages/Connectivity/service/ServiceConnectivityResources/resources-certs/com.android.connectivity.resources.pk8 and /dev/null differ diff --git a/packages/Connectivity/service/ServiceConnectivityResources/resources-certs/com.android.connectivity.resources.x509.pem b/packages/Connectivity/service/ServiceConnectivityResources/resources-certs/com.android.connectivity.resources.x509.pem deleted file mode 100644 index 70eca1cee1d0f..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/resources-certs/com.android.connectivity.resources.x509.pem +++ /dev/null @@ -1,36 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIGQzCCBCugAwIBAgIUZY8nxBMINp/79sziXU77MLPpEXowDQYJKoZIhvcNAQEL -BQAwga8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH -DA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRy -b2lkMSswKQYDVQQDDCJjb20uYW5kcm9pZC5jb25uZWN0aXZpdHkucmVzb3VyY2Vz -MSIwIAYJKoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJvaWQuY29tMCAXDTIxMDQyMjA3 -MjkxMFoYDzQ3NTkwMzE5MDcyOTEwWjCBrzELMAkGA1UEBhMCVVMxEzARBgNVBAgM -CkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB0Fu -ZHJvaWQxEDAOBgNVBAsMB0FuZHJvaWQxKzApBgNVBAMMImNvbS5hbmRyb2lkLmNv -bm5lY3Rpdml0eS5yZXNvdXJjZXMxIjAgBgkqhkiG9w0BCQEWE2FuZHJvaWRAYW5k -cm9pZC5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC361NT9qSz -h3uLcLBD67HNE1QX3ykwGyw8u7ExzqpsqLCzZsOCFRJQJY+CnrgNaAz0NXeNtx7D -Lpr9OCWWbG1KTQ/ANlR8g6xCqlAk4xdixsAnIlBUJB90+RlkcWrliEY7OwcqIu3x -/qe+5UR3irIFZOApNHOm760PjRl7VWAnYZC/PhkW0iKwnBuE96ddPIJc+KuiqCcP -KflgF4/jmbHTZ+5uvVV4qkfovc744HnQtQoCDoYR8WpsJv3YL5xrAv78o3WCRzx6 -xxB+eUlJpuyyfIee2lUCG4Ly4jgOsWaupnUglLDORnz/L8fhhnpv83wLal7E0Shx -sqvzZZbb1QLuwMWy++gfzdDvGWewES3BdSFp5NwYWXQGZWSkEEFbIiorKSurU1On -9OwB0jT/H2B/CAFKYJQ2V+hQ4I7PG+z9p7ZFNR6GZbZuhEr+Dpq1CwtI3W45izr3 -RJgcc2IP6Oj7/XC2MmKGMqZkybBWcvazdyAMHzk9EZIBT2Oru3dnOl3uVUUPeZRs -xRzqaA0MAlyj+GJ9uziEr3W1j+U1CFEnNWtlD/jqcTAwmaOsn1GhWyMAo1KOrJ/o -LcJvwk5P/0XEyeli7/DSUpGjYiAgWMHWCOn9s6aYw3YFb+A/SgX3/+FIDib/vHTX -i76JZfO0CfoKsbFDCH9KOMupHM9EO3ftQwIDAQABo1MwUTAdBgNVHQ4EFgQU/KGg -gmMqXD5YOe5+B0W+YezN9LcwHwYDVR0jBBgwFoAU/KGggmMqXD5YOe5+B0W+YezN -9LcwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAhr+AaNaIlRyM -WKyJ+2Aa35fH5e44Xr/xPpriM5HHxsj0evjMCODqCQ7kzfwSEmtXh5uZYYNKb/JP -ZMDHIFcYi1QCvm6E6YOd+Qn9CVxrwaDhigJv7ylhVf8q201GTvHhJIU99yFIrzJQ -RNhxw+pNo7FYMZr3J7JZPAy60DN1KZvRV4FjZx5qiPUMyu4zVygzDkr0v5Ilncdp -l9VVjOi7ocHyBKI+7RkXl97xN4SUe3vszwZQHCVyVopBw+YrMbDBCrknrQzUEgie -BuI+kj5oOeiQ0P1i1K+UCCAjrLwhNyc9H02rKUtBHxa2AVjw7YpAJlBesb49Qvq+ -5L6JjHFVSSOEbIjboNib26zNackjbiefF74meSUbGVGfcJ1OdkZsXZWphmER8V7X -Wz3Z8JwOXW1RLPgcbjilHUR5g8pEmWBv4KrTCSg5IvOJr4w3pyyMBiiVI9NI5sB7 -g5Mi9v3ifPD1OHA4Y3wYCb26mMEpRb8ogOhMHcGNbdnL3QtIUg4cmXGqGSY/LbpU -np0sIQDSjc46o79F0boPsLlaN3US5WZIu0nc9SHkjoNhd0CJQ5r9aEn4/wNrZgxs -s8OEKsqcS7OsWiIE6nG51TMDsCuyRBrGedtSUyFFSVSpivpYIrPVNKKlHsJ/o+Nv -Udb6dBjCraPvJB8binB1aojwya3MwRs= ------END CERTIFICATE----- diff --git a/packages/Connectivity/service/ServiceConnectivityResources/resources-certs/key.pem b/packages/Connectivity/service/ServiceConnectivityResources/resources-certs/key.pem deleted file mode 100644 index 38771c261518e..0000000000000 --- a/packages/Connectivity/service/ServiceConnectivityResources/resources-certs/key.pem +++ /dev/null @@ -1,52 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQC361NT9qSzh3uL -cLBD67HNE1QX3ykwGyw8u7ExzqpsqLCzZsOCFRJQJY+CnrgNaAz0NXeNtx7DLpr9 -OCWWbG1KTQ/ANlR8g6xCqlAk4xdixsAnIlBUJB90+RlkcWrliEY7OwcqIu3x/qe+ -5UR3irIFZOApNHOm760PjRl7VWAnYZC/PhkW0iKwnBuE96ddPIJc+KuiqCcPKflg -F4/jmbHTZ+5uvVV4qkfovc744HnQtQoCDoYR8WpsJv3YL5xrAv78o3WCRzx6xxB+ -eUlJpuyyfIee2lUCG4Ly4jgOsWaupnUglLDORnz/L8fhhnpv83wLal7E0Shxsqvz -ZZbb1QLuwMWy++gfzdDvGWewES3BdSFp5NwYWXQGZWSkEEFbIiorKSurU1On9OwB -0jT/H2B/CAFKYJQ2V+hQ4I7PG+z9p7ZFNR6GZbZuhEr+Dpq1CwtI3W45izr3RJgc -c2IP6Oj7/XC2MmKGMqZkybBWcvazdyAMHzk9EZIBT2Oru3dnOl3uVUUPeZRsxRzq -aA0MAlyj+GJ9uziEr3W1j+U1CFEnNWtlD/jqcTAwmaOsn1GhWyMAo1KOrJ/oLcJv -wk5P/0XEyeli7/DSUpGjYiAgWMHWCOn9s6aYw3YFb+A/SgX3/+FIDib/vHTXi76J -ZfO0CfoKsbFDCH9KOMupHM9EO3ftQwIDAQABAoICAQCXM/GKqtAXBIBOT/Ops0C2 -n3hYM9BRy1UgDRKNJyG3OSwkIY0ECbzHhUmpkkEwTGWx8675JB43Sr6DBUDpnPRw -zE/xrvjgcQQSvqAq40PbohhhU/WEZzoxWYVFrXS7hcBve4TVYGgMtlZEO4qBWNYo -Vxlu5r9Z89tsWI0ldzgYyD5O64eG2nVIit6Y/11p6pAmTQ4WKHYMIm7xUA2siTPH -4L8F7cQx8pQxxLI+q5WaPuweasBQShA7IAc7T1EiLRFitCOsWlJfgf6Oa7oTwhcA -Wh7JOyf+Fo4ejlqVwcTwOss6YOPGge7LgQWr5HoORbeqTuXgmy/L4Z85+EABNOs1 -5muHZvsuPXSmW6g1bCi8zvQcjFIX31yBVg8zkdG8WRezFxiVlN8UFAx4rwo03aBs -rDyU4GCxoUBvF/M9534l1gKOyr0hlQ40nQ4kBabbm2wWOKCVzmLEtFmWX9RV0tjX -pEtTCqgsGlsIypLy21+uow8SBojhkZ+xORCF2XivGu6SKtvwGvjpYXpXrI6DN4Lw -kH5J5FwSu1SNY8tnIEJEmj8IMTp+Vw20kwNVTcwdC2nJDDiezJum4PqZRdWIuupm -BWzXD3fvMXqHmT02sJTQ+FRAgiQLLWDzNAYMJUofzuIwycs4iO9MOPHjkHScvk4N -FXLrzFBSbdw+wi1DdzzMuQKCAQEA5wx07O5bHBHybs6tpwuZ0TuJ3OIVXh/ocNVR -gSOCSMirv+K4u3jToXwjfTXUc9lcn+DenZPpGmUWF0sZ83ytZm1eFVgGZpP6941C -waSeb8zGsgbEyZIQTVILfgtyPDwdtgu0d1Ip+ppj9czXmnxMY/ruHOX1Do1UfZoA -UA1ytHJSjFKU6saAhHrdk91soTVzc/E3uo7U4Ff0L8/3tT3DAEFYxDXUCH8W2IZZ -6zVvlqnPH4elxsPYM6rtIwq52reOTLNxC+SFSamK/82zu09Kjj5sQ6HKlvKJFiL5 -bULWu4lenoDfEN0lng+QopJTgZq4/tgOLum43C/Zd0PGC9R6PwKCAQEAy8fvPqwM -gPbNasni9qGVG+FfiFd/wEMlgKlVVqi+WzF6tCAnXCQXXg3A7FpLQrX8hVKdMznq -wPgM5AXP4FOguBFNk65chZmPizBIUDPJ4TNHI8FcGgcxbKGvDdVHsUpa/h5rJlvV -GLJTKV4KjcsTjl5tlRsJ48bSfpBNQHpSKlCswT6jjteiDY6Rln0GFKQIKDHqp3I6 -Zn1E4yfdiIz9VnMPfg1fbjBeR7s1zNzlrR8Dv9oK9tkzI5G1wSbdzksg2O1q2tvg -WrZrTAA3Uw6sPUMft0vk5Jw6a6CLkrcfayv3xDHwvM/4P3HgP8j9WQ8at8ttHpfD -oWyt3fZ3pBuj/QKCAQANqxH7tjoTlgg2f+mL+Ua3NwN32rQS5mZUznnM3vHlJmHq -rxnolURHyFU9IgMYe2JcXuwsfESM+C/vXtUBL33+kje/oX53cQemv2eUlw18ZavX -ekkH96kZOeJOKZUvdQr46wZZDLZJCfsh3mVe0T2fqIePlBcELl4yM/sSwUjo3d5+ -SKBgpy+RJseW6MF1Y/kZgcqfMbXsM6fRcEciJK41hKggq2KIwiPy2TfWj0mzqwYC -wn6PHKTcoZ73tLm786Hqba8hWfp8mhgL+/pG+XDaq1yyP48BkQWFFrqUuSCE5aKA -U/VeRQblq9wNkgR4pVOOV++23MK/2+DMimjb6Ez3AoIBABIXK7wKlgmU32ONjKKM -capJ9asq6WJuE5Q6dCL/U/bQi64V9KiPY6ur2OailW/UrBhB30a+64I6AxrzESM/ -CVON5a8omXoayc13edP05QUjAjvAXKbK4K5eJCY8OuMYUL+if6ymFmLc4dkYSiOQ -Vaob4+qKvfQEoIcv1EvXEBhFlTCKmQaDShWeBHqxmqqWbUr0M3qt/1U95bGsxlPr -AEp+aG+uTDyB+ryvd/U53wHhcPnFJ5gGbC3KL7J3+tTngoD/gq7vOhmTfC8BDehH -sy61GMmy6R0KaX1IgVuC+j0PaC14qYB5jfZD675930/asWqDmqpOmsVn2n+L888T -zRkCggEBAIMuNhhfGGY6E4PLUcPM0LZA4tI/wTpeYEahunU1hWIYo/iZB9od2biz -EeYY4BtkzCoE5ZWYXqTgiMxN4hJ4ufB+5umZ4BO0Gyx4p2/Ik2uv1BXu++GbM+TI -eeFmaBh00dTtjccpeZEDgNkjAO7Rh9GV2ifl3uhqg0MnFXywPUX2Vm2bmwQXnfV9 -wY2TXgOmBN2epFBOArJwiA5IfV+bSqXCFCx8fgyOWpMNq9+zDRd6KCeHyge54ahm -jMhCncp1OPDPaV+gnUdgWDGcywYg0KQvu5dLuCFfvucnsWoH2txsVZrXFha5XSM4 -/4Pif3Aj5E9dm1zkUtZJYQbII5SKQ94= ------END PRIVATE KEY----- diff --git a/packages/Connectivity/service/jarjar-rules.txt b/packages/Connectivity/service/jarjar-rules.txt deleted file mode 100644 index 5caa11b11ae4b..0000000000000 --- a/packages/Connectivity/service/jarjar-rules.txt +++ /dev/null @@ -1,17 +0,0 @@ -rule android.sysprop.** com.android.connectivity.sysprop.@1 -rule com.android.net.module.util.** com.android.connectivity.net-utils.@1 -rule com.android.modules.utils.** com.android.connectivity.modules-utils.@1 - -# internal util classes -# Exclude AsyncChannel. TODO: remove AsyncChannel usage in ConnectivityService -rule com.android.internal.util.AsyncChannel* @0 -# Exclude LocationPermissionChecker. This is going to be moved to libs/net -rule com.android.internal.util.LocationPermissionChecker* @0 -rule android.util.LocalLog* com.android.connectivity.util.LocalLog@1 -# android.util.IndentingPrintWriter* should use a different package name from -# the one in com.android.internal.util -rule android.util.IndentingPrintWriter* android.connectivity.util.IndentingPrintWriter@1 -rule com.android.internal.util.** com.android.connectivity.util.@1 - -rule com.android.internal.messages.** com.android.connectivity.messages.@1 -rule com.google.protobuf.** com.android.connectivity.protobuf.@1 diff --git a/packages/Connectivity/service/jni/com_android_server_TestNetworkService.cpp b/packages/Connectivity/service/jni/com_android_server_TestNetworkService.cpp deleted file mode 100644 index e7a40e5ea66be..0000000000000 --- a/packages/Connectivity/service/jni/com_android_server_TestNetworkService.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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. - */ - -#define LOG_NDEBUG 0 - -#define LOG_TAG "TestNetworkServiceJni" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "jni.h" -#include -#include -#include -#include - -namespace android { - -//------------------------------------------------------------------------------ - -static void throwException(JNIEnv* env, int error, const char* action, const char* iface) { - const std::string& msg = "Error: " + std::string(action) + " " + std::string(iface) + ": " - + std::string(strerror(error)); - jniThrowException(env, "java/lang/IllegalStateException", msg.c_str()); -} - -static int createTunTapInterface(JNIEnv* env, bool isTun, const char* iface) { - base::unique_fd tun(open("/dev/tun", O_RDWR | O_NONBLOCK)); - ifreq ifr{}; - - // Allocate interface. - ifr.ifr_flags = (isTun ? IFF_TUN : IFF_TAP) | IFF_NO_PI; - strlcpy(ifr.ifr_name, iface, IFNAMSIZ); - if (ioctl(tun.get(), TUNSETIFF, &ifr)) { - throwException(env, errno, "allocating", ifr.ifr_name); - return -1; - } - - // Activate interface using an unconnected datagram socket. - base::unique_fd inet6CtrlSock(socket(AF_INET6, SOCK_DGRAM, 0)); - ifr.ifr_flags = IFF_UP; - - if (ioctl(inet6CtrlSock.get(), SIOCSIFFLAGS, &ifr)) { - throwException(env, errno, "activating", ifr.ifr_name); - return -1; - } - - return tun.release(); -} - -//------------------------------------------------------------------------------ - -static jint create(JNIEnv* env, jobject /* thiz */, jboolean isTun, jstring jIface) { - ScopedUtfChars iface(env, jIface); - if (!iface.c_str()) { - jniThrowNullPointerException(env, "iface"); - return -1; - } - - int tun = createTunTapInterface(env, isTun, iface.c_str()); - - // Any exceptions will be thrown from the createTunTapInterface call - return tun; -} - -//------------------------------------------------------------------------------ - -static const JNINativeMethod gMethods[] = { - {"jniCreateTunTap", "(ZLjava/lang/String;)I", (void*)create}, -}; - -int register_android_server_TestNetworkService(JNIEnv* env) { - return jniRegisterNativeMethods(env, "com/android/server/TestNetworkService", gMethods, - NELEM(gMethods)); -} - -}; // namespace android diff --git a/packages/Connectivity/service/jni/onload.cpp b/packages/Connectivity/service/jni/onload.cpp deleted file mode 100644 index 00128794bcd06..0000000000000 --- a/packages/Connectivity/service/jni/onload.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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. - */ - -#include -#include - -namespace android { - -int register_android_server_TestNetworkService(JNIEnv* env); - -extern "C" jint JNI_OnLoad(JavaVM* vm, void*) { - JNIEnv *env; - if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) { - ALOGE("GetEnv failed"); - return JNI_ERR; - } - - if (register_android_server_TestNetworkService(env) < 0) { - return JNI_ERR; - } - - return JNI_VERSION_1_6; -} - -}; diff --git a/packages/Connectivity/service/lint-baseline.xml b/packages/Connectivity/service/lint-baseline.xml deleted file mode 100644 index 95c169ce64a36..0000000000000 --- a/packages/Connectivity/service/lint-baseline.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/packages/Connectivity/service/proto/connectivityproto.proto b/packages/Connectivity/service/proto/connectivityproto.proto deleted file mode 100644 index a992d7c26368a..0000000000000 --- a/packages/Connectivity/service/proto/connectivityproto.proto +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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. - */ - -syntax = "proto2"; - -// Connectivity protos can be created in this directory. Note this file must be included before -// building system-messages-proto, otherwise it will not build by itself. diff --git a/packages/Connectivity/service/src/com/android/server/ConnectivityService.java b/packages/Connectivity/service/src/com/android/server/ConnectivityService.java deleted file mode 100644 index 5c47f27ef58f1..0000000000000 --- a/packages/Connectivity/service/src/com/android/server/ConnectivityService.java +++ /dev/null @@ -1,10077 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server; - -import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE; -import static android.content.pm.PackageManager.FEATURE_BLUETOOTH; -import static android.content.pm.PackageManager.FEATURE_WATCH; -import static android.content.pm.PackageManager.FEATURE_WIFI; -import static android.content.pm.PackageManager.FEATURE_WIFI_DIRECT; -import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_PROBES_ATTEMPTED_BITMASK; -import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_PROBES_SUCCEEDED_BITMASK; -import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_VALIDATION_RESULT; -import static android.net.ConnectivityDiagnosticsManager.DataStallReport.DETECTION_METHOD_DNS_EVENTS; -import static android.net.ConnectivityDiagnosticsManager.DataStallReport.DETECTION_METHOD_TCP_METRICS; -import static android.net.ConnectivityDiagnosticsManager.DataStallReport.KEY_DNS_CONSECUTIVE_TIMEOUTS; -import static android.net.ConnectivityDiagnosticsManager.DataStallReport.KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS; -import static android.net.ConnectivityDiagnosticsManager.DataStallReport.KEY_TCP_PACKET_FAIL_RATE; -import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_MASK; -import static android.net.ConnectivityManager.BLOCKED_REASON_LOCKDOWN_VPN; -import static android.net.ConnectivityManager.BLOCKED_REASON_NONE; -import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; -import static android.net.ConnectivityManager.TYPE_BLUETOOTH; -import static android.net.ConnectivityManager.TYPE_ETHERNET; -import static android.net.ConnectivityManager.TYPE_MOBILE; -import static android.net.ConnectivityManager.TYPE_MOBILE_CBS; -import static android.net.ConnectivityManager.TYPE_MOBILE_DUN; -import static android.net.ConnectivityManager.TYPE_MOBILE_EMERGENCY; -import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA; -import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI; -import static android.net.ConnectivityManager.TYPE_MOBILE_IA; -import static android.net.ConnectivityManager.TYPE_MOBILE_IMS; -import static android.net.ConnectivityManager.TYPE_MOBILE_MMS; -import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL; -import static android.net.ConnectivityManager.TYPE_NONE; -import static android.net.ConnectivityManager.TYPE_PROXY; -import static android.net.ConnectivityManager.TYPE_VPN; -import static android.net.ConnectivityManager.TYPE_WIFI; -import static android.net.ConnectivityManager.TYPE_WIFI_P2P; -import static android.net.ConnectivityManager.getNetworkTypeName; -import static android.net.ConnectivityManager.isNetworkTypeValid; -import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OPPORTUNISTIC; -import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS; -import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL; -import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID; -import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL; -import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE; -import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND; -import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED; -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_ROAMING; -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_NOT_VPN; -import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID; -import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE; -import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY; -import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; -import static android.net.NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION; -import static android.net.NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS; -import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS; -import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; -import static android.net.NetworkCapabilities.TRANSPORT_TEST; -import static android.net.NetworkCapabilities.TRANSPORT_VPN; -import static android.net.NetworkRequest.Type.LISTEN_FOR_BEST; -import static android.net.shared.NetworkMonitorUtils.isPrivateDnsValidationRequired; -import static android.os.Process.INVALID_UID; -import static android.os.Process.VPN_UID; -import static android.system.OsConstants.IPPROTO_TCP; -import static android.system.OsConstants.IPPROTO_UDP; - -import static java.util.Map.Entry; - -import android.Manifest; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.app.AppOpsManager; -import android.app.BroadcastOptions; -import android.app.PendingIntent; -import android.app.usage.NetworkStatsManager; -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageManager; -import android.database.ContentObserver; -import android.net.CaptivePortal; -import android.net.CaptivePortalData; -import android.net.ConnectionInfo; -import android.net.ConnectivityAnnotations.RestrictBackgroundStatus; -import android.net.ConnectivityDiagnosticsManager.ConnectivityReport; -import android.net.ConnectivityDiagnosticsManager.DataStallReport; -import android.net.ConnectivityManager; -import android.net.ConnectivityManager.BlockedReason; -import android.net.ConnectivityManager.NetworkCallback; -import android.net.ConnectivityResources; -import android.net.ConnectivitySettingsManager; -import android.net.DataStallReportParcelable; -import android.net.DnsResolverServiceManager; -import android.net.ICaptivePortal; -import android.net.IConnectivityDiagnosticsCallback; -import android.net.IConnectivityManager; -import android.net.IDnsResolver; -import android.net.INetd; -import android.net.INetworkActivityListener; -import android.net.INetworkAgent; -import android.net.INetworkMonitor; -import android.net.INetworkMonitorCallbacks; -import android.net.INetworkOfferCallback; -import android.net.IOnCompleteListener; -import android.net.IQosCallback; -import android.net.ISocketKeepaliveCallback; -import android.net.InetAddresses; -import android.net.IpMemoryStore; -import android.net.IpPrefix; -import android.net.LinkProperties; -import android.net.MatchAllNetworkSpecifier; -import android.net.NativeNetworkConfig; -import android.net.NativeNetworkType; -import android.net.NattSocketKeepalive; -import android.net.Network; -import android.net.NetworkAgent; -import android.net.NetworkAgentConfig; -import android.net.NetworkCapabilities; -import android.net.NetworkInfo; -import android.net.NetworkInfo.DetailedState; -import android.net.NetworkMonitorManager; -import android.net.NetworkPolicyManager; -import android.net.NetworkPolicyManager.NetworkPolicyCallback; -import android.net.NetworkProvider; -import android.net.NetworkRequest; -import android.net.NetworkScore; -import android.net.NetworkSpecifier; -import android.net.NetworkStack; -import android.net.NetworkState; -import android.net.NetworkStateSnapshot; -import android.net.NetworkTestResultParcelable; -import android.net.NetworkUtils; -import android.net.NetworkWatchlistManager; -import android.net.OemNetworkPreferences; -import android.net.PrivateDnsConfigParcel; -import android.net.ProxyInfo; -import android.net.QosCallbackException; -import android.net.QosFilter; -import android.net.QosSocketFilter; -import android.net.QosSocketInfo; -import android.net.RouteInfo; -import android.net.RouteInfoParcel; -import android.net.SocketKeepalive; -import android.net.TetheringManager; -import android.net.TransportInfo; -import android.net.UidRange; -import android.net.UidRangeParcel; -import android.net.UnderlyingNetworkInfo; -import android.net.Uri; -import android.net.VpnManager; -import android.net.VpnTransportInfo; -import android.net.metrics.IpConnectivityLog; -import android.net.metrics.NetworkEvent; -import android.net.netlink.InetDiagMessage; -import android.net.networkstack.ModuleNetworkStackClient; -import android.net.networkstack.NetworkStackClientBase; -import android.net.resolv.aidl.DnsHealthEventParcel; -import android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener; -import android.net.resolv.aidl.Nat64PrefixEventParcel; -import android.net.resolv.aidl.PrivateDnsValidationEventParcel; -import android.net.shared.PrivateDnsConfig; -import android.net.util.MultinetworkPolicyTracker; -import android.os.BatteryStatsManager; -import android.os.Binder; -import android.os.Build; -import android.os.Bundle; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.Looper; -import android.os.Message; -import android.os.Messenger; -import android.os.ParcelFileDescriptor; -import android.os.Parcelable; -import android.os.PersistableBundle; -import android.os.PowerManager; -import android.os.Process; -import android.os.RemoteCallbackList; -import android.os.RemoteException; -import android.os.ServiceSpecificException; -import android.os.SystemClock; -import android.os.SystemProperties; -import android.os.UserHandle; -import android.os.UserManager; -import android.provider.Settings; -import android.sysprop.NetworkProperties; -import android.telephony.TelephonyManager; -import android.text.TextUtils; -import android.util.ArrayMap; -import android.util.ArraySet; -import android.util.LocalLog; -import android.util.Log; -import android.util.Pair; -import android.util.SparseArray; -import android.util.SparseIntArray; - -import com.android.connectivity.resources.R; -import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.IndentingPrintWriter; -import com.android.internal.util.MessageUtils; -import com.android.modules.utils.BasicShellCommandHandler; -import com.android.net.module.util.BaseNetdUnsolicitedEventListener; -import com.android.net.module.util.CollectionUtils; -import com.android.net.module.util.LinkPropertiesUtils.CompareOrUpdateResult; -import com.android.net.module.util.LinkPropertiesUtils.CompareResult; -import com.android.net.module.util.LocationPermissionChecker; -import com.android.net.module.util.NetworkCapabilitiesUtils; -import com.android.net.module.util.PermissionUtils; -import com.android.server.connectivity.AutodestructReference; -import com.android.server.connectivity.DnsManager; -import com.android.server.connectivity.DnsManager.PrivateDnsValidationUpdate; -import com.android.server.connectivity.FullScore; -import com.android.server.connectivity.KeepaliveTracker; -import com.android.server.connectivity.LingerMonitor; -import com.android.server.connectivity.MockableSystemProperties; -import com.android.server.connectivity.NetworkAgentInfo; -import com.android.server.connectivity.NetworkDiagnostics; -import com.android.server.connectivity.NetworkNotificationManager; -import com.android.server.connectivity.NetworkNotificationManager.NotificationType; -import com.android.server.connectivity.NetworkOffer; -import com.android.server.connectivity.NetworkRanker; -import com.android.server.connectivity.PermissionMonitor; -import com.android.server.connectivity.ProfileNetworkPreferences; -import com.android.server.connectivity.ProxyTracker; -import com.android.server.connectivity.QosCallbackTracker; - -import libcore.io.IoUtils; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.net.Inet4Address; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.ConcurrentModificationException; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.SortedSet; -import java.util.StringJoiner; -import java.util.TreeSet; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * @hide - */ -public class ConnectivityService extends IConnectivityManager.Stub - implements PendingIntent.OnFinished { - private static final String TAG = ConnectivityService.class.getSimpleName(); - - private static final String DIAG_ARG = "--diag"; - public static final String SHORT_ARG = "--short"; - private static final String NETWORK_ARG = "networks"; - private static final String REQUEST_ARG = "requests"; - - private static final boolean DBG = true; - private static final boolean DDBG = Log.isLoggable(TAG, Log.DEBUG); - private static final boolean VDBG = Log.isLoggable(TAG, Log.VERBOSE); - - private static final boolean LOGD_BLOCKED_NETWORKINFO = true; - - /** - * Default URL to use for {@link #getCaptivePortalServerUrl()}. This should not be changed - * by OEMs for configuration purposes, as this value is overridden by - * ConnectivitySettingsManager.CAPTIVE_PORTAL_HTTP_URL. - * R.string.config_networkCaptivePortalServerUrl should be overridden instead for this purpose - * (preferably via runtime resource overlays). - */ - private static final String DEFAULT_CAPTIVE_PORTAL_HTTP_URL = - "http://connectivitycheck.gstatic.com/generate_204"; - - // TODO: create better separation between radio types and network types - - // how long to wait before switching back to a radio's default network - private static final int RESTORE_DEFAULT_NETWORK_DELAY = 1 * 60 * 1000; - // system property that can override the above value - private static final String NETWORK_RESTORE_DELAY_PROP_NAME = - "android.telephony.apn-restore"; - - // How long to wait before putting up a "This network doesn't have an Internet connection, - // connect anyway?" dialog after the user selects a network that doesn't validate. - private static final int PROMPT_UNVALIDATED_DELAY_MS = 8 * 1000; - - // Default to 30s linger time-out, and 5s for nascent network. Modifiable only for testing. - private static final String LINGER_DELAY_PROPERTY = "persist.netmon.linger"; - private static final int DEFAULT_LINGER_DELAY_MS = 30_000; - private static final int DEFAULT_NASCENT_DELAY_MS = 5_000; - - // The maximum number of network request allowed per uid before an exception is thrown. - private static final int MAX_NETWORK_REQUESTS_PER_UID = 100; - - // The maximum number of network request allowed for system UIDs before an exception is thrown. - @VisibleForTesting - static final int MAX_NETWORK_REQUESTS_PER_SYSTEM_UID = 250; - - @VisibleForTesting - protected int mLingerDelayMs; // Can't be final, or test subclass constructors can't change it. - @VisibleForTesting - protected int mNascentDelayMs; - - // How long to delay to removal of a pending intent based request. - // See ConnectivitySettingsManager.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS - private final int mReleasePendingIntentDelayMs; - - private MockableSystemProperties mSystemProperties; - - @VisibleForTesting - protected final PermissionMonitor mPermissionMonitor; - - private final PerUidCounter mNetworkRequestCounter; - @VisibleForTesting - final PerUidCounter mSystemNetworkRequestCounter; - - private volatile boolean mLockdownEnabled; - - /** - * Stale copy of uid blocked reasons provided by NPMS. As long as they are accessed only in - * internal handler thread, they don't need a lock. - */ - private SparseIntArray mUidBlockedReasons = new SparseIntArray(); - - private final Context mContext; - private final ConnectivityResources mResources; - // The Context is created for UserHandle.ALL. - private final Context mUserAllContext; - private final Dependencies mDeps; - // 0 is full bad, 100 is full good - private int mDefaultInetConditionPublished = 0; - - @VisibleForTesting - protected IDnsResolver mDnsResolver; - @VisibleForTesting - protected INetd mNetd; - private NetworkStatsManager mStatsManager; - private NetworkPolicyManager mPolicyManager; - private final NetdCallback mNetdCallback; - - /** - * TestNetworkService (lazily) created upon first usage. Locked to prevent creation of multiple - * instances. - */ - @GuardedBy("mTNSLock") - private TestNetworkService mTNS; - - private final Object mTNSLock = new Object(); - - private String mCurrentTcpBufferSizes; - - private static final SparseArray sMagicDecoderRing = MessageUtils.findMessageNames( - new Class[] { ConnectivityService.class, NetworkAgent.class, NetworkAgentInfo.class }); - - private enum ReapUnvalidatedNetworks { - // Tear down networks that have no chance (e.g. even if validated) of becoming - // the highest scoring network satisfying a NetworkRequest. This should be passed when - // all networks have been rematched against all NetworkRequests. - REAP, - // Don't reap networks. This should be passed when some networks have not yet been - // rematched against all NetworkRequests. - DONT_REAP - } - - private enum UnneededFor { - LINGER, // Determine whether this network is unneeded and should be lingered. - TEARDOWN, // Determine whether this network is unneeded and should be torn down. - } - - /** - * used internally to clear a wakelock when transitioning - * from one net to another. Clear happens when we get a new - * network - EVENT_EXPIRE_NET_TRANSITION_WAKELOCK happens - * after a timeout if no network is found (typically 1 min). - */ - private static final int EVENT_CLEAR_NET_TRANSITION_WAKELOCK = 8; - - /** - * used internally to reload global proxy settings - */ - private static final int EVENT_APPLY_GLOBAL_HTTP_PROXY = 9; - - /** - * PAC manager has received new port. - */ - private static final int EVENT_PROXY_HAS_CHANGED = 16; - - /** - * used internally when registering NetworkProviders - * obj = NetworkProviderInfo - */ - private static final int EVENT_REGISTER_NETWORK_PROVIDER = 17; - - /** - * used internally when registering NetworkAgents - * obj = Messenger - */ - private static final int EVENT_REGISTER_NETWORK_AGENT = 18; - - /** - * used to add a network request - * includes a NetworkRequestInfo - */ - private static final int EVENT_REGISTER_NETWORK_REQUEST = 19; - - /** - * indicates a timeout period is over - check if we had a network yet or not - * and if not, call the timeout callback (but leave the request live until they - * cancel it. - * includes a NetworkRequestInfo - */ - private static final int EVENT_TIMEOUT_NETWORK_REQUEST = 20; - - /** - * used to add a network listener - no request - * includes a NetworkRequestInfo - */ - private static final int EVENT_REGISTER_NETWORK_LISTENER = 21; - - /** - * used to remove a network request, either a listener or a real request - * arg1 = UID of caller - * obj = NetworkRequest - */ - private static final int EVENT_RELEASE_NETWORK_REQUEST = 22; - - /** - * used internally when registering NetworkProviders - * obj = Messenger - */ - private static final int EVENT_UNREGISTER_NETWORK_PROVIDER = 23; - - /** - * used internally to expire a wakelock when transitioning - * from one net to another. Expire happens when we fail to find - * a new network (typically after 1 minute) - - * EVENT_CLEAR_NET_TRANSITION_WAKELOCK happens if we had found - * a replacement network. - */ - private static final int EVENT_EXPIRE_NET_TRANSITION_WAKELOCK = 24; - - /** - * used to add a network request with a pending intent - * obj = NetworkRequestInfo - */ - private static final int EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT = 26; - - /** - * used to remove a pending intent and its associated network request. - * arg1 = UID of caller - * obj = PendingIntent - */ - private static final int EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT = 27; - - /** - * used to specify whether a network should be used even if unvalidated. - * arg1 = whether to accept the network if it's unvalidated (1 or 0) - * arg2 = whether to remember this choice in the future (1 or 0) - * obj = network - */ - private static final int EVENT_SET_ACCEPT_UNVALIDATED = 28; - - /** - * used to ask the user to confirm a connection to an unvalidated network. - * obj = network - */ - private static final int EVENT_PROMPT_UNVALIDATED = 29; - - /** - * used internally to (re)configure always-on networks. - */ - private static final int EVENT_CONFIGURE_ALWAYS_ON_NETWORKS = 30; - - /** - * used to add a network listener with a pending intent - * obj = NetworkRequestInfo - */ - private static final int EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT = 31; - - /** - * used to specify whether a network should not be penalized when it becomes unvalidated. - */ - private static final int EVENT_SET_AVOID_UNVALIDATED = 35; - - /** - * used to trigger revalidation of a network. - */ - private static final int EVENT_REVALIDATE_NETWORK = 36; - - // Handle changes in Private DNS settings. - private static final int EVENT_PRIVATE_DNS_SETTINGS_CHANGED = 37; - - // Handle private DNS validation status updates. - private static final int EVENT_PRIVATE_DNS_VALIDATION_UPDATE = 38; - - /** - * Event for NetworkMonitor/NetworkAgentInfo to inform ConnectivityService that the network has - * been tested. - * obj = {@link NetworkTestedResults} representing information sent from NetworkMonitor. - * data = PersistableBundle of extras passed from NetworkMonitor. If {@link - * NetworkMonitorCallbacks#notifyNetworkTested} is called, this will be null. - */ - private static final int EVENT_NETWORK_TESTED = 41; - - /** - * Event for NetworkMonitor/NetworkAgentInfo to inform ConnectivityService that the private DNS - * config was resolved. - * obj = PrivateDnsConfig - * arg2 = netid - */ - private static final int EVENT_PRIVATE_DNS_CONFIG_RESOLVED = 42; - - /** - * Request ConnectivityService display provisioning notification. - * arg1 = Whether to make the notification visible. - * arg2 = NetID. - * obj = Intent to be launched when notification selected by user, null if !arg1. - */ - private static final int EVENT_PROVISIONING_NOTIFICATION = 43; - - /** - * Used to specify whether a network should be used even if connectivity is partial. - * arg1 = whether to accept the network if its connectivity is partial (1 for true or 0 for - * false) - * arg2 = whether to remember this choice in the future (1 for true or 0 for false) - * obj = network - */ - private static final int EVENT_SET_ACCEPT_PARTIAL_CONNECTIVITY = 44; - - /** - * Event for NetworkMonitor to inform ConnectivityService that the probe status has changed. - * Both of the arguments are bitmasks, and the value of bits come from - * INetworkMonitor.NETWORK_VALIDATION_PROBE_*. - * arg1 = A bitmask to describe which probes are completed. - * arg2 = A bitmask to describe which probes are successful. - */ - public static final int EVENT_PROBE_STATUS_CHANGED = 45; - - /** - * Event for NetworkMonitor to inform ConnectivityService that captive portal data has changed. - * arg1 = unused - * arg2 = netId - * obj = captive portal data - */ - private static final int EVENT_CAPPORT_DATA_CHANGED = 46; - - /** - * Used by setRequireVpnForUids. - * arg1 = whether the specified UID ranges are required to use a VPN. - * obj = Array of UidRange objects. - */ - private static final int EVENT_SET_REQUIRE_VPN_FOR_UIDS = 47; - - /** - * Used internally when setting the default networks for OemNetworkPreferences. - * obj = Pair - */ - private static final int EVENT_SET_OEM_NETWORK_PREFERENCE = 48; - - /** - * Used to indicate the system default network becomes active. - */ - private static final int EVENT_REPORT_NETWORK_ACTIVITY = 49; - - /** - * Used internally when setting a network preference for a user profile. - * obj = Pair - */ - private static final int EVENT_SET_PROFILE_NETWORK_PREFERENCE = 50; - - /** - * Event to specify that reasons for why an uid is blocked changed. - * arg1 = uid - * arg2 = blockedReasons - */ - private static final int EVENT_UID_BLOCKED_REASON_CHANGED = 51; - - /** - * Event to register a new network offer - * obj = NetworkOffer - */ - private static final int EVENT_REGISTER_NETWORK_OFFER = 52; - - /** - * Event to unregister an existing network offer - * obj = INetworkOfferCallback - */ - private static final int EVENT_UNREGISTER_NETWORK_OFFER = 53; - - /** - * Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification - * should be shown. - */ - private static final int PROVISIONING_NOTIFICATION_SHOW = 1; - - /** - * Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification - * should be hidden. - */ - private static final int PROVISIONING_NOTIFICATION_HIDE = 0; - - private static String eventName(int what) { - return sMagicDecoderRing.get(what, Integer.toString(what)); - } - - private static IDnsResolver getDnsResolver(Context context) { - final DnsResolverServiceManager dsm = context.getSystemService( - DnsResolverServiceManager.class); - return IDnsResolver.Stub.asInterface(dsm.getService()); - } - - /** Handler thread used for all of the handlers below. */ - @VisibleForTesting - protected final HandlerThread mHandlerThread; - /** Handler used for internal events. */ - final private InternalHandler mHandler; - /** Handler used for incoming {@link NetworkStateTracker} events. */ - final private NetworkStateTrackerHandler mTrackerHandler; - /** Handler used for processing {@link android.net.ConnectivityDiagnosticsManager} events */ - @VisibleForTesting - final ConnectivityDiagnosticsHandler mConnectivityDiagnosticsHandler; - - private final DnsManager mDnsManager; - private final NetworkRanker mNetworkRanker; - - private boolean mSystemReady; - private Intent mInitialBroadcast; - - private PowerManager.WakeLock mNetTransitionWakeLock; - private final PowerManager.WakeLock mPendingIntentWakeLock; - - // A helper object to track the current default HTTP proxy. ConnectivityService needs to tell - // the world when it changes. - @VisibleForTesting - protected final ProxyTracker mProxyTracker; - - final private SettingsObserver mSettingsObserver; - - private UserManager mUserManager; - - // the set of network types that can only be enabled by system/sig apps - private List mProtectedNetworks; - - private Set mWolSupportedInterfaces; - - private final TelephonyManager mTelephonyManager; - private final AppOpsManager mAppOpsManager; - - private final LocationPermissionChecker mLocationPermissionChecker; - - private KeepaliveTracker mKeepaliveTracker; - private QosCallbackTracker mQosCallbackTracker; - private NetworkNotificationManager mNotifier; - private LingerMonitor mLingerMonitor; - - // sequence number of NetworkRequests - private int mNextNetworkRequestId = NetworkRequest.FIRST_REQUEST_ID; - - // Sequence number for NetworkProvider IDs. - private final AtomicInteger mNextNetworkProviderId = new AtomicInteger( - NetworkProvider.FIRST_PROVIDER_ID); - - // NetworkRequest activity String log entries. - private static final int MAX_NETWORK_REQUEST_LOGS = 20; - private final LocalLog mNetworkRequestInfoLogs = new LocalLog(MAX_NETWORK_REQUEST_LOGS); - - // NetworkInfo blocked and unblocked String log entries - private static final int MAX_NETWORK_INFO_LOGS = 40; - private final LocalLog mNetworkInfoBlockingLogs = new LocalLog(MAX_NETWORK_INFO_LOGS); - - private static final int MAX_WAKELOCK_LOGS = 20; - private final LocalLog mWakelockLogs = new LocalLog(MAX_WAKELOCK_LOGS); - private int mTotalWakelockAcquisitions = 0; - private int mTotalWakelockReleases = 0; - private long mTotalWakelockDurationMs = 0; - private long mMaxWakelockDurationMs = 0; - private long mLastWakeLockAcquireTimestamp = 0; - - private final IpConnectivityLog mMetricsLog; - - @GuardedBy("mBandwidthRequests") - private final SparseArray mBandwidthRequests = new SparseArray(10); - - @VisibleForTesting - final MultinetworkPolicyTracker mMultinetworkPolicyTracker; - - @VisibleForTesting - final Map mConnectivityDiagnosticsCallbacks = - new HashMap<>(); - - /** - * Implements support for the legacy "one network per network type" model. - * - * We used to have a static array of NetworkStateTrackers, one for each - * network type, but that doesn't work any more now that we can have, - * for example, more that one wifi network. This class stores all the - * NetworkAgentInfo objects that support a given type, but the legacy - * API will only see the first one. - * - * It serves two main purposes: - * - * 1. Provide information about "the network for a given type" (since this - * API only supports one). - * 2. Send legacy connectivity change broadcasts. Broadcasts are sent if - * the first network for a given type changes, or if the default network - * changes. - */ - @VisibleForTesting - static class LegacyTypeTracker { - - private static final boolean DBG = true; - private static final boolean VDBG = false; - - /** - * Array of lists, one per legacy network type (e.g., TYPE_MOBILE_MMS). - * Each list holds references to all NetworkAgentInfos that are used to - * satisfy requests for that network type. - * - * This array is built out at startup such that an unsupported network - * doesn't get an ArrayList instance, making this a tristate: - * unsupported, supported but not active and active. - * - * The actual lists are populated when we scan the network types that - * are supported on this device. - * - * Threading model: - * - addSupportedType() is only called in the constructor - * - add(), update(), remove() are only called from the ConnectivityService handler thread. - * They are therefore not thread-safe with respect to each other. - * - getNetworkForType() can be called at any time on binder threads. It is synchronized - * on mTypeLists to be thread-safe with respect to a concurrent remove call. - * - getRestoreTimerForType(type) is also synchronized on mTypeLists. - * - dump is thread-safe with respect to concurrent add and remove calls. - */ - private final ArrayList mTypeLists[]; - @NonNull - private final ConnectivityService mService; - - // Restore timers for requestNetworkForFeature (network type -> timer in ms). Types without - // an entry have no timer (equivalent to -1). Lazily loaded. - @NonNull - private ArrayMap mRestoreTimers = new ArrayMap<>(); - - LegacyTypeTracker(@NonNull ConnectivityService service) { - mService = service; - mTypeLists = new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE + 1]; - } - - public void loadSupportedTypes(@NonNull Context ctx, @NonNull TelephonyManager tm) { - final PackageManager pm = ctx.getPackageManager(); - if (pm.hasSystemFeature(FEATURE_WIFI)) { - addSupportedType(TYPE_WIFI); - } - if (pm.hasSystemFeature(FEATURE_WIFI_DIRECT)) { - addSupportedType(TYPE_WIFI_P2P); - } - if (tm.isDataCapable()) { - // Telephony does not have granular support for these types: they are either all - // supported, or none is supported - addSupportedType(TYPE_MOBILE); - addSupportedType(TYPE_MOBILE_MMS); - addSupportedType(TYPE_MOBILE_SUPL); - addSupportedType(TYPE_MOBILE_DUN); - addSupportedType(TYPE_MOBILE_HIPRI); - addSupportedType(TYPE_MOBILE_FOTA); - addSupportedType(TYPE_MOBILE_IMS); - addSupportedType(TYPE_MOBILE_CBS); - addSupportedType(TYPE_MOBILE_IA); - addSupportedType(TYPE_MOBILE_EMERGENCY); - } - if (pm.hasSystemFeature(FEATURE_BLUETOOTH)) { - addSupportedType(TYPE_BLUETOOTH); - } - if (pm.hasSystemFeature(FEATURE_WATCH)) { - // TYPE_PROXY is only used on Wear - addSupportedType(TYPE_PROXY); - } - // Ethernet is often not specified in the configs, although many devices can use it via - // USB host adapters. Add it as long as the ethernet service is here. - if (ctx.getSystemService(Context.ETHERNET_SERVICE) != null) { - addSupportedType(TYPE_ETHERNET); - } - - // Always add TYPE_VPN as a supported type - addSupportedType(TYPE_VPN); - } - - private void addSupportedType(int type) { - if (mTypeLists[type] != null) { - throw new IllegalStateException( - "legacy list for type " + type + "already initialized"); - } - mTypeLists[type] = new ArrayList<>(); - } - - public boolean isTypeSupported(int type) { - return isNetworkTypeValid(type) && mTypeLists[type] != null; - } - - public NetworkAgentInfo getNetworkForType(int type) { - synchronized (mTypeLists) { - if (isTypeSupported(type) && !mTypeLists[type].isEmpty()) { - return mTypeLists[type].get(0); - } - } - return null; - } - - public int getRestoreTimerForType(int type) { - synchronized (mTypeLists) { - if (mRestoreTimers == null) { - mRestoreTimers = loadRestoreTimers(); - } - return mRestoreTimers.getOrDefault(type, -1); - } - } - - private ArrayMap loadRestoreTimers() { - final String[] configs = mService.mResources.get().getStringArray( - R.array.config_legacy_networktype_restore_timers); - final ArrayMap ret = new ArrayMap<>(configs.length); - for (final String config : configs) { - final String[] splits = TextUtils.split(config, ","); - if (splits.length != 2) { - logwtf("Invalid restore timer token count: " + config); - continue; - } - try { - ret.put(Integer.parseInt(splits[0]), Integer.parseInt(splits[1])); - } catch (NumberFormatException e) { - logwtf("Invalid restore timer number format: " + config, e); - } - } - return ret; - } - - private void maybeLogBroadcast(NetworkAgentInfo nai, DetailedState state, int type, - boolean isDefaultNetwork) { - if (DBG) { - log("Sending " + state - + " broadcast for type " + type + " " + nai.toShortString() - + " isDefaultNetwork=" + isDefaultNetwork); - } - } - - // When a lockdown VPN connects, send another CONNECTED broadcast for the underlying - // network type, to preserve previous behaviour. - private void maybeSendLegacyLockdownBroadcast(@NonNull NetworkAgentInfo vpnNai) { - if (vpnNai != mService.getLegacyLockdownNai()) return; - - if (vpnNai.declaredUnderlyingNetworks == null - || vpnNai.declaredUnderlyingNetworks.length != 1) { - Log.wtf(TAG, "Legacy lockdown VPN must have exactly one underlying network: " - + Arrays.toString(vpnNai.declaredUnderlyingNetworks)); - return; - } - final NetworkAgentInfo underlyingNai = mService.getNetworkAgentInfoForNetwork( - vpnNai.declaredUnderlyingNetworks[0]); - if (underlyingNai == null) return; - - final int type = underlyingNai.networkInfo.getType(); - final DetailedState state = DetailedState.CONNECTED; - maybeLogBroadcast(underlyingNai, state, type, true /* isDefaultNetwork */); - mService.sendLegacyNetworkBroadcast(underlyingNai, state, type); - } - - /** Adds the given network to the specified legacy type list. */ - public void add(int type, NetworkAgentInfo nai) { - if (!isTypeSupported(type)) { - return; // Invalid network type. - } - if (VDBG) log("Adding agent " + nai + " for legacy network type " + type); - - ArrayList list = mTypeLists[type]; - if (list.contains(nai)) { - return; - } - synchronized (mTypeLists) { - list.add(nai); - } - - // Send a broadcast if this is the first network of its type or if it's the default. - final boolean isDefaultNetwork = mService.isDefaultNetwork(nai); - - // If a legacy lockdown VPN is active, override the NetworkInfo state in all broadcasts - // to preserve previous behaviour. - final DetailedState state = mService.getLegacyLockdownState(DetailedState.CONNECTED); - if ((list.size() == 1) || isDefaultNetwork) { - maybeLogBroadcast(nai, state, type, isDefaultNetwork); - mService.sendLegacyNetworkBroadcast(nai, state, type); - } - - if (type == TYPE_VPN && state == DetailedState.CONNECTED) { - maybeSendLegacyLockdownBroadcast(nai); - } - } - - /** Removes the given network from the specified legacy type list. */ - public void remove(int type, NetworkAgentInfo nai, boolean wasDefault) { - ArrayList list = mTypeLists[type]; - if (list == null || list.isEmpty()) { - return; - } - final boolean wasFirstNetwork = list.get(0).equals(nai); - - synchronized (mTypeLists) { - if (!list.remove(nai)) { - return; - } - } - - if (wasFirstNetwork || wasDefault) { - maybeLogBroadcast(nai, DetailedState.DISCONNECTED, type, wasDefault); - mService.sendLegacyNetworkBroadcast(nai, DetailedState.DISCONNECTED, type); - } - - if (!list.isEmpty() && wasFirstNetwork) { - if (DBG) log("Other network available for type " + type + - ", sending connected broadcast"); - final NetworkAgentInfo replacement = list.get(0); - maybeLogBroadcast(replacement, DetailedState.CONNECTED, type, - mService.isDefaultNetwork(replacement)); - mService.sendLegacyNetworkBroadcast(replacement, DetailedState.CONNECTED, type); - } - } - - /** Removes the given network from all legacy type lists. */ - public void remove(NetworkAgentInfo nai, boolean wasDefault) { - if (VDBG) log("Removing agent " + nai + " wasDefault=" + wasDefault); - for (int type = 0; type < mTypeLists.length; type++) { - remove(type, nai, wasDefault); - } - } - - // send out another legacy broadcast - currently only used for suspend/unsuspend - // toggle - public void update(NetworkAgentInfo nai) { - final boolean isDefault = mService.isDefaultNetwork(nai); - final DetailedState state = nai.networkInfo.getDetailedState(); - for (int type = 0; type < mTypeLists.length; type++) { - final ArrayList list = mTypeLists[type]; - final boolean contains = (list != null && list.contains(nai)); - final boolean isFirst = contains && (nai == list.get(0)); - if (isFirst || contains && isDefault) { - maybeLogBroadcast(nai, state, type, isDefault); - mService.sendLegacyNetworkBroadcast(nai, state, type); - } - } - } - - public void dump(IndentingPrintWriter pw) { - pw.println("mLegacyTypeTracker:"); - pw.increaseIndent(); - pw.print("Supported types:"); - for (int type = 0; type < mTypeLists.length; type++) { - if (mTypeLists[type] != null) pw.print(" " + type); - } - pw.println(); - pw.println("Current state:"); - pw.increaseIndent(); - synchronized (mTypeLists) { - for (int type = 0; type < mTypeLists.length; type++) { - if (mTypeLists[type] == null || mTypeLists[type].isEmpty()) continue; - for (NetworkAgentInfo nai : mTypeLists[type]) { - pw.println(type + " " + nai.toShortString()); - } - } - } - pw.decreaseIndent(); - pw.decreaseIndent(); - pw.println(); - } - } - private final LegacyTypeTracker mLegacyTypeTracker = new LegacyTypeTracker(this); - - final LocalPriorityDump mPriorityDumper = new LocalPriorityDump(); - /** - * Helper class which parses out priority arguments and dumps sections according to their - * priority. If priority arguments are omitted, function calls the legacy dump command. - */ - private class LocalPriorityDump { - private static final String PRIORITY_ARG = "--dump-priority"; - private static final String PRIORITY_ARG_HIGH = "HIGH"; - private static final String PRIORITY_ARG_NORMAL = "NORMAL"; - - LocalPriorityDump() {} - - private void dumpHigh(FileDescriptor fd, PrintWriter pw) { - doDump(fd, pw, new String[] {DIAG_ARG}); - doDump(fd, pw, new String[] {SHORT_ARG}); - } - - private void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args) { - doDump(fd, pw, args); - } - - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (args == null) { - dumpNormal(fd, pw, args); - return; - } - - String priority = null; - for (int argIndex = 0; argIndex < args.length; argIndex++) { - if (args[argIndex].equals(PRIORITY_ARG) && argIndex + 1 < args.length) { - argIndex++; - priority = args[argIndex]; - } - } - - if (PRIORITY_ARG_HIGH.equals(priority)) { - dumpHigh(fd, pw); - } else if (PRIORITY_ARG_NORMAL.equals(priority)) { - dumpNormal(fd, pw, args); - } else { - // ConnectivityService publishes binder service using publishBinderService() with - // no priority assigned will be treated as NORMAL priority. Dumpsys does not send - // "--dump-priority" arguments to the service. Thus, dump NORMAL only to align the - // legacy output for dumpsys connectivity. - // TODO: Integrate into signal dump. - dumpNormal(fd, pw, args); - } - } - } - - /** - * Keeps track of the number of requests made under different uids. - */ - public static class PerUidCounter { - private final int mMaxCountPerUid; - - // Map from UID to number of NetworkRequests that UID has filed. - @VisibleForTesting - @GuardedBy("mUidToNetworkRequestCount") - final SparseIntArray mUidToNetworkRequestCount = new SparseIntArray(); - - /** - * Constructor - * - * @param maxCountPerUid the maximum count per uid allowed - */ - public PerUidCounter(final int maxCountPerUid) { - mMaxCountPerUid = maxCountPerUid; - } - - /** - * Increments the request count of the given uid. Throws an exception if the number - * of open requests for the uid exceeds the value of maxCounterPerUid which is the value - * passed into the constructor. see: {@link #PerUidCounter(int)}. - * - * @throws ServiceSpecificException with - * {@link ConnectivityManager.Errors.TOO_MANY_REQUESTS} if the number of requests for - * the uid exceed the allowed number. - * - * @param uid the uid that the request was made under - */ - public void incrementCountOrThrow(final int uid) { - synchronized (mUidToNetworkRequestCount) { - incrementCountOrThrow(uid, 1 /* numToIncrement */); - } - } - - private void incrementCountOrThrow(final int uid, final int numToIncrement) { - final int newRequestCount = - mUidToNetworkRequestCount.get(uid, 0) + numToIncrement; - if (newRequestCount >= mMaxCountPerUid) { - throw new ServiceSpecificException( - ConnectivityManager.Errors.TOO_MANY_REQUESTS); - } - mUidToNetworkRequestCount.put(uid, newRequestCount); - } - - /** - * Decrements the request count of the given uid. - * - * @param uid the uid that the request was made under - */ - public void decrementCount(final int uid) { - synchronized (mUidToNetworkRequestCount) { - decrementCount(uid, 1 /* numToDecrement */); - } - } - - private void decrementCount(final int uid, final int numToDecrement) { - final int newRequestCount = - mUidToNetworkRequestCount.get(uid, 0) - numToDecrement; - if (newRequestCount < 0) { - logwtf("BUG: too small request count " + newRequestCount + " for UID " + uid); - } else if (newRequestCount == 0) { - mUidToNetworkRequestCount.delete(uid); - } else { - mUidToNetworkRequestCount.put(uid, newRequestCount); - } - } - - /** - * Used to adjust the request counter for the per-app API flows. Directly adjusting the - * counter is not ideal however in the per-app flows, the nris can't be removed until they - * are used to create the new nris upon set. Therefore the request count limit can be - * artificially hit. This method is used as a workaround for this particular case so that - * the request counts are accounted for correctly. - * @param uid the uid to adjust counts for - * @param numOfNewRequests the new request count to account for - * @param r the runnable to execute - */ - public void transact(final int uid, final int numOfNewRequests, @NonNull final Runnable r) { - // This should only be used on the handler thread as per all current and foreseen - // use-cases. ensureRunningOnConnectivityServiceThread() can't be used because there is - // no ref to the outer ConnectivityService. - synchronized (mUidToNetworkRequestCount) { - final int reqCountOverage = getCallingUidRequestCountOverage(uid, numOfNewRequests); - decrementCount(uid, reqCountOverage); - r.run(); - incrementCountOrThrow(uid, reqCountOverage); - } - } - - private int getCallingUidRequestCountOverage(final int uid, final int numOfNewRequests) { - final int newUidRequestCount = mUidToNetworkRequestCount.get(uid, 0) - + numOfNewRequests; - return newUidRequestCount >= MAX_NETWORK_REQUESTS_PER_SYSTEM_UID - ? newUidRequestCount - (MAX_NETWORK_REQUESTS_PER_SYSTEM_UID - 1) : 0; - } - } - - /** - * Dependencies of ConnectivityService, for injection in tests. - */ - @VisibleForTesting - public static class Dependencies { - public int getCallingUid() { - return Binder.getCallingUid(); - } - - /** - * Get system properties to use in ConnectivityService. - */ - public MockableSystemProperties getSystemProperties() { - return new MockableSystemProperties(); - } - - /** - * Get the {@link ConnectivityResources} to use in ConnectivityService. - */ - public ConnectivityResources getResources(@NonNull Context ctx) { - return new ConnectivityResources(ctx); - } - - /** - * Create a HandlerThread to use in ConnectivityService. - */ - public HandlerThread makeHandlerThread() { - return new HandlerThread("ConnectivityServiceThread"); - } - - /** - * Get a reference to the ModuleNetworkStackClient. - */ - public NetworkStackClientBase getNetworkStack() { - return ModuleNetworkStackClient.getInstance(null); - } - - /** - * @see ProxyTracker - */ - public ProxyTracker makeProxyTracker(@NonNull Context context, - @NonNull Handler connServiceHandler) { - return new ProxyTracker(context, connServiceHandler, EVENT_PROXY_HAS_CHANGED); - } - - /** - * @see NetIdManager - */ - public NetIdManager makeNetIdManager() { - return new NetIdManager(); - } - - /** - * @see NetworkUtils#queryUserAccess(int, int) - */ - public boolean queryUserAccess(int uid, Network network, ConnectivityService cs) { - return cs.queryUserAccess(uid, network); - } - - /** - * Gets the UID that owns a socket connection. Needed because opening SOCK_DIAG sockets - * requires CAP_NET_ADMIN, which the unit tests do not have. - */ - public int getConnectionOwnerUid(int protocol, InetSocketAddress local, - InetSocketAddress remote) { - return InetDiagMessage.getConnectionOwnerUid(protocol, local, remote); - } - - /** - * @see MultinetworkPolicyTracker - */ - public MultinetworkPolicyTracker makeMultinetworkPolicyTracker( - @NonNull Context c, @NonNull Handler h, @NonNull Runnable r) { - return new MultinetworkPolicyTracker(c, h, r); - } - - /** - * @see BatteryStatsManager - */ - public void reportNetworkInterfaceForTransports(Context context, String iface, - int[] transportTypes) { - final BatteryStatsManager batteryStats = - context.getSystemService(BatteryStatsManager.class); - batteryStats.reportNetworkInterfaceForTransports(iface, transportTypes); - } - - public boolean getCellular464XlatEnabled() { - return NetworkProperties.isCellular464XlatEnabled().orElse(true); - } - } - - public ConnectivityService(Context context) { - this(context, getDnsResolver(context), new IpConnectivityLog(), - INetd.Stub.asInterface((IBinder) context.getSystemService(Context.NETD_SERVICE)), - new Dependencies()); - } - - @VisibleForTesting - protected ConnectivityService(Context context, IDnsResolver dnsresolver, - IpConnectivityLog logger, INetd netd, Dependencies deps) { - if (DBG) log("ConnectivityService starting up"); - - mDeps = Objects.requireNonNull(deps, "missing Dependencies"); - mSystemProperties = mDeps.getSystemProperties(); - mNetIdManager = mDeps.makeNetIdManager(); - mContext = Objects.requireNonNull(context, "missing Context"); - mResources = deps.getResources(mContext); - mNetworkRequestCounter = new PerUidCounter(MAX_NETWORK_REQUESTS_PER_UID); - mSystemNetworkRequestCounter = new PerUidCounter(MAX_NETWORK_REQUESTS_PER_SYSTEM_UID); - - mMetricsLog = logger; - mNetworkRanker = new NetworkRanker(); - final NetworkRequest defaultInternetRequest = createDefaultRequest(); - mDefaultRequest = new NetworkRequestInfo( - Process.myUid(), defaultInternetRequest, null, - new Binder(), NetworkCallback.FLAG_INCLUDE_LOCATION_INFO, - null /* attributionTags */); - mNetworkRequests.put(defaultInternetRequest, mDefaultRequest); - mDefaultNetworkRequests.add(mDefaultRequest); - mNetworkRequestInfoLogs.log("REGISTER " + mDefaultRequest); - - mDefaultMobileDataRequest = createDefaultInternetRequestForTransport( - NetworkCapabilities.TRANSPORT_CELLULAR, NetworkRequest.Type.BACKGROUND_REQUEST); - - // The default WiFi request is a background request so that apps using WiFi are - // migrated to a better network (typically ethernet) when one comes up, instead - // of staying on WiFi forever. - mDefaultWifiRequest = createDefaultInternetRequestForTransport( - NetworkCapabilities.TRANSPORT_WIFI, NetworkRequest.Type.BACKGROUND_REQUEST); - - mDefaultVehicleRequest = createAlwaysOnRequestForCapability( - NetworkCapabilities.NET_CAPABILITY_VEHICLE_INTERNAL, - NetworkRequest.Type.BACKGROUND_REQUEST); - - mHandlerThread = mDeps.makeHandlerThread(); - mHandlerThread.start(); - mHandler = new InternalHandler(mHandlerThread.getLooper()); - mTrackerHandler = new NetworkStateTrackerHandler(mHandlerThread.getLooper()); - mConnectivityDiagnosticsHandler = - new ConnectivityDiagnosticsHandler(mHandlerThread.getLooper()); - - mReleasePendingIntentDelayMs = Settings.Secure.getInt(context.getContentResolver(), - ConnectivitySettingsManager.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000); - - mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS); - // TODO: Consider making the timer customizable. - mNascentDelayMs = DEFAULT_NASCENT_DELAY_MS; - - mStatsManager = mContext.getSystemService(NetworkStatsManager.class); - mPolicyManager = mContext.getSystemService(NetworkPolicyManager.class); - mDnsResolver = Objects.requireNonNull(dnsresolver, "missing IDnsResolver"); - mProxyTracker = mDeps.makeProxyTracker(mContext, mHandler); - - mNetd = netd; - mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); - mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); - mLocationPermissionChecker = new LocationPermissionChecker(mContext); - - // To ensure uid state is synchronized with Network Policy, register for - // NetworkPolicyManagerService events must happen prior to NetworkPolicyManagerService - // reading existing policy from disk. - mPolicyManager.registerNetworkPolicyCallback(null, mPolicyCallback); - - final PowerManager powerManager = (PowerManager) context.getSystemService( - Context.POWER_SERVICE); - mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); - mPendingIntentWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); - - mLegacyTypeTracker.loadSupportedTypes(mContext, mTelephonyManager); - mProtectedNetworks = new ArrayList<>(); - int[] protectedNetworks = mResources.get().getIntArray(R.array.config_protectedNetworks); - for (int p : protectedNetworks) { - if (mLegacyTypeTracker.isTypeSupported(p) && !mProtectedNetworks.contains(p)) { - mProtectedNetworks.add(p); - } else { - if (DBG) loge("Ignoring protectedNetwork " + p); - } - } - - mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); - - mPermissionMonitor = new PermissionMonitor(mContext, mNetd); - - mUserAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */); - // Listen for user add/removes to inform PermissionMonitor. - // Should run on mHandler to avoid any races. - final IntentFilter userIntentFilter = new IntentFilter(); - userIntentFilter.addAction(Intent.ACTION_USER_ADDED); - userIntentFilter.addAction(Intent.ACTION_USER_REMOVED); - mUserAllContext.registerReceiver(mUserIntentReceiver, userIntentFilter, - null /* broadcastPermission */, mHandler); - - // Listen to package add/removes for netd - final IntentFilter packageIntentFilter = new IntentFilter(); - packageIntentFilter.addAction(Intent.ACTION_PACKAGE_ADDED); - packageIntentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); - packageIntentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED); - packageIntentFilter.addDataScheme("package"); - mUserAllContext.registerReceiver(mPackageIntentReceiver, packageIntentFilter, - null /* broadcastPermission */, mHandler); - - mNetworkActivityTracker = new LegacyNetworkActivityTracker(mContext, mHandler, mNetd); - - mNetdCallback = new NetdCallback(); - try { - mNetd.registerUnsolicitedEventListener(mNetdCallback); - } catch (RemoteException | ServiceSpecificException e) { - loge("Error registering event listener :" + e); - } - - mSettingsObserver = new SettingsObserver(mContext, mHandler); - registerSettingsCallbacks(); - - mKeepaliveTracker = new KeepaliveTracker(mContext, mHandler); - mNotifier = new NetworkNotificationManager(mContext, mTelephonyManager); - mQosCallbackTracker = new QosCallbackTracker(mHandler, mNetworkRequestCounter); - - final int dailyLimit = Settings.Global.getInt(mContext.getContentResolver(), - ConnectivitySettingsManager.NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT, - LingerMonitor.DEFAULT_NOTIFICATION_DAILY_LIMIT); - final long rateLimit = Settings.Global.getLong(mContext.getContentResolver(), - ConnectivitySettingsManager.NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS, - LingerMonitor.DEFAULT_NOTIFICATION_RATE_LIMIT_MILLIS); - mLingerMonitor = new LingerMonitor(mContext, mNotifier, dailyLimit, rateLimit); - - mMultinetworkPolicyTracker = mDeps.makeMultinetworkPolicyTracker( - mContext, mHandler, () -> updateAvoidBadWifi()); - mMultinetworkPolicyTracker.start(); - - mDnsManager = new DnsManager(mContext, mDnsResolver); - registerPrivateDnsSettingsCallbacks(); - - // This NAI is a sentinel used to offer no service to apps that are on a multi-layer - // request that doesn't allow fallback to the default network. It should never be visible - // to apps. As such, it's not in the list of NAIs and doesn't need many of the normal - // arguments like the handler or the DnsResolver. - // TODO : remove this ; it is probably better handled with a sentinel request. - mNoServiceNetwork = new NetworkAgentInfo(null, - new Network(INetd.UNREACHABLE_NET_ID), - new NetworkInfo(TYPE_NONE, 0, "", ""), - new LinkProperties(), new NetworkCapabilities(), - new NetworkScore.Builder().setLegacyInt(0).build(), mContext, null, - new NetworkAgentConfig(), this, null, null, 0, INVALID_UID, - mLingerDelayMs, mQosCallbackTracker, mDeps); - } - - private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) { - return createDefaultNetworkCapabilitiesForUidRange(new UidRange(uid, uid)); - } - - private static NetworkCapabilities createDefaultNetworkCapabilitiesForUidRange( - @NonNull final UidRange uids) { - final NetworkCapabilities netCap = new NetworkCapabilities(); - netCap.addCapability(NET_CAPABILITY_INTERNET); - netCap.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); - netCap.removeCapability(NET_CAPABILITY_NOT_VPN); - netCap.setUids(UidRange.toIntRanges(Collections.singleton(uids))); - return netCap; - } - - private NetworkRequest createDefaultRequest() { - return createDefaultInternetRequestForTransport( - TYPE_NONE, NetworkRequest.Type.REQUEST); - } - - private NetworkRequest createDefaultInternetRequestForTransport( - int transportType, NetworkRequest.Type type) { - final NetworkCapabilities netCap = new NetworkCapabilities(); - netCap.addCapability(NET_CAPABILITY_INTERNET); - netCap.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); - netCap.setRequestorUidAndPackageName(Process.myUid(), mContext.getPackageName()); - if (transportType > TYPE_NONE) { - netCap.addTransportType(transportType); - } - return createNetworkRequest(type, netCap); - } - - private NetworkRequest createNetworkRequest( - NetworkRequest.Type type, NetworkCapabilities netCap) { - return new NetworkRequest(netCap, TYPE_NONE, nextNetworkRequestId(), type); - } - - private NetworkRequest createAlwaysOnRequestForCapability(int capability, - NetworkRequest.Type type) { - final NetworkCapabilities netCap = new NetworkCapabilities(); - netCap.clearAll(); - netCap.addCapability(capability); - netCap.setRequestorUidAndPackageName(Process.myUid(), mContext.getPackageName()); - return new NetworkRequest(netCap, TYPE_NONE, nextNetworkRequestId(), type); - } - - // Used only for testing. - // TODO: Delete this and either: - // 1. Give FakeSettingsProvider the ability to send settings change notifications (requires - // changing ContentResolver to make registerContentObserver non-final). - // 2. Give FakeSettingsProvider an alternative notification mechanism and have the test use it - // by subclassing SettingsObserver. - @VisibleForTesting - void updateAlwaysOnNetworks() { - mHandler.sendEmptyMessage(EVENT_CONFIGURE_ALWAYS_ON_NETWORKS); - } - - // See FakeSettingsProvider comment above. - @VisibleForTesting - void updatePrivateDnsSettings() { - mHandler.sendEmptyMessage(EVENT_PRIVATE_DNS_SETTINGS_CHANGED); - } - - private void handleAlwaysOnNetworkRequest(NetworkRequest networkRequest, int id) { - final boolean enable = mContext.getResources().getBoolean(id); - handleAlwaysOnNetworkRequest(networkRequest, enable); - } - - private void handleAlwaysOnNetworkRequest( - NetworkRequest networkRequest, String settingName, boolean defaultValue) { - final boolean enable = toBool(Settings.Global.getInt( - mContext.getContentResolver(), settingName, encodeBool(defaultValue))); - handleAlwaysOnNetworkRequest(networkRequest, enable); - } - - private void handleAlwaysOnNetworkRequest(NetworkRequest networkRequest, boolean enable) { - final boolean isEnabled = (mNetworkRequests.get(networkRequest) != null); - if (enable == isEnabled) { - return; // Nothing to do. - } - - if (enable) { - handleRegisterNetworkRequest(new NetworkRequestInfo( - Process.myUid(), networkRequest, null, new Binder(), - NetworkCallback.FLAG_INCLUDE_LOCATION_INFO, - null /* attributionTags */)); - } else { - handleReleaseNetworkRequest(networkRequest, Process.SYSTEM_UID, - /* callOnUnavailable */ false); - } - } - - private void handleConfigureAlwaysOnNetworks() { - handleAlwaysOnNetworkRequest(mDefaultMobileDataRequest, - ConnectivitySettingsManager.MOBILE_DATA_ALWAYS_ON, true /* defaultValue */); - handleAlwaysOnNetworkRequest(mDefaultWifiRequest, - ConnectivitySettingsManager.WIFI_ALWAYS_REQUESTED, false /* defaultValue */); - final boolean vehicleAlwaysRequested = mResources.get().getBoolean( - R.bool.config_vehicleInternalNetworkAlwaysRequested); - handleAlwaysOnNetworkRequest(mDefaultVehicleRequest, vehicleAlwaysRequested); - } - - private void registerSettingsCallbacks() { - // Watch for global HTTP proxy changes. - mSettingsObserver.observe( - Settings.Global.getUriFor(Settings.Global.HTTP_PROXY), - EVENT_APPLY_GLOBAL_HTTP_PROXY); - - // Watch for whether or not to keep mobile data always on. - mSettingsObserver.observe( - Settings.Global.getUriFor(ConnectivitySettingsManager.MOBILE_DATA_ALWAYS_ON), - EVENT_CONFIGURE_ALWAYS_ON_NETWORKS); - - // Watch for whether or not to keep wifi always on. - mSettingsObserver.observe( - Settings.Global.getUriFor(ConnectivitySettingsManager.WIFI_ALWAYS_REQUESTED), - EVENT_CONFIGURE_ALWAYS_ON_NETWORKS); - } - - private void registerPrivateDnsSettingsCallbacks() { - for (Uri uri : DnsManager.getPrivateDnsSettingsUris()) { - mSettingsObserver.observe(uri, EVENT_PRIVATE_DNS_SETTINGS_CHANGED); - } - } - - private synchronized int nextNetworkRequestId() { - // TODO: Consider handle wrapping and exclude {@link NetworkRequest#REQUEST_ID_NONE} if - // doing that. - return mNextNetworkRequestId++; - } - - @VisibleForTesting - protected NetworkAgentInfo getNetworkAgentInfoForNetwork(Network network) { - if (network == null) { - return null; - } - return getNetworkAgentInfoForNetId(network.getNetId()); - } - - private NetworkAgentInfo getNetworkAgentInfoForNetId(int netId) { - synchronized (mNetworkForNetId) { - return mNetworkForNetId.get(netId); - } - } - - // TODO: determine what to do when more than one VPN applies to |uid|. - private NetworkAgentInfo getVpnForUid(int uid) { - synchronized (mNetworkForNetId) { - for (int i = 0; i < mNetworkForNetId.size(); i++) { - final NetworkAgentInfo nai = mNetworkForNetId.valueAt(i); - if (nai.isVPN() && nai.everConnected && nai.networkCapabilities.appliesToUid(uid)) { - return nai; - } - } - } - return null; - } - - private Network[] getVpnUnderlyingNetworks(int uid) { - if (mLockdownEnabled) return null; - final NetworkAgentInfo nai = getVpnForUid(uid); - if (nai != null) return nai.declaredUnderlyingNetworks; - return null; - } - - private NetworkAgentInfo getNetworkAgentInfoForUid(int uid) { - NetworkAgentInfo nai = getDefaultNetworkForUid(uid); - - final Network[] networks = getVpnUnderlyingNetworks(uid); - if (networks != null) { - // getUnderlyingNetworks() returns: - // null => there was no VPN, or the VPN didn't specify anything, so we use the default. - // empty array => the VPN explicitly said "no default network". - // non-empty array => the VPN specified one or more default networks; we use the - // first one. - if (networks.length > 0) { - nai = getNetworkAgentInfoForNetwork(networks[0]); - } else { - nai = null; - } - } - return nai; - } - - /** - * Check if UID should be blocked from using the specified network. - */ - private boolean isNetworkWithCapabilitiesBlocked(@Nullable final NetworkCapabilities nc, - final int uid, final boolean ignoreBlocked) { - // Networks aren't blocked when ignoring blocked status - if (ignoreBlocked) { - return false; - } - if (isUidBlockedByVpn(uid, mVpnBlockedUidRanges)) return true; - final long ident = Binder.clearCallingIdentity(); - try { - final boolean metered = nc == null ? true : nc.isMetered(); - return mPolicyManager.isUidNetworkingBlocked(uid, metered); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - private void maybeLogBlockedNetworkInfo(NetworkInfo ni, int uid) { - if (ni == null || !LOGD_BLOCKED_NETWORKINFO) { - return; - } - final boolean blocked; - synchronized (mBlockedAppUids) { - if (ni.getDetailedState() == DetailedState.BLOCKED && mBlockedAppUids.add(uid)) { - blocked = true; - } else if (ni.isConnected() && mBlockedAppUids.remove(uid)) { - blocked = false; - } else { - return; - } - } - String action = blocked ? "BLOCKED" : "UNBLOCKED"; - log(String.format("Returning %s NetworkInfo to uid=%d", action, uid)); - mNetworkInfoBlockingLogs.log(action + " " + uid); - } - - private void maybeLogBlockedStatusChanged(NetworkRequestInfo nri, Network net, int blocked) { - if (nri == null || net == null || !LOGD_BLOCKED_NETWORKINFO) { - return; - } - final String action = (blocked != 0) ? "BLOCKED" : "UNBLOCKED"; - final int requestId = nri.getActiveRequest() != null - ? nri.getActiveRequest().requestId : nri.mRequests.get(0).requestId; - mNetworkInfoBlockingLogs.log(String.format( - "%s %d(%d) on netId %d: %s", action, nri.mAsUid, requestId, net.getNetId(), - Integer.toHexString(blocked))); - } - - /** - * Apply any relevant filters to the specified {@link NetworkInfo} for the given UID. For - * example, this may mark the network as {@link DetailedState#BLOCKED} based - * on {@link #isNetworkWithCapabilitiesBlocked}. - */ - @NonNull - private NetworkInfo filterNetworkInfo(@NonNull NetworkInfo networkInfo, int type, - @NonNull NetworkCapabilities nc, int uid, boolean ignoreBlocked) { - final NetworkInfo filtered = new NetworkInfo(networkInfo); - // Many legacy types (e.g,. TYPE_MOBILE_HIPRI) are not actually a property of the network - // but only exists if an app asks about them or requests them. Ensure the requesting app - // gets the type it asks for. - filtered.setType(type); - if (isNetworkWithCapabilitiesBlocked(nc, uid, ignoreBlocked)) { - filtered.setDetailedState(DetailedState.BLOCKED, null /* reason */, - null /* extraInfo */); - } - filterForLegacyLockdown(filtered); - return filtered; - } - - private NetworkInfo getFilteredNetworkInfo(NetworkAgentInfo nai, int uid, - boolean ignoreBlocked) { - return filterNetworkInfo(nai.networkInfo, nai.networkInfo.getType(), - nai.networkCapabilities, uid, ignoreBlocked); - } - - /** - * Return NetworkInfo for the active (i.e., connected) network interface. - * It is assumed that at most one network is active at a time. If more - * than one is active, it is indeterminate which will be returned. - * @return the info for the active network, or {@code null} if none is - * active - */ - @Override - public NetworkInfo getActiveNetworkInfo() { - enforceAccessPermission(); - final int uid = mDeps.getCallingUid(); - final NetworkAgentInfo nai = getNetworkAgentInfoForUid(uid); - if (nai == null) return null; - final NetworkInfo networkInfo = getFilteredNetworkInfo(nai, uid, false); - maybeLogBlockedNetworkInfo(networkInfo, uid); - return networkInfo; - } - - @Override - public Network getActiveNetwork() { - enforceAccessPermission(); - return getActiveNetworkForUidInternal(mDeps.getCallingUid(), false); - } - - @Override - public Network getActiveNetworkForUid(int uid, boolean ignoreBlocked) { - PermissionUtils.enforceNetworkStackPermission(mContext); - return getActiveNetworkForUidInternal(uid, ignoreBlocked); - } - - private Network getActiveNetworkForUidInternal(final int uid, boolean ignoreBlocked) { - final NetworkAgentInfo vpnNai = getVpnForUid(uid); - if (vpnNai != null) { - final NetworkCapabilities requiredCaps = createDefaultNetworkCapabilitiesForUid(uid); - if (requiredCaps.satisfiedByNetworkCapabilities(vpnNai.networkCapabilities)) { - return vpnNai.network; - } - } - - NetworkAgentInfo nai = getDefaultNetworkForUid(uid); - if (nai == null || isNetworkWithCapabilitiesBlocked(nai.networkCapabilities, uid, - ignoreBlocked)) { - return null; - } - return nai.network; - } - - @Override - public NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked) { - PermissionUtils.enforceNetworkStackPermission(mContext); - final NetworkAgentInfo nai = getNetworkAgentInfoForUid(uid); - if (nai == null) return null; - return getFilteredNetworkInfo(nai, uid, ignoreBlocked); - } - - /** Returns a NetworkInfo object for a network that doesn't exist. */ - private NetworkInfo makeFakeNetworkInfo(int networkType, int uid) { - final NetworkInfo info = new NetworkInfo(networkType, 0 /* subtype */, - getNetworkTypeName(networkType), "" /* subtypeName */); - info.setIsAvailable(true); - // For compatibility with legacy code, return BLOCKED instead of DISCONNECTED when - // background data is restricted. - final NetworkCapabilities nc = new NetworkCapabilities(); // Metered. - final DetailedState state = isNetworkWithCapabilitiesBlocked(nc, uid, false) - ? DetailedState.BLOCKED - : DetailedState.DISCONNECTED; - info.setDetailedState(state, null /* reason */, null /* extraInfo */); - filterForLegacyLockdown(info); - return info; - } - - private NetworkInfo getFilteredNetworkInfoForType(int networkType, int uid) { - if (!mLegacyTypeTracker.isTypeSupported(networkType)) { - return null; - } - final NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType); - if (nai == null) { - return makeFakeNetworkInfo(networkType, uid); - } - return filterNetworkInfo(nai.networkInfo, networkType, nai.networkCapabilities, uid, - false); - } - - @Override - public NetworkInfo getNetworkInfo(int networkType) { - enforceAccessPermission(); - final int uid = mDeps.getCallingUid(); - if (getVpnUnderlyingNetworks(uid) != null) { - // A VPN is active, so we may need to return one of its underlying networks. This - // information is not available in LegacyTypeTracker, so we have to get it from - // getNetworkAgentInfoForUid. - final NetworkAgentInfo nai = getNetworkAgentInfoForUid(uid); - if (nai == null) return null; - final NetworkInfo networkInfo = getFilteredNetworkInfo(nai, uid, false); - if (networkInfo.getType() == networkType) { - return networkInfo; - } - } - return getFilteredNetworkInfoForType(networkType, uid); - } - - @Override - public NetworkInfo getNetworkInfoForUid(Network network, int uid, boolean ignoreBlocked) { - enforceAccessPermission(); - final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network); - if (nai == null) return null; - return getFilteredNetworkInfo(nai, uid, ignoreBlocked); - } - - @Override - public NetworkInfo[] getAllNetworkInfo() { - enforceAccessPermission(); - final ArrayList result = new ArrayList<>(); - for (int networkType = 0; networkType <= ConnectivityManager.MAX_NETWORK_TYPE; - networkType++) { - NetworkInfo info = getNetworkInfo(networkType); - if (info != null) { - result.add(info); - } - } - return result.toArray(new NetworkInfo[result.size()]); - } - - @Override - public Network getNetworkForType(int networkType) { - enforceAccessPermission(); - if (!mLegacyTypeTracker.isTypeSupported(networkType)) { - return null; - } - final NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType); - if (nai == null) { - return null; - } - final int uid = mDeps.getCallingUid(); - if (isNetworkWithCapabilitiesBlocked(nai.networkCapabilities, uid, false)) { - return null; - } - return nai.network; - } - - @Override - public Network[] getAllNetworks() { - enforceAccessPermission(); - synchronized (mNetworkForNetId) { - final Network[] result = new Network[mNetworkForNetId.size()]; - for (int i = 0; i < mNetworkForNetId.size(); i++) { - result[i] = mNetworkForNetId.valueAt(i).network; - } - return result; - } - } - - @Override - public NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser( - int userId, String callingPackageName, @Nullable String callingAttributionTag) { - // The basic principle is: if an app's traffic could possibly go over a - // network, without the app doing anything multinetwork-specific, - // (hence, by "default"), then include that network's capabilities in - // the array. - // - // In the normal case, app traffic only goes over the system's default - // network connection, so that's the only network returned. - // - // With a VPN in force, some app traffic may go into the VPN, and thus - // over whatever underlying networks the VPN specifies, while other app - // traffic may go over the system default network (e.g.: a split-tunnel - // VPN, or an app disallowed by the VPN), so the set of networks - // returned includes the VPN's underlying networks and the system - // default. - enforceAccessPermission(); - - HashMap result = new HashMap<>(); - - for (final NetworkRequestInfo nri : mDefaultNetworkRequests) { - if (!nri.isBeingSatisfied()) { - continue; - } - final NetworkAgentInfo nai = nri.getSatisfier(); - final NetworkCapabilities nc = getNetworkCapabilitiesInternal(nai); - if (null != nc - && nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) - && !result.containsKey(nai.network)) { - result.put( - nai.network, - createWithLocationInfoSanitizedIfNecessaryWhenParceled( - nc, false /* includeLocationSensitiveInfo */, - getCallingPid(), mDeps.getCallingUid(), callingPackageName, - callingAttributionTag)); - } - } - - // No need to check mLockdownEnabled. If it's true, getVpnUnderlyingNetworks returns null. - final Network[] networks = getVpnUnderlyingNetworks(mDeps.getCallingUid()); - if (null != networks) { - for (final Network network : networks) { - final NetworkCapabilities nc = getNetworkCapabilitiesInternal(network); - if (null != nc) { - result.put( - network, - createWithLocationInfoSanitizedIfNecessaryWhenParceled( - nc, - false /* includeLocationSensitiveInfo */, - getCallingPid(), mDeps.getCallingUid(), callingPackageName, - callingAttributionTag)); - } - } - } - - NetworkCapabilities[] out = new NetworkCapabilities[result.size()]; - out = result.values().toArray(out); - return out; - } - - @Override - public boolean isNetworkSupported(int networkType) { - enforceAccessPermission(); - return mLegacyTypeTracker.isTypeSupported(networkType); - } - - /** - * Return LinkProperties for the active (i.e., connected) default - * network interface for the calling uid. - * @return the ip properties for the active network, or {@code null} if - * none is active - */ - @Override - public LinkProperties getActiveLinkProperties() { - enforceAccessPermission(); - final int uid = mDeps.getCallingUid(); - NetworkAgentInfo nai = getNetworkAgentInfoForUid(uid); - if (nai == null) return null; - return linkPropertiesRestrictedForCallerPermissions(nai.linkProperties, - Binder.getCallingPid(), uid); - } - - @Override - public LinkProperties getLinkPropertiesForType(int networkType) { - enforceAccessPermission(); - NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType); - final LinkProperties lp = getLinkProperties(nai); - if (lp == null) return null; - return linkPropertiesRestrictedForCallerPermissions( - lp, Binder.getCallingPid(), mDeps.getCallingUid()); - } - - // TODO - this should be ALL networks - @Override - public LinkProperties getLinkProperties(Network network) { - enforceAccessPermission(); - final LinkProperties lp = getLinkProperties(getNetworkAgentInfoForNetwork(network)); - if (lp == null) return null; - return linkPropertiesRestrictedForCallerPermissions( - lp, Binder.getCallingPid(), mDeps.getCallingUid()); - } - - @Nullable - private LinkProperties getLinkProperties(@Nullable NetworkAgentInfo nai) { - if (nai == null) { - return null; - } - synchronized (nai) { - return nai.linkProperties; - } - } - - private NetworkCapabilities getNetworkCapabilitiesInternal(Network network) { - return getNetworkCapabilitiesInternal(getNetworkAgentInfoForNetwork(network)); - } - - private NetworkCapabilities getNetworkCapabilitiesInternal(NetworkAgentInfo nai) { - if (nai == null) return null; - synchronized (nai) { - return networkCapabilitiesRestrictedForCallerPermissions( - nai.networkCapabilities, Binder.getCallingPid(), mDeps.getCallingUid()); - } - } - - @Override - public NetworkCapabilities getNetworkCapabilities(Network network, String callingPackageName, - @Nullable String callingAttributionTag) { - mAppOpsManager.checkPackage(mDeps.getCallingUid(), callingPackageName); - enforceAccessPermission(); - return createWithLocationInfoSanitizedIfNecessaryWhenParceled( - getNetworkCapabilitiesInternal(network), - false /* includeLocationSensitiveInfo */, - getCallingPid(), mDeps.getCallingUid(), callingPackageName, callingAttributionTag); - } - - @VisibleForTesting - NetworkCapabilities networkCapabilitiesRestrictedForCallerPermissions( - NetworkCapabilities nc, int callerPid, int callerUid) { - final NetworkCapabilities newNc = new NetworkCapabilities(nc); - if (!checkSettingsPermission(callerPid, callerUid)) { - newNc.setUids(null); - newNc.setSSID(null); - } - if (newNc.getNetworkSpecifier() != null) { - newNc.setNetworkSpecifier(newNc.getNetworkSpecifier().redact()); - } - newNc.setAdministratorUids(new int[0]); - if (!checkAnyPermissionOf( - callerPid, callerUid, android.Manifest.permission.NETWORK_FACTORY)) { - newNc.setSubscriptionIds(Collections.emptySet()); - } - - return newNc; - } - - /** - * Wrapper used to cache the permission check results performed for the corresponding - * app. This avoid performing multiple permission checks for different fields in - * NetworkCapabilities. - * Note: This wrapper does not support any sort of invalidation and thus must not be - * persistent or long-lived. It may only be used for the time necessary to - * compute the redactions required by one particular NetworkCallback or - * synchronous call. - */ - private class RedactionPermissionChecker { - private final int mCallingPid; - private final int mCallingUid; - @NonNull private final String mCallingPackageName; - @Nullable private final String mCallingAttributionTag; - - private Boolean mHasLocationPermission = null; - private Boolean mHasLocalMacAddressPermission = null; - private Boolean mHasSettingsPermission = null; - - RedactionPermissionChecker(int callingPid, int callingUid, - @NonNull String callingPackageName, @Nullable String callingAttributionTag) { - mCallingPid = callingPid; - mCallingUid = callingUid; - mCallingPackageName = callingPackageName; - mCallingAttributionTag = callingAttributionTag; - } - - private boolean hasLocationPermissionInternal() { - final long token = Binder.clearCallingIdentity(); - try { - return mLocationPermissionChecker.checkLocationPermission( - mCallingPackageName, mCallingAttributionTag, mCallingUid, - null /* message */); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - /** - * Returns whether the app holds location permission or not (might return cached result - * if the permission was already checked before). - */ - public boolean hasLocationPermission() { - if (mHasLocationPermission == null) { - // If there is no cached result, perform the check now. - mHasLocationPermission = hasLocationPermissionInternal(); - } - return mHasLocationPermission; - } - - /** - * Returns whether the app holds local mac address permission or not (might return cached - * result if the permission was already checked before). - */ - public boolean hasLocalMacAddressPermission() { - if (mHasLocalMacAddressPermission == null) { - // If there is no cached result, perform the check now. - mHasLocalMacAddressPermission = - checkLocalMacAddressPermission(mCallingPid, mCallingUid); - } - return mHasLocalMacAddressPermission; - } - - /** - * Returns whether the app holds settings permission or not (might return cached - * result if the permission was already checked before). - */ - public boolean hasSettingsPermission() { - if (mHasSettingsPermission == null) { - // If there is no cached result, perform the check now. - mHasSettingsPermission = checkSettingsPermission(mCallingPid, mCallingUid); - } - return mHasSettingsPermission; - } - } - - private static boolean shouldRedact(@NetworkCapabilities.RedactionType long redactions, - @NetworkCapabilities.NetCapability long redaction) { - return (redactions & redaction) != 0; - } - - /** - * Use the provided |applicableRedactions| to check the receiving app's - * permissions and clear/set the corresponding bit in the returned bitmask. The bitmask - * returned will be used to ensure the necessary redactions are performed by NetworkCapabilities - * before being sent to the corresponding app. - */ - private @NetworkCapabilities.RedactionType long retrieveRequiredRedactions( - @NetworkCapabilities.RedactionType long applicableRedactions, - @NonNull RedactionPermissionChecker redactionPermissionChecker, - boolean includeLocationSensitiveInfo) { - long redactions = applicableRedactions; - if (shouldRedact(redactions, REDACT_FOR_ACCESS_FINE_LOCATION)) { - if (includeLocationSensitiveInfo - && redactionPermissionChecker.hasLocationPermission()) { - redactions &= ~REDACT_FOR_ACCESS_FINE_LOCATION; - } - } - if (shouldRedact(redactions, REDACT_FOR_LOCAL_MAC_ADDRESS)) { - if (redactionPermissionChecker.hasLocalMacAddressPermission()) { - redactions &= ~REDACT_FOR_LOCAL_MAC_ADDRESS; - } - } - if (shouldRedact(redactions, REDACT_FOR_NETWORK_SETTINGS)) { - if (redactionPermissionChecker.hasSettingsPermission()) { - redactions &= ~REDACT_FOR_NETWORK_SETTINGS; - } - } - return redactions; - } - - @VisibleForTesting - @Nullable - NetworkCapabilities createWithLocationInfoSanitizedIfNecessaryWhenParceled( - @Nullable NetworkCapabilities nc, boolean includeLocationSensitiveInfo, - int callingPid, int callingUid, @NonNull String callingPkgName, - @Nullable String callingAttributionTag) { - if (nc == null) { - return null; - } - // Avoid doing location permission check if the transport info has no location sensitive - // data. - final RedactionPermissionChecker redactionPermissionChecker = - new RedactionPermissionChecker(callingPid, callingUid, callingPkgName, - callingAttributionTag); - final long redactions = retrieveRequiredRedactions( - nc.getApplicableRedactions(), redactionPermissionChecker, - includeLocationSensitiveInfo); - final NetworkCapabilities newNc = new NetworkCapabilities(nc, redactions); - // Reset owner uid if not destined for the owner app. - if (callingUid != nc.getOwnerUid()) { - newNc.setOwnerUid(INVALID_UID); - return newNc; - } - // Allow VPNs to see ownership of their own VPN networks - not location sensitive. - if (nc.hasTransport(TRANSPORT_VPN)) { - // Owner UIDs already checked above. No need to re-check. - return newNc; - } - // If the calling does not want location sensitive data & target SDK >= S, then mask info. - // Else include the owner UID iff the calling has location permission to provide backwards - // compatibility for older apps. - if (!includeLocationSensitiveInfo - && isTargetSdkAtleast( - Build.VERSION_CODES.S, callingUid, callingPkgName)) { - newNc.setOwnerUid(INVALID_UID); - return newNc; - } - // Reset owner uid if the app has no location permission. - if (!redactionPermissionChecker.hasLocationPermission()) { - newNc.setOwnerUid(INVALID_UID); - } - return newNc; - } - - private LinkProperties linkPropertiesRestrictedForCallerPermissions( - LinkProperties lp, int callerPid, int callerUid) { - if (lp == null) return new LinkProperties(); - - // Only do a permission check if sanitization is needed, to avoid unnecessary binder calls. - final boolean needsSanitization = - (lp.getCaptivePortalApiUrl() != null || lp.getCaptivePortalData() != null); - if (!needsSanitization) { - return new LinkProperties(lp); - } - - if (checkSettingsPermission(callerPid, callerUid)) { - return new LinkProperties(lp, true /* parcelSensitiveFields */); - } - - final LinkProperties newLp = new LinkProperties(lp); - // Sensitive fields would not be parceled anyway, but sanitize for consistency before the - // object gets parceled. - newLp.setCaptivePortalApiUrl(null); - newLp.setCaptivePortalData(null); - return newLp; - } - - private void restrictRequestUidsForCallerAndSetRequestorInfo(NetworkCapabilities nc, - int callerUid, String callerPackageName) { - // There is no need to track the effective UID of the request here. If the caller - // lacks the settings permission, the effective UID is the same as the calling ID. - if (!checkSettingsPermission()) { - // Unprivileged apps can only pass in null or their own UID. - if (nc.getUids() == null) { - // If the caller passes in null, the callback will also match networks that do not - // apply to its UID, similarly to what it would see if it called getAllNetworks. - // In this case, redact everything in the request immediately. This ensures that the - // app is not able to get any redacted information by filing an unredacted request - // and observing whether the request matches something. - if (nc.getNetworkSpecifier() != null) { - nc.setNetworkSpecifier(nc.getNetworkSpecifier().redact()); - } - } else { - nc.setSingleUid(callerUid); - } - } - nc.setRequestorUidAndPackageName(callerUid, callerPackageName); - nc.setAdministratorUids(new int[0]); - - // Clear owner UID; this can never come from an app. - nc.setOwnerUid(INVALID_UID); - } - - private void restrictBackgroundRequestForCaller(NetworkCapabilities nc) { - if (!mPermissionMonitor.hasUseBackgroundNetworksPermission(mDeps.getCallingUid())) { - nc.addCapability(NET_CAPABILITY_FOREGROUND); - } - } - - @Override - public @RestrictBackgroundStatus int getRestrictBackgroundStatusByCaller() { - enforceAccessPermission(); - final int callerUid = Binder.getCallingUid(); - final long token = Binder.clearCallingIdentity(); - try { - return mPolicyManager.getRestrictBackgroundStatus(callerUid); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - // TODO: Consider delete this function or turn it into a no-op method. - @Override - public NetworkState[] getAllNetworkState() { - // This contains IMSI details, so make sure the caller is privileged. - PermissionUtils.enforceNetworkStackPermission(mContext); - - final ArrayList result = new ArrayList<>(); - for (NetworkStateSnapshot snapshot : getAllNetworkStateSnapshots()) { - // NetworkStateSnapshot doesn't contain NetworkInfo, so need to fetch it from the - // NetworkAgentInfo. - final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(snapshot.getNetwork()); - if (nai != null && nai.networkInfo.isConnected()) { - result.add(new NetworkState(new NetworkInfo(nai.networkInfo), - snapshot.getLinkProperties(), snapshot.getNetworkCapabilities(), - snapshot.getNetwork(), snapshot.getSubscriberId())); - } - } - return result.toArray(new NetworkState[result.size()]); - } - - @Override - @NonNull - public List getAllNetworkStateSnapshots() { - // This contains IMSI details, so make sure the caller is privileged. - enforceNetworkStackOrSettingsPermission(); - - final ArrayList result = new ArrayList<>(); - for (Network network : getAllNetworks()) { - final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network); - // TODO: Consider include SUSPENDED networks, which should be considered as - // temporary shortage of connectivity of a connected network. - if (nai != null && nai.networkInfo.isConnected()) { - // TODO (b/73321673) : NetworkStateSnapshot contains a copy of the - // NetworkCapabilities, which may contain UIDs of apps to which the - // network applies. Should the UIDs be cleared so as not to leak or - // interfere ? - result.add(nai.getNetworkStateSnapshot()); - } - } - return result; - } - - @Override - public boolean isActiveNetworkMetered() { - enforceAccessPermission(); - - final NetworkCapabilities caps = getNetworkCapabilitiesInternal(getActiveNetwork()); - if (caps != null) { - return !caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); - } else { - // Always return the most conservative value - return true; - } - } - - /** - * Ensures that the system cannot call a particular method. - */ - private boolean disallowedBecauseSystemCaller() { - // TODO: start throwing a SecurityException when GnssLocationProvider stops calling - // requestRouteToHost. In Q, GnssLocationProvider is changed to not call requestRouteToHost - // for devices launched with Q and above. However, existing devices upgrading to Q and - // above must continued to be supported for few more releases. - if (isSystem(mDeps.getCallingUid()) && SystemProperties.getInt( - "ro.product.first_api_level", 0) > Build.VERSION_CODES.P) { - log("This method exists only for app backwards compatibility" - + " and must not be called by system services."); - return true; - } - return false; - } - - /** - * Ensure that a network route exists to deliver traffic to the specified - * host via the specified network interface. - * @param networkType the type of the network over which traffic to the - * specified host is to be routed - * @param hostAddress the IP address of the host to which the route is - * desired - * @return {@code true} on success, {@code false} on failure - */ - @Override - public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress, - String callingPackageName, String callingAttributionTag) { - if (disallowedBecauseSystemCaller()) { - return false; - } - enforceChangePermission(callingPackageName, callingAttributionTag); - if (mProtectedNetworks.contains(networkType)) { - enforceConnectivityRestrictedNetworksPermission(); - } - - InetAddress addr; - try { - addr = InetAddress.getByAddress(hostAddress); - } catch (UnknownHostException e) { - if (DBG) log("requestRouteToHostAddress got " + e.toString()); - return false; - } - - if (!ConnectivityManager.isNetworkTypeValid(networkType)) { - if (DBG) log("requestRouteToHostAddress on invalid network: " + networkType); - return false; - } - - NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType); - if (nai == null) { - if (mLegacyTypeTracker.isTypeSupported(networkType) == false) { - if (DBG) log("requestRouteToHostAddress on unsupported network: " + networkType); - } else { - if (DBG) log("requestRouteToHostAddress on down network: " + networkType); - } - return false; - } - - DetailedState netState; - synchronized (nai) { - netState = nai.networkInfo.getDetailedState(); - } - - if (netState != DetailedState.CONNECTED && netState != DetailedState.CAPTIVE_PORTAL_CHECK) { - if (VDBG) { - log("requestRouteToHostAddress on down network " - + "(" + networkType + ") - dropped" - + " netState=" + netState); - } - return false; - } - - final int uid = mDeps.getCallingUid(); - final long token = Binder.clearCallingIdentity(); - try { - LinkProperties lp; - int netId; - synchronized (nai) { - lp = nai.linkProperties; - netId = nai.network.getNetId(); - } - boolean ok = addLegacyRouteToHost(lp, addr, netId, uid); - if (DBG) { - log("requestRouteToHostAddress " + addr + nai.toShortString() + " ok=" + ok); - } - return ok; - } finally { - Binder.restoreCallingIdentity(token); - } - } - - private boolean addLegacyRouteToHost(LinkProperties lp, InetAddress addr, int netId, int uid) { - RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getAllRoutes(), addr); - if (bestRoute == null) { - bestRoute = RouteInfo.makeHostRoute(addr, lp.getInterfaceName()); - } else { - String iface = bestRoute.getInterface(); - if (bestRoute.getGateway().equals(addr)) { - // if there is no better route, add the implied hostroute for our gateway - bestRoute = RouteInfo.makeHostRoute(addr, iface); - } else { - // if we will connect to this through another route, add a direct route - // to it's gateway - bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway(), iface); - } - } - if (DBG) log("Adding legacy route " + bestRoute + - " for UID/PID " + uid + "/" + Binder.getCallingPid()); - - final String dst = bestRoute.getDestinationLinkAddress().toString(); - final String nextHop = bestRoute.hasGateway() - ? bestRoute.getGateway().getHostAddress() : ""; - try { - mNetd.networkAddLegacyRoute(netId, bestRoute.getInterface(), dst, nextHop , uid); - } catch (RemoteException | ServiceSpecificException e) { - if (DBG) loge("Exception trying to add a route: " + e); - return false; - } - return true; - } - - class DnsResolverUnsolicitedEventCallback extends - IDnsResolverUnsolicitedEventListener.Stub { - @Override - public void onPrivateDnsValidationEvent(final PrivateDnsValidationEventParcel event) { - try { - mHandler.sendMessage(mHandler.obtainMessage( - EVENT_PRIVATE_DNS_VALIDATION_UPDATE, - new PrivateDnsValidationUpdate(event.netId, - InetAddresses.parseNumericAddress(event.ipAddress), - event.hostname, event.validation))); - } catch (IllegalArgumentException e) { - loge("Error parsing ip address in validation event"); - } - } - - @Override - public void onDnsHealthEvent(final DnsHealthEventParcel event) { - NetworkAgentInfo nai = getNetworkAgentInfoForNetId(event.netId); - // Netd event only allow registrants from system. Each NetworkMonitor thread is under - // the caller thread of registerNetworkAgent. Thus, it's not allowed to register netd - // event callback for certain nai. e.g. cellular. Register here to pass to - // NetworkMonitor instead. - // TODO: Move the Dns Event to NetworkMonitor. NetdEventListenerService only allow one - // callback from each caller type. Need to re-factor NetdEventListenerService to allow - // multiple NetworkMonitor registrants. - if (nai != null && nai.satisfies(mDefaultRequest.mRequests.get(0))) { - nai.networkMonitor().notifyDnsResponse(event.healthResult); - } - } - - @Override - public void onNat64PrefixEvent(final Nat64PrefixEventParcel event) { - mHandler.post(() -> handleNat64PrefixEvent(event.netId, event.prefixOperation, - event.prefixAddress, event.prefixLength)); - } - - @Override - public int getInterfaceVersion() { - return this.VERSION; - } - - @Override - public String getInterfaceHash() { - return this.HASH; - } - } - - @VisibleForTesting - protected final DnsResolverUnsolicitedEventCallback mResolverUnsolEventCallback = - new DnsResolverUnsolicitedEventCallback(); - - private void registerDnsResolverUnsolicitedEventListener() { - try { - mDnsResolver.registerUnsolicitedEventListener(mResolverUnsolEventCallback); - } catch (Exception e) { - loge("Error registering DnsResolver unsolicited event callback: " + e); - } - } - - private final NetworkPolicyCallback mPolicyCallback = new NetworkPolicyCallback() { - @Override - public void onUidBlockedReasonChanged(int uid, @BlockedReason int blockedReasons) { - mHandler.sendMessage(mHandler.obtainMessage(EVENT_UID_BLOCKED_REASON_CHANGED, - uid, blockedReasons)); - } - }; - - private void handleUidBlockedReasonChanged(int uid, @BlockedReason int blockedReasons) { - maybeNotifyNetworkBlockedForNewState(uid, blockedReasons); - setUidBlockedReasons(uid, blockedReasons); - } - - private boolean checkAnyPermissionOf(String... permissions) { - for (String permission : permissions) { - if (mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) { - return true; - } - } - return false; - } - - private boolean checkAnyPermissionOf(int pid, int uid, String... permissions) { - for (String permission : permissions) { - if (mContext.checkPermission(permission, pid, uid) == PERMISSION_GRANTED) { - return true; - } - } - return false; - } - - private void enforceAnyPermissionOf(String... permissions) { - if (!checkAnyPermissionOf(permissions)) { - throw new SecurityException("Requires one of the following permissions: " - + String.join(", ", permissions) + "."); - } - } - - private void enforceInternetPermission() { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.INTERNET, - "ConnectivityService"); - } - - private void enforceAccessPermission() { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.ACCESS_NETWORK_STATE, - "ConnectivityService"); - } - - /** - * Performs a strict and comprehensive check of whether a calling package is allowed to - * change the state of network, as the condition differs for pre-M, M+, and - * privileged/preinstalled apps. The caller is expected to have either the - * CHANGE_NETWORK_STATE or the WRITE_SETTINGS permission declared. Either of these - * permissions allow changing network state; WRITE_SETTINGS is a runtime permission and - * can be revoked, but (except in M, excluding M MRs), CHANGE_NETWORK_STATE is a normal - * permission and cannot be revoked. See http://b/23597341 - * - * Note: if the check succeeds because the application holds WRITE_SETTINGS, the operation - * of this app will be updated to the current time. - */ - private void enforceChangePermission(String callingPkg, String callingAttributionTag) { - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.CHANGE_NETWORK_STATE) - == PackageManager.PERMISSION_GRANTED) { - return; - } - - if (callingPkg == null) { - throw new SecurityException("Calling package name is null."); - } - - final AppOpsManager appOpsMgr = mContext.getSystemService(AppOpsManager.class); - final int uid = mDeps.getCallingUid(); - final int mode = appOpsMgr.noteOpNoThrow(AppOpsManager.OPSTR_WRITE_SETTINGS, uid, - callingPkg, callingAttributionTag, null /* message */); - - if (mode == AppOpsManager.MODE_ALLOWED) { - return; - } - - if ((mode == AppOpsManager.MODE_DEFAULT) && (mContext.checkCallingOrSelfPermission( - android.Manifest.permission.WRITE_SETTINGS) == PackageManager.PERMISSION_GRANTED)) { - return; - } - - throw new SecurityException(callingPkg + " was not granted either of these permissions:" - + android.Manifest.permission.CHANGE_NETWORK_STATE + "," - + android.Manifest.permission.WRITE_SETTINGS + "."); - } - - private void enforceSettingsPermission() { - enforceAnyPermissionOf( - android.Manifest.permission.NETWORK_SETTINGS, - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); - } - - private void enforceNetworkFactoryPermission() { - enforceAnyPermissionOf( - android.Manifest.permission.NETWORK_FACTORY, - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); - } - - private void enforceNetworkFactoryOrSettingsPermission() { - enforceAnyPermissionOf( - android.Manifest.permission.NETWORK_SETTINGS, - android.Manifest.permission.NETWORK_FACTORY, - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); - } - - private void enforceNetworkFactoryOrTestNetworksPermission() { - enforceAnyPermissionOf( - android.Manifest.permission.MANAGE_TEST_NETWORKS, - android.Manifest.permission.NETWORK_FACTORY, - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); - } - - private boolean checkSettingsPermission() { - return checkAnyPermissionOf( - android.Manifest.permission.NETWORK_SETTINGS, - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); - } - - private boolean checkSettingsPermission(int pid, int uid) { - return PERMISSION_GRANTED == mContext.checkPermission( - android.Manifest.permission.NETWORK_SETTINGS, pid, uid) - || PERMISSION_GRANTED == mContext.checkPermission( - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, pid, uid); - } - - private void enforceNetworkStackOrSettingsPermission() { - enforceAnyPermissionOf( - android.Manifest.permission.NETWORK_SETTINGS, - android.Manifest.permission.NETWORK_STACK, - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); - } - - private void enforceNetworkStackSettingsOrSetup() { - enforceAnyPermissionOf( - android.Manifest.permission.NETWORK_SETTINGS, - android.Manifest.permission.NETWORK_SETUP_WIZARD, - android.Manifest.permission.NETWORK_STACK, - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); - } - - private void enforceAirplaneModePermission() { - enforceAnyPermissionOf( - android.Manifest.permission.NETWORK_AIRPLANE_MODE, - android.Manifest.permission.NETWORK_SETTINGS, - android.Manifest.permission.NETWORK_SETUP_WIZARD, - android.Manifest.permission.NETWORK_STACK, - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); - } - - private void enforceOemNetworkPreferencesPermission() { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE, - "ConnectivityService"); - } - - private boolean checkNetworkStackPermission() { - return checkAnyPermissionOf( - android.Manifest.permission.NETWORK_STACK, - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); - } - - private boolean checkNetworkStackPermission(int pid, int uid) { - return checkAnyPermissionOf(pid, uid, - android.Manifest.permission.NETWORK_STACK, - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); - } - - private boolean checkNetworkSignalStrengthWakeupPermission(int pid, int uid) { - return checkAnyPermissionOf(pid, uid, - android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP, - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, - android.Manifest.permission.NETWORK_SETTINGS); - } - - private void enforceConnectivityRestrictedNetworksPermission() { - try { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS, - "ConnectivityService"); - return; - } catch (SecurityException e) { /* fallback to ConnectivityInternalPermission */ } - // TODO: Remove this fallback check after all apps have declared - // CONNECTIVITY_USE_RESTRICTED_NETWORKS. - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.CONNECTIVITY_INTERNAL, - "ConnectivityService"); - } - - private void enforceKeepalivePermission() { - mContext.enforceCallingOrSelfPermission(KeepaliveTracker.PERMISSION, "ConnectivityService"); - } - - private boolean checkLocalMacAddressPermission(int pid, int uid) { - return PERMISSION_GRANTED == mContext.checkPermission( - Manifest.permission.LOCAL_MAC_ADDRESS, pid, uid); - } - - private void sendConnectedBroadcast(NetworkInfo info) { - sendGeneralBroadcast(info, CONNECTIVITY_ACTION); - } - - private void sendInetConditionBroadcast(NetworkInfo info) { - sendGeneralBroadcast(info, ConnectivityManager.INET_CONDITION_ACTION); - } - - private Intent makeGeneralIntent(NetworkInfo info, String bcastType) { - Intent intent = new Intent(bcastType); - intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, new NetworkInfo(info)); - intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType()); - if (info.isFailover()) { - intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true); - info.setFailover(false); - } - if (info.getReason() != null) { - intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason()); - } - if (info.getExtraInfo() != null) { - intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, - info.getExtraInfo()); - } - intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished); - return intent; - } - - private void sendGeneralBroadcast(NetworkInfo info, String bcastType) { - sendStickyBroadcast(makeGeneralIntent(info, bcastType)); - } - - private void sendStickyBroadcast(Intent intent) { - synchronized (this) { - if (!mSystemReady - && intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) { - mInitialBroadcast = new Intent(intent); - } - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - if (VDBG) { - log("sendStickyBroadcast: action=" + intent.getAction()); - } - - Bundle options = null; - final long ident = Binder.clearCallingIdentity(); - if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) { - final NetworkInfo ni = intent.getParcelableExtra( - ConnectivityManager.EXTRA_NETWORK_INFO); - final BroadcastOptions opts = BroadcastOptions.makeBasic(); - opts.setMaxManifestReceiverApiLevel(Build.VERSION_CODES.M); - options = opts.toBundle(); - intent.addFlags(Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS); - } - try { - mUserAllContext.sendStickyBroadcast(intent, options); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - } - - /** - * Called by SystemServer through ConnectivityManager when the system is ready. - */ - @Override - public void systemReady() { - if (mDeps.getCallingUid() != Process.SYSTEM_UID) { - throw new SecurityException("Calling Uid is not system uid."); - } - systemReadyInternal(); - } - - /** - * Called when ConnectivityService can initialize remaining components. - */ - @VisibleForTesting - public void systemReadyInternal() { - // Since mApps in PermissionMonitor needs to be populated first to ensure that - // listening network request which is sent by MultipathPolicyTracker won't be added - // NET_CAPABILITY_FOREGROUND capability. Thus, MultipathPolicyTracker.start() must - // be called after PermissionMonitor#startMonitoring(). - // Calling PermissionMonitor#startMonitoring() in systemReadyInternal() and the - // MultipathPolicyTracker.start() is called in NetworkPolicyManagerService#systemReady() - // to ensure the tracking will be initialized correctly. - mPermissionMonitor.startMonitoring(); - mProxyTracker.loadGlobalProxy(); - registerDnsResolverUnsolicitedEventListener(); - - synchronized (this) { - mSystemReady = true; - if (mInitialBroadcast != null) { - mContext.sendStickyBroadcastAsUser(mInitialBroadcast, UserHandle.ALL); - mInitialBroadcast = null; - } - } - - // Create network requests for always-on networks. - mHandler.sendMessage(mHandler.obtainMessage(EVENT_CONFIGURE_ALWAYS_ON_NETWORKS)); - } - - /** - * Start listening for default data network activity state changes. - */ - @Override - public void registerNetworkActivityListener(@NonNull INetworkActivityListener l) { - mNetworkActivityTracker.registerNetworkActivityListener(l); - } - - /** - * Stop listening for default data network activity state changes. - */ - @Override - public void unregisterNetworkActivityListener(@NonNull INetworkActivityListener l) { - mNetworkActivityTracker.unregisterNetworkActivityListener(l); - } - - /** - * Check whether the default network radio is currently active. - */ - @Override - public boolean isDefaultNetworkActive() { - return mNetworkActivityTracker.isDefaultNetworkActive(); - } - - /** - * Reads the network specific MTU size from resources. - * and set it on it's iface. - */ - private void updateMtu(LinkProperties newLp, LinkProperties oldLp) { - final String iface = newLp.getInterfaceName(); - final int mtu = newLp.getMtu(); - if (oldLp == null && mtu == 0) { - // Silently ignore unset MTU value. - return; - } - if (oldLp != null && newLp.isIdenticalMtu(oldLp)) { - if (VDBG) log("identical MTU - not setting"); - return; - } - if (!LinkProperties.isValidMtu(mtu, newLp.hasGlobalIpv6Address())) { - if (mtu != 0) loge("Unexpected mtu value: " + mtu + ", " + iface); - return; - } - - // Cannot set MTU without interface name - if (TextUtils.isEmpty(iface)) { - loge("Setting MTU size with null iface."); - return; - } - - try { - if (VDBG || DDBG) log("Setting MTU size: " + iface + ", " + mtu); - mNetd.interfaceSetMtu(iface, mtu); - } catch (RemoteException | ServiceSpecificException e) { - loge("exception in interfaceSetMtu()" + e); - } - } - - @VisibleForTesting - protected static final String DEFAULT_TCP_BUFFER_SIZES = "4096,87380,110208,4096,16384,110208"; - - private void updateTcpBufferSizes(String tcpBufferSizes) { - String[] values = null; - if (tcpBufferSizes != null) { - values = tcpBufferSizes.split(","); - } - - if (values == null || values.length != 6) { - if (DBG) log("Invalid tcpBufferSizes string: " + tcpBufferSizes +", using defaults"); - tcpBufferSizes = DEFAULT_TCP_BUFFER_SIZES; - values = tcpBufferSizes.split(","); - } - - if (tcpBufferSizes.equals(mCurrentTcpBufferSizes)) return; - - try { - if (VDBG || DDBG) log("Setting tx/rx TCP buffers to " + tcpBufferSizes); - - String rmemValues = String.join(" ", values[0], values[1], values[2]); - String wmemValues = String.join(" ", values[3], values[4], values[5]); - mNetd.setTcpRWmemorySize(rmemValues, wmemValues); - mCurrentTcpBufferSizes = tcpBufferSizes; - } catch (RemoteException | ServiceSpecificException e) { - loge("Can't set TCP buffer sizes:" + e); - } - } - - @Override - public int getRestoreDefaultNetworkDelay(int networkType) { - String restoreDefaultNetworkDelayStr = mSystemProperties.get( - NETWORK_RESTORE_DELAY_PROP_NAME); - if(restoreDefaultNetworkDelayStr != null && - restoreDefaultNetworkDelayStr.length() != 0) { - try { - return Integer.parseInt(restoreDefaultNetworkDelayStr); - } catch (NumberFormatException e) { - } - } - // if the system property isn't set, use the value for the apn type - int ret = RESTORE_DEFAULT_NETWORK_DELAY; - - if (mLegacyTypeTracker.isTypeSupported(networkType)) { - ret = mLegacyTypeTracker.getRestoreTimerForType(networkType); - } - return ret; - } - - private void dumpNetworkDiagnostics(IndentingPrintWriter pw) { - final List netDiags = new ArrayList(); - final long DIAG_TIME_MS = 5000; - for (NetworkAgentInfo nai : networksSortedById()) { - PrivateDnsConfig privateDnsCfg = mDnsManager.getPrivateDnsConfig(nai.network); - // Start gathering diagnostic information. - netDiags.add(new NetworkDiagnostics( - nai.network, - new LinkProperties(nai.linkProperties), // Must be a copy. - privateDnsCfg, - DIAG_TIME_MS)); - } - - for (NetworkDiagnostics netDiag : netDiags) { - pw.println(); - netDiag.waitForMeasurements(); - netDiag.dump(pw); - } - } - - @Override - protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer, - @Nullable String[] args) { - if (!checkDumpPermission(mContext, TAG, writer)) return; - - mPriorityDumper.dump(fd, writer, args); - } - - private boolean checkDumpPermission(Context context, String tag, PrintWriter pw) { - if (context.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) - != PackageManager.PERMISSION_GRANTED) { - pw.println("Permission Denial: can't dump " + tag + " from from pid=" - + Binder.getCallingPid() + ", uid=" + mDeps.getCallingUid() - + " due to missing android.permission.DUMP permission"); - return false; - } else { - return true; - } - } - - private void doDump(FileDescriptor fd, PrintWriter writer, String[] args) { - final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); - - if (CollectionUtils.contains(args, DIAG_ARG)) { - dumpNetworkDiagnostics(pw); - return; - } else if (CollectionUtils.contains(args, NETWORK_ARG)) { - dumpNetworks(pw); - return; - } else if (CollectionUtils.contains(args, REQUEST_ARG)) { - dumpNetworkRequests(pw); - return; - } - - pw.print("NetworkProviders for:"); - for (NetworkProviderInfo npi : mNetworkProviderInfos.values()) { - pw.print(" " + npi.name); - } - pw.println(); - pw.println(); - - final NetworkAgentInfo defaultNai = getDefaultNetwork(); - pw.print("Active default network: "); - if (defaultNai == null) { - pw.println("none"); - } else { - pw.println(defaultNai.network.getNetId()); - } - pw.println(); - - pw.print("Current per-app default networks: "); - pw.increaseIndent(); - dumpPerAppNetworkPreferences(pw); - pw.decreaseIndent(); - pw.println(); - - pw.println("Current Networks:"); - pw.increaseIndent(); - dumpNetworks(pw); - pw.decreaseIndent(); - pw.println(); - - pw.println("Status for known UIDs:"); - pw.increaseIndent(); - final int size = mUidBlockedReasons.size(); - for (int i = 0; i < size; i++) { - // Don't crash if the array is modified while dumping in bugreports. - try { - final int uid = mUidBlockedReasons.keyAt(i); - final int blockedReasons = mUidBlockedReasons.valueAt(i); - pw.println("UID=" + uid + " blockedReasons=" - + Integer.toHexString(blockedReasons)); - } catch (ArrayIndexOutOfBoundsException e) { - pw.println(" ArrayIndexOutOfBoundsException"); - } catch (ConcurrentModificationException e) { - pw.println(" ConcurrentModificationException"); - } - } - pw.println(); - pw.decreaseIndent(); - - pw.println("Network Requests:"); - pw.increaseIndent(); - dumpNetworkRequests(pw); - pw.decreaseIndent(); - pw.println(); - - mLegacyTypeTracker.dump(pw); - - pw.println(); - mKeepaliveTracker.dump(pw); - - pw.println(); - dumpAvoidBadWifiSettings(pw); - - pw.println(); - - if (!CollectionUtils.contains(args, SHORT_ARG)) { - pw.println(); - pw.println("mNetworkRequestInfoLogs (most recent first):"); - pw.increaseIndent(); - mNetworkRequestInfoLogs.reverseDump(pw); - pw.decreaseIndent(); - - pw.println(); - pw.println("mNetworkInfoBlockingLogs (most recent first):"); - pw.increaseIndent(); - mNetworkInfoBlockingLogs.reverseDump(pw); - pw.decreaseIndent(); - - pw.println(); - pw.println("NetTransition WakeLock activity (most recent first):"); - pw.increaseIndent(); - pw.println("total acquisitions: " + mTotalWakelockAcquisitions); - pw.println("total releases: " + mTotalWakelockReleases); - pw.println("cumulative duration: " + (mTotalWakelockDurationMs / 1000) + "s"); - pw.println("longest duration: " + (mMaxWakelockDurationMs / 1000) + "s"); - if (mTotalWakelockAcquisitions > mTotalWakelockReleases) { - long duration = SystemClock.elapsedRealtime() - mLastWakeLockAcquireTimestamp; - pw.println("currently holding WakeLock for: " + (duration / 1000) + "s"); - } - mWakelockLogs.reverseDump(pw); - - pw.println(); - pw.println("bandwidth update requests (by uid):"); - pw.increaseIndent(); - synchronized (mBandwidthRequests) { - for (int i = 0; i < mBandwidthRequests.size(); i++) { - pw.println("[" + mBandwidthRequests.keyAt(i) - + "]: " + mBandwidthRequests.valueAt(i)); - } - } - pw.decreaseIndent(); - pw.decreaseIndent(); - - pw.println(); - pw.println("mOemNetworkPreferencesLogs (most recent first):"); - pw.increaseIndent(); - mOemNetworkPreferencesLogs.reverseDump(pw); - pw.decreaseIndent(); - } - - pw.println(); - - pw.println(); - pw.println("Permission Monitor:"); - pw.increaseIndent(); - mPermissionMonitor.dump(pw); - pw.decreaseIndent(); - - pw.println(); - pw.println("Legacy network activity:"); - pw.increaseIndent(); - mNetworkActivityTracker.dump(pw); - pw.decreaseIndent(); - } - - private void dumpNetworks(IndentingPrintWriter pw) { - for (NetworkAgentInfo nai : networksSortedById()) { - pw.println(nai.toString()); - pw.increaseIndent(); - pw.println(String.format( - "Requests: REQUEST:%d LISTEN:%d BACKGROUND_REQUEST:%d total:%d", - nai.numForegroundNetworkRequests(), - nai.numNetworkRequests() - nai.numRequestNetworkRequests(), - nai.numBackgroundNetworkRequests(), - nai.numNetworkRequests())); - pw.increaseIndent(); - for (int i = 0; i < nai.numNetworkRequests(); i++) { - pw.println(nai.requestAt(i).toString()); - } - pw.decreaseIndent(); - pw.println("Inactivity Timers:"); - pw.increaseIndent(); - nai.dumpInactivityTimers(pw); - pw.decreaseIndent(); - pw.decreaseIndent(); - } - } - - private void dumpPerAppNetworkPreferences(IndentingPrintWriter pw) { - pw.println("Per-App Network Preference:"); - pw.increaseIndent(); - if (0 == mOemNetworkPreferences.getNetworkPreferences().size()) { - pw.println("none"); - } else { - pw.println(mOemNetworkPreferences.toString()); - } - pw.decreaseIndent(); - - for (final NetworkRequestInfo defaultRequest : mDefaultNetworkRequests) { - if (mDefaultRequest == defaultRequest) { - continue; - } - - final boolean isActive = null != defaultRequest.getSatisfier(); - pw.println("Is per-app network active:"); - pw.increaseIndent(); - pw.println(isActive); - if (isActive) { - pw.println("Active network: " + defaultRequest.getSatisfier().network.netId); - } - pw.println("Tracked UIDs:"); - pw.increaseIndent(); - if (0 == defaultRequest.mRequests.size()) { - pw.println("none, this should never occur."); - } else { - pw.println(defaultRequest.mRequests.get(0).networkCapabilities.getUidRanges()); - } - pw.decreaseIndent(); - pw.decreaseIndent(); - } - } - - private void dumpNetworkRequests(IndentingPrintWriter pw) { - for (NetworkRequestInfo nri : requestsSortedById()) { - pw.println(nri.toString()); - } - } - - /** - * Return an array of all current NetworkAgentInfos sorted by network id. - */ - private NetworkAgentInfo[] networksSortedById() { - NetworkAgentInfo[] networks = new NetworkAgentInfo[0]; - networks = mNetworkAgentInfos.toArray(networks); - Arrays.sort(networks, Comparator.comparingInt(nai -> nai.network.getNetId())); - return networks; - } - - /** - * Return an array of all current NetworkRequest sorted by request id. - */ - @VisibleForTesting - NetworkRequestInfo[] requestsSortedById() { - NetworkRequestInfo[] requests = new NetworkRequestInfo[0]; - requests = getNrisFromGlobalRequests().toArray(requests); - // Sort the array based off the NRI containing the min requestId in its requests. - Arrays.sort(requests, - Comparator.comparingInt(nri -> Collections.min(nri.mRequests, - Comparator.comparingInt(req -> req.requestId)).requestId - ) - ); - return requests; - } - - private boolean isLiveNetworkAgent(NetworkAgentInfo nai, int what) { - final NetworkAgentInfo officialNai = getNetworkAgentInfoForNetwork(nai.network); - if (officialNai != null && officialNai.equals(nai)) return true; - if (officialNai != null || VDBG) { - loge(eventName(what) + " - isLiveNetworkAgent found mismatched netId: " + officialNai + - " - " + nai); - } - return false; - } - - // must be stateless - things change under us. - private class NetworkStateTrackerHandler extends Handler { - public NetworkStateTrackerHandler(Looper looper) { - super(looper); - } - - private void maybeHandleNetworkAgentMessage(Message msg) { - final Pair arg = (Pair) msg.obj; - final NetworkAgentInfo nai = arg.first; - if (!mNetworkAgentInfos.contains(nai)) { - if (VDBG) { - log(String.format("%s from unknown NetworkAgent", eventName(msg.what))); - } - return; - } - - switch (msg.what) { - case NetworkAgent.EVENT_NETWORK_CAPABILITIES_CHANGED: { - NetworkCapabilities networkCapabilities = (NetworkCapabilities) arg.second; - if (networkCapabilities.hasConnectivityManagedCapability()) { - Log.wtf(TAG, "BUG: " + nai + " has CS-managed capability."); - } - if (networkCapabilities.hasTransport(TRANSPORT_TEST)) { - // Make sure the original object is not mutated. NetworkAgent normally - // makes a copy of the capabilities when sending the message through - // the Messenger, but if this ever changes, not making a defensive copy - // here will give attack vectors to clients using this code path. - networkCapabilities = new NetworkCapabilities(networkCapabilities); - networkCapabilities.restrictCapabilitesForTestNetwork(nai.creatorUid); - } - processCapabilitiesFromAgent(nai, networkCapabilities); - updateCapabilities(nai.getCurrentScore(), nai, networkCapabilities); - break; - } - case NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED: { - LinkProperties newLp = (LinkProperties) arg.second; - processLinkPropertiesFromAgent(nai, newLp); - handleUpdateLinkProperties(nai, newLp); - break; - } - case NetworkAgent.EVENT_NETWORK_INFO_CHANGED: { - NetworkInfo info = (NetworkInfo) arg.second; - updateNetworkInfo(nai, info); - break; - } - case NetworkAgent.EVENT_NETWORK_SCORE_CHANGED: { - updateNetworkScore(nai, (NetworkScore) arg.second); - break; - } - case NetworkAgent.EVENT_SET_EXPLICITLY_SELECTED: { - if (nai.everConnected) { - loge("ERROR: cannot call explicitlySelected on already-connected network"); - // Note that if the NAI had been connected, this would affect the - // score, and therefore would require re-mixing the score and performing - // a rematch. - } - nai.networkAgentConfig.explicitlySelected = toBool(msg.arg1); - nai.networkAgentConfig.acceptUnvalidated = toBool(msg.arg1) && toBool(msg.arg2); - // Mark the network as temporarily accepting partial connectivity so that it - // will be validated (and possibly become default) even if it only provides - // partial internet access. Note that if user connects to partial connectivity - // and choose "don't ask again", then wifi disconnected by some reasons(maybe - // out of wifi coverage) and if the same wifi is available again, the device - // will auto connect to this wifi even though the wifi has "no internet". - // TODO: Evaluate using a separate setting in IpMemoryStore. - nai.networkAgentConfig.acceptPartialConnectivity = toBool(msg.arg2); - break; - } - case NetworkAgent.EVENT_SOCKET_KEEPALIVE: { - mKeepaliveTracker.handleEventSocketKeepalive(nai, msg.arg1, msg.arg2); - break; - } - case NetworkAgent.EVENT_UNDERLYING_NETWORKS_CHANGED: { - // TODO: prevent loops, e.g., if a network declares itself as underlying. - if (!nai.supportsUnderlyingNetworks()) { - Log.wtf(TAG, "Non-virtual networks cannot have underlying networks"); - break; - } - - final List underlying = (List) arg.second; - - if (isLegacyLockdownNai(nai) - && (underlying == null || underlying.size() != 1)) { - Log.wtf(TAG, "Legacy lockdown VPN " + nai.toShortString() - + " must have exactly one underlying network: " + underlying); - } - - final Network[] oldUnderlying = nai.declaredUnderlyingNetworks; - nai.declaredUnderlyingNetworks = (underlying != null) - ? underlying.toArray(new Network[0]) : null; - - if (!Arrays.equals(oldUnderlying, nai.declaredUnderlyingNetworks)) { - if (DBG) { - log(nai.toShortString() + " changed underlying networks to " - + Arrays.toString(nai.declaredUnderlyingNetworks)); - } - updateCapabilitiesForNetwork(nai); - notifyIfacesChangedForNetworkStats(); - } - break; - } - case NetworkAgent.EVENT_TEARDOWN_DELAY_CHANGED: { - if (msg.arg1 >= 0 && msg.arg1 <= NetworkAgent.MAX_TEARDOWN_DELAY_MS) { - nai.teardownDelayMs = msg.arg1; - } else { - logwtf(nai.toShortString() + " set invalid teardown delay " + msg.arg1); - } - break; - } - case NetworkAgent.EVENT_LINGER_DURATION_CHANGED: { - nai.setLingerDuration((int) arg.second); - break; - } - } - } - - private boolean maybeHandleNetworkMonitorMessage(Message msg) { - switch (msg.what) { - default: - return false; - case EVENT_PROBE_STATUS_CHANGED: { - final Integer netId = (Integer) msg.obj; - final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(netId); - if (nai == null) { - break; - } - final boolean probePrivateDnsCompleted = - ((msg.arg1 & NETWORK_VALIDATION_PROBE_PRIVDNS) != 0); - final boolean privateDnsBroken = - ((msg.arg2 & NETWORK_VALIDATION_PROBE_PRIVDNS) == 0); - if (probePrivateDnsCompleted) { - if (nai.networkCapabilities.isPrivateDnsBroken() != privateDnsBroken) { - nai.networkCapabilities.setPrivateDnsBroken(privateDnsBroken); - updateCapabilitiesForNetwork(nai); - } - // Only show the notification when the private DNS is broken and the - // PRIVATE_DNS_BROKEN notification hasn't shown since last valid. - if (privateDnsBroken && !nai.networkAgentConfig.hasShownBroken) { - showNetworkNotification(nai, NotificationType.PRIVATE_DNS_BROKEN); - } - nai.networkAgentConfig.hasShownBroken = privateDnsBroken; - } else if (nai.networkCapabilities.isPrivateDnsBroken()) { - // If probePrivateDnsCompleted is false but nai.networkCapabilities says - // private DNS is broken, it means this network is being reevaluated. - // Either probing private DNS is not necessary any more or it hasn't been - // done yet. In either case, the networkCapabilities should be updated to - // reflect the new status. - nai.networkCapabilities.setPrivateDnsBroken(false); - updateCapabilitiesForNetwork(nai); - nai.networkAgentConfig.hasShownBroken = false; - } - break; - } - case EVENT_NETWORK_TESTED: { - final NetworkTestedResults results = (NetworkTestedResults) msg.obj; - - final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(results.mNetId); - if (nai == null) break; - - handleNetworkTested(nai, results.mTestResult, - (results.mRedirectUrl == null) ? "" : results.mRedirectUrl); - break; - } - case EVENT_PROVISIONING_NOTIFICATION: { - final int netId = msg.arg2; - final boolean visible = toBool(msg.arg1); - final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(netId); - // If captive portal status has changed, update capabilities or disconnect. - if (nai != null && (visible != nai.lastCaptivePortalDetected)) { - nai.lastCaptivePortalDetected = visible; - nai.everCaptivePortalDetected |= visible; - if (nai.lastCaptivePortalDetected && - ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_AVOID - == getCaptivePortalMode()) { - if (DBG) log("Avoiding captive portal network: " + nai.toShortString()); - nai.onPreventAutomaticReconnect(); - teardownUnneededNetwork(nai); - break; - } - updateCapabilitiesForNetwork(nai); - } - if (!visible) { - // Only clear SIGN_IN and NETWORK_SWITCH notifications here, or else other - // notifications belong to the same network may be cleared unexpectedly. - mNotifier.clearNotification(netId, NotificationType.SIGN_IN); - mNotifier.clearNotification(netId, NotificationType.NETWORK_SWITCH); - } else { - if (nai == null) { - loge("EVENT_PROVISIONING_NOTIFICATION from unknown NetworkMonitor"); - break; - } - if (!nai.networkAgentConfig.provisioningNotificationDisabled) { - mNotifier.showNotification(netId, NotificationType.SIGN_IN, nai, null, - (PendingIntent) msg.obj, - nai.networkAgentConfig.explicitlySelected); - } - } - break; - } - case EVENT_PRIVATE_DNS_CONFIG_RESOLVED: { - final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2); - if (nai == null) break; - - updatePrivateDns(nai, (PrivateDnsConfig) msg.obj); - break; - } - case EVENT_CAPPORT_DATA_CHANGED: { - final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2); - if (nai == null) break; - handleCapportApiDataUpdate(nai, (CaptivePortalData) msg.obj); - break; - } - } - return true; - } - - private void handleNetworkTested( - @NonNull NetworkAgentInfo nai, int testResult, @NonNull String redirectUrl) { - final boolean wasPartial = nai.partialConnectivity; - nai.partialConnectivity = ((testResult & NETWORK_VALIDATION_RESULT_PARTIAL) != 0); - final boolean partialConnectivityChanged = - (wasPartial != nai.partialConnectivity); - - final boolean valid = ((testResult & NETWORK_VALIDATION_RESULT_VALID) != 0); - final boolean wasValidated = nai.lastValidated; - final boolean wasDefault = isDefaultNetwork(nai); - - if (DBG) { - final String logMsg = !TextUtils.isEmpty(redirectUrl) - ? " with redirect to " + redirectUrl - : ""; - log(nai.toShortString() + " validation " + (valid ? "passed" : "failed") + logMsg); - } - if (valid != nai.lastValidated) { - final int oldScore = nai.getCurrentScore(); - nai.lastValidated = valid; - nai.everValidated |= valid; - updateCapabilities(oldScore, nai, nai.networkCapabilities); - if (valid) { - handleFreshlyValidatedNetwork(nai); - // Clear NO_INTERNET, PRIVATE_DNS_BROKEN, PARTIAL_CONNECTIVITY and - // LOST_INTERNET notifications if network becomes valid. - mNotifier.clearNotification(nai.network.getNetId(), - NotificationType.NO_INTERNET); - mNotifier.clearNotification(nai.network.getNetId(), - NotificationType.LOST_INTERNET); - mNotifier.clearNotification(nai.network.getNetId(), - NotificationType.PARTIAL_CONNECTIVITY); - mNotifier.clearNotification(nai.network.getNetId(), - NotificationType.PRIVATE_DNS_BROKEN); - // If network becomes valid, the hasShownBroken should be reset for - // that network so that the notification will be fired when the private - // DNS is broken again. - nai.networkAgentConfig.hasShownBroken = false; - } - } else if (partialConnectivityChanged) { - updateCapabilitiesForNetwork(nai); - } - updateInetCondition(nai); - // Let the NetworkAgent know the state of its network - // TODO: Evaluate to update partial connectivity to status to NetworkAgent. - nai.onValidationStatusChanged( - valid ? NetworkAgent.VALID_NETWORK : NetworkAgent.INVALID_NETWORK, - redirectUrl); - - // If NetworkMonitor detects partial connectivity before - // EVENT_PROMPT_UNVALIDATED arrives, show the partial connectivity notification - // immediately. Re-notify partial connectivity silently if no internet - // notification already there. - if (!wasPartial && nai.partialConnectivity) { - // Remove delayed message if there is a pending message. - mHandler.removeMessages(EVENT_PROMPT_UNVALIDATED, nai.network); - handlePromptUnvalidated(nai.network); - } - - if (wasValidated && !nai.lastValidated) { - handleNetworkUnvalidated(nai); - } - } - - private int getCaptivePortalMode() { - return Settings.Global.getInt(mContext.getContentResolver(), - ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE, - ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_PROMPT); - } - - private boolean maybeHandleNetworkAgentInfoMessage(Message msg) { - switch (msg.what) { - default: - return false; - case NetworkAgentInfo.EVENT_NETWORK_LINGER_COMPLETE: { - NetworkAgentInfo nai = (NetworkAgentInfo) msg.obj; - if (nai != null && isLiveNetworkAgent(nai, msg.what)) { - handleLingerComplete(nai); - } - break; - } - case NetworkAgentInfo.EVENT_AGENT_REGISTERED: { - handleNetworkAgentRegistered(msg); - break; - } - case NetworkAgentInfo.EVENT_AGENT_DISCONNECTED: { - handleNetworkAgentDisconnected(msg); - break; - } - } - return true; - } - - @Override - public void handleMessage(Message msg) { - if (!maybeHandleNetworkMonitorMessage(msg) - && !maybeHandleNetworkAgentInfoMessage(msg)) { - maybeHandleNetworkAgentMessage(msg); - } - } - } - - private class NetworkMonitorCallbacks extends INetworkMonitorCallbacks.Stub { - private final int mNetId; - private final AutodestructReference mNai; - - private NetworkMonitorCallbacks(NetworkAgentInfo nai) { - mNetId = nai.network.getNetId(); - mNai = new AutodestructReference<>(nai); - } - - @Override - public void onNetworkMonitorCreated(INetworkMonitor networkMonitor) { - mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, - new Pair<>(mNai.getAndDestroy(), networkMonitor))); - } - - @Override - public void notifyNetworkTested(int testResult, @Nullable String redirectUrl) { - // Legacy version of notifyNetworkTestedWithExtras. - // Would only be called if the system has a NetworkStack module older than the - // framework, which does not happen in practice. - Log.wtf(TAG, "Deprecated notifyNetworkTested called: no action taken"); - } - - @Override - public void notifyNetworkTestedWithExtras(NetworkTestResultParcelable p) { - // Notify mTrackerHandler and mConnectivityDiagnosticsHandler of the event. Both use - // the same looper so messages will be processed in sequence. - final Message msg = mTrackerHandler.obtainMessage( - EVENT_NETWORK_TESTED, - new NetworkTestedResults( - mNetId, p.result, p.timestampMillis, p.redirectUrl)); - mTrackerHandler.sendMessage(msg); - - // Invoke ConnectivityReport generation for this Network test event. - final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(mNetId); - if (nai == null) return; - - final PersistableBundle extras = new PersistableBundle(); - extras.putInt(KEY_NETWORK_VALIDATION_RESULT, p.result); - extras.putInt(KEY_NETWORK_PROBES_SUCCEEDED_BITMASK, p.probesSucceeded); - extras.putInt(KEY_NETWORK_PROBES_ATTEMPTED_BITMASK, p.probesAttempted); - - ConnectivityReportEvent reportEvent = - new ConnectivityReportEvent(p.timestampMillis, nai, extras); - final Message m = mConnectivityDiagnosticsHandler.obtainMessage( - ConnectivityDiagnosticsHandler.EVENT_NETWORK_TESTED, reportEvent); - mConnectivityDiagnosticsHandler.sendMessage(m); - } - - @Override - public void notifyPrivateDnsConfigResolved(PrivateDnsConfigParcel config) { - mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage( - EVENT_PRIVATE_DNS_CONFIG_RESOLVED, - 0, mNetId, PrivateDnsConfig.fromParcel(config))); - } - - @Override - public void notifyProbeStatusChanged(int probesCompleted, int probesSucceeded) { - mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage( - EVENT_PROBE_STATUS_CHANGED, - probesCompleted, probesSucceeded, new Integer(mNetId))); - } - - @Override - public void notifyCaptivePortalDataChanged(CaptivePortalData data) { - mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage( - EVENT_CAPPORT_DATA_CHANGED, - 0, mNetId, data)); - } - - @Override - public void showProvisioningNotification(String action, String packageName) { - final Intent intent = new Intent(action); - intent.setPackage(packageName); - - final PendingIntent pendingIntent; - // Only the system server can register notifications with package "android" - final long token = Binder.clearCallingIdentity(); - try { - pendingIntent = PendingIntent.getBroadcast( - mContext, - 0 /* requestCode */, - intent, - PendingIntent.FLAG_IMMUTABLE); - } finally { - Binder.restoreCallingIdentity(token); - } - mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage( - EVENT_PROVISIONING_NOTIFICATION, PROVISIONING_NOTIFICATION_SHOW, - mNetId, pendingIntent)); - } - - @Override - public void hideProvisioningNotification() { - mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage( - EVENT_PROVISIONING_NOTIFICATION, PROVISIONING_NOTIFICATION_HIDE, mNetId)); - } - - @Override - public void notifyDataStallSuspected(DataStallReportParcelable p) { - ConnectivityService.this.notifyDataStallSuspected(p, mNetId); - } - - @Override - public int getInterfaceVersion() { - return this.VERSION; - } - - @Override - public String getInterfaceHash() { - return this.HASH; - } - } - - private void notifyDataStallSuspected(DataStallReportParcelable p, int netId) { - log("Data stall detected with methods: " + p.detectionMethod); - - final PersistableBundle extras = new PersistableBundle(); - int detectionMethod = 0; - if (hasDataStallDetectionMethod(p, DETECTION_METHOD_DNS_EVENTS)) { - extras.putInt(KEY_DNS_CONSECUTIVE_TIMEOUTS, p.dnsConsecutiveTimeouts); - detectionMethod |= DETECTION_METHOD_DNS_EVENTS; - } - if (hasDataStallDetectionMethod(p, DETECTION_METHOD_TCP_METRICS)) { - extras.putInt(KEY_TCP_PACKET_FAIL_RATE, p.tcpPacketFailRate); - extras.putInt(KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS, - p.tcpMetricsCollectionPeriodMillis); - detectionMethod |= DETECTION_METHOD_TCP_METRICS; - } - - final Message msg = mConnectivityDiagnosticsHandler.obtainMessage( - ConnectivityDiagnosticsHandler.EVENT_DATA_STALL_SUSPECTED, detectionMethod, netId, - new Pair<>(p.timestampMillis, extras)); - - // NetworkStateTrackerHandler currently doesn't take any actions based on data - // stalls so send the message directly to ConnectivityDiagnosticsHandler and avoid - // the cost of going through two handlers. - mConnectivityDiagnosticsHandler.sendMessage(msg); - } - - private boolean hasDataStallDetectionMethod(DataStallReportParcelable p, int detectionMethod) { - return (p.detectionMethod & detectionMethod) != 0; - } - - private boolean networkRequiresPrivateDnsValidation(NetworkAgentInfo nai) { - return isPrivateDnsValidationRequired(nai.networkCapabilities); - } - - private void handleFreshlyValidatedNetwork(NetworkAgentInfo nai) { - if (nai == null) return; - // If the Private DNS mode is opportunistic, reprogram the DNS servers - // in order to restart a validation pass from within netd. - final PrivateDnsConfig cfg = mDnsManager.getPrivateDnsConfig(); - if (cfg.useTls && TextUtils.isEmpty(cfg.hostname)) { - updateDnses(nai.linkProperties, null, nai.network.getNetId()); - } - } - - private void handlePrivateDnsSettingsChanged() { - final PrivateDnsConfig cfg = mDnsManager.getPrivateDnsConfig(); - - for (NetworkAgentInfo nai : mNetworkAgentInfos) { - handlePerNetworkPrivateDnsConfig(nai, cfg); - if (networkRequiresPrivateDnsValidation(nai)) { - handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties)); - } - } - } - - private void handlePerNetworkPrivateDnsConfig(NetworkAgentInfo nai, PrivateDnsConfig cfg) { - // Private DNS only ever applies to networks that might provide - // Internet access and therefore also require validation. - if (!networkRequiresPrivateDnsValidation(nai)) return; - - // Notify the NetworkAgentInfo/NetworkMonitor in case NetworkMonitor needs to cancel or - // schedule DNS resolutions. If a DNS resolution is required the - // result will be sent back to us. - nai.networkMonitor().notifyPrivateDnsChanged(cfg.toParcel()); - - // With Private DNS bypass support, we can proceed to update the - // Private DNS config immediately, even if we're in strict mode - // and have not yet resolved the provider name into a set of IPs. - updatePrivateDns(nai, cfg); - } - - private void updatePrivateDns(NetworkAgentInfo nai, PrivateDnsConfig newCfg) { - mDnsManager.updatePrivateDns(nai.network, newCfg); - updateDnses(nai.linkProperties, null, nai.network.getNetId()); - } - - private void handlePrivateDnsValidationUpdate(PrivateDnsValidationUpdate update) { - NetworkAgentInfo nai = getNetworkAgentInfoForNetId(update.netId); - if (nai == null) { - return; - } - mDnsManager.updatePrivateDnsValidation(update); - handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties)); - } - - private void handleNat64PrefixEvent(int netId, int operation, String prefixAddress, - int prefixLength) { - NetworkAgentInfo nai = mNetworkForNetId.get(netId); - if (nai == null) return; - - log(String.format("NAT64 prefix changed on netId %d: operation=%d, %s/%d", - netId, operation, prefixAddress, prefixLength)); - - IpPrefix prefix = null; - if (operation == IDnsResolverUnsolicitedEventListener.PREFIX_OPERATION_ADDED) { - try { - prefix = new IpPrefix(InetAddresses.parseNumericAddress(prefixAddress), - prefixLength); - } catch (IllegalArgumentException e) { - loge("Invalid NAT64 prefix " + prefixAddress + "/" + prefixLength); - return; - } - } - - nai.clatd.setNat64PrefixFromDns(prefix); - handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties)); - } - - private void handleCapportApiDataUpdate(@NonNull final NetworkAgentInfo nai, - @Nullable final CaptivePortalData data) { - nai.capportApiData = data; - // CaptivePortalData will be merged into LinkProperties from NetworkAgentInfo - handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties)); - } - - /** - * Updates the inactivity state from the network requests inside the NAI. - * @param nai the agent info to update - * @param now the timestamp of the event causing this update - * @return whether the network was inactive as a result of this update - */ - private boolean updateInactivityState(@NonNull final NetworkAgentInfo nai, final long now) { - // 1. Update the inactivity timer. If it's changed, reschedule or cancel the alarm. - // 2. If the network was inactive and there are now requests, unset inactive. - // 3. If this network is unneeded (which implies it is not lingering), and there is at least - // one lingered request, set inactive. - nai.updateInactivityTimer(); - if (nai.isInactive() && nai.numForegroundNetworkRequests() > 0) { - if (DBG) log("Unsetting inactive " + nai.toShortString()); - nai.unsetInactive(); - logNetworkEvent(nai, NetworkEvent.NETWORK_UNLINGER); - } else if (unneeded(nai, UnneededFor.LINGER) && nai.getInactivityExpiry() > 0) { - if (DBG) { - final int lingerTime = (int) (nai.getInactivityExpiry() - now); - log("Setting inactive " + nai.toShortString() + " for " + lingerTime + "ms"); - } - nai.setInactive(); - logNetworkEvent(nai, NetworkEvent.NETWORK_LINGER); - return true; - } - return false; - } - - private void handleNetworkAgentRegistered(Message msg) { - final NetworkAgentInfo nai = (NetworkAgentInfo) msg.obj; - if (!mNetworkAgentInfos.contains(nai)) { - return; - } - - if (msg.arg1 == NetworkAgentInfo.ARG_AGENT_SUCCESS) { - if (VDBG) log("NetworkAgent registered"); - } else { - loge("Error connecting NetworkAgent"); - mNetworkAgentInfos.remove(nai); - if (nai != null) { - final boolean wasDefault = isDefaultNetwork(nai); - synchronized (mNetworkForNetId) { - mNetworkForNetId.remove(nai.network.getNetId()); - } - mNetIdManager.releaseNetId(nai.network.getNetId()); - // Just in case. - mLegacyTypeTracker.remove(nai, wasDefault); - } - } - } - - private void handleNetworkAgentDisconnected(Message msg) { - NetworkAgentInfo nai = (NetworkAgentInfo) msg.obj; - if (mNetworkAgentInfos.contains(nai)) { - disconnectAndDestroyNetwork(nai); - } - } - - // Destroys a network, remove references to it from the internal state managed by - // ConnectivityService, free its interfaces and clean up. - // Must be called on the Handler thread. - private void disconnectAndDestroyNetwork(NetworkAgentInfo nai) { - ensureRunningOnConnectivityServiceThread(); - if (DBG) { - log(nai.toShortString() + " disconnected, was satisfying " + nai.numNetworkRequests()); - } - // Clear all notifications of this network. - mNotifier.clearNotification(nai.network.getNetId()); - // A network agent has disconnected. - // TODO - if we move the logic to the network agent (have them disconnect - // because they lost all their requests or because their score isn't good) - // then they would disconnect organically, report their new state and then - // disconnect the channel. - if (nai.networkInfo.isConnected()) { - nai.networkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, - null, null); - } - final boolean wasDefault = isDefaultNetwork(nai); - if (wasDefault) { - mDefaultInetConditionPublished = 0; - } - notifyIfacesChangedForNetworkStats(); - // TODO - we shouldn't send CALLBACK_LOST to requests that can be satisfied - // by other networks that are already connected. Perhaps that can be done by - // sending all CALLBACK_LOST messages (for requests, not listens) at the end - // of rematchAllNetworksAndRequests - notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOST); - mKeepaliveTracker.handleStopAllKeepalives(nai, SocketKeepalive.ERROR_INVALID_NETWORK); - - mQosCallbackTracker.handleNetworkReleased(nai.network); - for (String iface : nai.linkProperties.getAllInterfaceNames()) { - // Disable wakeup packet monitoring for each interface. - wakeupModifyInterface(iface, nai.networkCapabilities, false); - } - nai.networkMonitor().notifyNetworkDisconnected(); - mNetworkAgentInfos.remove(nai); - nai.clatd.update(); - synchronized (mNetworkForNetId) { - // Remove the NetworkAgent, but don't mark the netId as - // available until we've told netd to delete it below. - mNetworkForNetId.remove(nai.network.getNetId()); - } - propagateUnderlyingNetworkCapabilities(nai.network); - // Remove all previously satisfied requests. - for (int i = 0; i < nai.numNetworkRequests(); i++) { - final NetworkRequest request = nai.requestAt(i); - final NetworkRequestInfo nri = mNetworkRequests.get(request); - final NetworkAgentInfo currentNetwork = nri.getSatisfier(); - if (currentNetwork != null - && currentNetwork.network.getNetId() == nai.network.getNetId()) { - // uid rules for this network will be removed in destroyNativeNetwork(nai). - // TODO : setting the satisfier is in fact the job of the rematch. Teach the - // rematch not to keep disconnected agents instead of setting it here ; this - // will also allow removing updating the offers below. - nri.setSatisfier(null, null); - for (final NetworkOfferInfo noi : mNetworkOffers) { - informOffer(nri, noi.offer, mNetworkRanker); - } - - if (mDefaultRequest == nri) { - // TODO : make battery stats aware that since 2013 multiple interfaces may be - // active at the same time. For now keep calling this with the default - // network, because while incorrect this is the closest to the old (also - // incorrect) behavior. - mNetworkActivityTracker.updateDataActivityTracking( - null /* newNetwork */, nai); - ensureNetworkTransitionWakelock(nai.toShortString()); - } - } - } - nai.clearInactivityState(); - // TODO: mLegacyTypeTracker.remove seems redundant given there's a full rematch right after. - // Currently, deleting it breaks tests that check for the default network disconnecting. - // Find out why, fix the rematch code, and delete this. - mLegacyTypeTracker.remove(nai, wasDefault); - rematchAllNetworksAndRequests(); - mLingerMonitor.noteDisconnect(nai); - - // Immediate teardown. - if (nai.teardownDelayMs == 0) { - destroyNetwork(nai); - return; - } - - // Delayed teardown. - try { - mNetd.networkSetPermissionForNetwork(nai.network.netId, INetd.PERMISSION_SYSTEM); - } catch (RemoteException e) { - Log.d(TAG, "Error marking network restricted during teardown: " + e); - } - mHandler.postDelayed(() -> destroyNetwork(nai), nai.teardownDelayMs); - } - - private void destroyNetwork(NetworkAgentInfo nai) { - if (nai.created) { - // Tell netd to clean up the configuration for this network - // (routing rules, DNS, etc). - // This may be slow as it requires a lot of netd shelling out to ip and - // ip[6]tables to flush routes and remove the incoming packet mark rule, so do it - // after we've rematched networks with requests (which might change the default - // network or service a new request from an app), so network traffic isn't interrupted - // for an unnecessarily long time. - destroyNativeNetwork(nai); - mDnsManager.removeNetwork(nai.network); - } - mNetIdManager.releaseNetId(nai.network.getNetId()); - nai.onNetworkDestroyed(); - } - - private boolean createNativeNetwork(@NonNull NetworkAgentInfo nai) { - try { - // This should never fail. Specifying an already in use NetID will cause failure. - final NativeNetworkConfig config; - if (nai.isVPN()) { - if (getVpnType(nai) == VpnManager.TYPE_VPN_NONE) { - Log.wtf(TAG, "Unable to get VPN type from network " + nai.toShortString()); - return false; - } - config = new NativeNetworkConfig(nai.network.getNetId(), NativeNetworkType.VIRTUAL, - INetd.PERMISSION_NONE, - (nai.networkAgentConfig == null || !nai.networkAgentConfig.allowBypass), - getVpnType(nai)); - } else { - config = new NativeNetworkConfig(nai.network.getNetId(), NativeNetworkType.PHYSICAL, - getNetworkPermission(nai.networkCapabilities), /*secure=*/ false, - VpnManager.TYPE_VPN_NONE); - } - mNetd.networkCreate(config); - mDnsResolver.createNetworkCache(nai.network.getNetId()); - mDnsManager.updateTransportsForNetwork(nai.network.getNetId(), - nai.networkCapabilities.getTransportTypes()); - return true; - } catch (RemoteException | ServiceSpecificException e) { - loge("Error creating network " + nai.toShortString() + ": " + e.getMessage()); - return false; - } - } - - private void destroyNativeNetwork(@NonNull NetworkAgentInfo nai) { - try { - mNetd.networkDestroy(nai.network.getNetId()); - } catch (RemoteException | ServiceSpecificException e) { - loge("Exception destroying network(networkDestroy): " + e); - } - try { - mDnsResolver.destroyNetworkCache(nai.network.getNetId()); - } catch (RemoteException | ServiceSpecificException e) { - loge("Exception destroying network: " + e); - } - } - - // If this method proves to be too slow then we can maintain a separate - // pendingIntent => NetworkRequestInfo map. - // This method assumes that every non-null PendingIntent maps to exactly 1 NetworkRequestInfo. - private NetworkRequestInfo findExistingNetworkRequestInfo(PendingIntent pendingIntent) { - for (Map.Entry entry : mNetworkRequests.entrySet()) { - PendingIntent existingPendingIntent = entry.getValue().mPendingIntent; - if (existingPendingIntent != null && - existingPendingIntent.intentFilterEquals(pendingIntent)) { - return entry.getValue(); - } - } - return null; - } - - private void handleRegisterNetworkRequestWithIntent(@NonNull final Message msg) { - final NetworkRequestInfo nri = (NetworkRequestInfo) (msg.obj); - // handleRegisterNetworkRequestWithIntent() doesn't apply to multilayer requests. - ensureNotMultilayerRequest(nri, "handleRegisterNetworkRequestWithIntent"); - final NetworkRequestInfo existingRequest = - findExistingNetworkRequestInfo(nri.mPendingIntent); - if (existingRequest != null) { // remove the existing request. - if (DBG) { - log("Replacing " + existingRequest.mRequests.get(0) + " with " - + nri.mRequests.get(0) + " because their intents matched."); - } - handleReleaseNetworkRequest(existingRequest.mRequests.get(0), mDeps.getCallingUid(), - /* callOnUnavailable */ false); - } - handleRegisterNetworkRequest(nri); - } - - private void handleRegisterNetworkRequest(@NonNull final NetworkRequestInfo nri) { - handleRegisterNetworkRequests(Collections.singleton(nri)); - } - - private void handleRegisterNetworkRequests(@NonNull final Set nris) { - ensureRunningOnConnectivityServiceThread(); - for (final NetworkRequestInfo nri : nris) { - mNetworkRequestInfoLogs.log("REGISTER " + nri); - for (final NetworkRequest req : nri.mRequests) { - mNetworkRequests.put(req, nri); - // TODO: Consider update signal strength for other types. - if (req.isListen()) { - for (final NetworkAgentInfo network : mNetworkAgentInfos) { - if (req.networkCapabilities.hasSignalStrength() - && network.satisfiesImmutableCapabilitiesOf(req)) { - updateSignalStrengthThresholds(network, "REGISTER", req); - } - } - } - } - // If this NRI has a satisfier already, it is replacing an older request that - // has been removed. Track it. - final NetworkRequest activeRequest = nri.getActiveRequest(); - if (null != activeRequest) { - // If there is an active request, then for sure there is a satisfier. - nri.getSatisfier().addRequest(activeRequest); - } - } - - rematchAllNetworksAndRequests(); - - // Requests that have not been matched to a network will not have been sent to the - // providers, because the old satisfier and the new satisfier are the same (null in this - // case). Send these requests to the providers. - for (final NetworkRequestInfo nri : nris) { - for (final NetworkOfferInfo noi : mNetworkOffers) { - informOffer(nri, noi.offer, mNetworkRanker); - } - } - } - - private void handleReleaseNetworkRequestWithIntent(@NonNull final PendingIntent pendingIntent, - final int callingUid) { - final NetworkRequestInfo nri = findExistingNetworkRequestInfo(pendingIntent); - if (nri != null) { - // handleReleaseNetworkRequestWithIntent() paths don't apply to multilayer requests. - ensureNotMultilayerRequest(nri, "handleReleaseNetworkRequestWithIntent"); - handleReleaseNetworkRequest( - nri.mRequests.get(0), - callingUid, - /* callOnUnavailable */ false); - } - } - - // Determines whether the network is the best (or could become the best, if it validated), for - // none of a particular type of NetworkRequests. The type of NetworkRequests considered depends - // on the value of reason: - // - // - UnneededFor.TEARDOWN: non-listen NetworkRequests. If a network is unneeded for this reason, - // then it should be torn down. - // - UnneededFor.LINGER: foreground NetworkRequests. If a network is unneeded for this reason, - // then it should be lingered. - private boolean unneeded(NetworkAgentInfo nai, UnneededFor reason) { - ensureRunningOnConnectivityServiceThread(); - - if (!nai.everConnected || nai.isVPN() || nai.isInactive() - || nai.getScore().getKeepConnectedReason() != NetworkScore.KEEP_CONNECTED_NONE) { - return false; - } - - final int numRequests; - switch (reason) { - case TEARDOWN: - numRequests = nai.numRequestNetworkRequests(); - break; - case LINGER: - numRequests = nai.numForegroundNetworkRequests(); - break; - default: - Log.wtf(TAG, "Invalid reason. Cannot happen."); - return true; - } - - if (numRequests > 0) return false; - - for (NetworkRequestInfo nri : mNetworkRequests.values()) { - if (reason == UnneededFor.LINGER - && !nri.isMultilayerRequest() - && nri.mRequests.get(0).isBackgroundRequest()) { - // Background requests don't affect lingering. - continue; - } - - if (isNetworkPotentialSatisfier(nai, nri)) { - return false; - } - } - return true; - } - - private boolean isNetworkPotentialSatisfier( - @NonNull final NetworkAgentInfo candidate, @NonNull final NetworkRequestInfo nri) { - // listen requests won't keep up a network satisfying it. If this is not a multilayer - // request, return immediately. For multilayer requests, check to see if any of the - // multilayer requests may have a potential satisfier. - if (!nri.isMultilayerRequest() && (nri.mRequests.get(0).isListen() - || nri.mRequests.get(0).isListenForBest())) { - return false; - } - for (final NetworkRequest req : nri.mRequests) { - // This multilayer listen request is satisfied therefore no further requests need to be - // evaluated deeming this network not a potential satisfier. - if ((req.isListen() || req.isListenForBest()) && nri.getActiveRequest() == req) { - return false; - } - // As non-multilayer listen requests have already returned, the below would only happen - // for a multilayer request therefore continue to the next request if available. - if (req.isListen() || req.isListenForBest()) { - continue; - } - // If this Network is already the highest scoring Network for a request, or if - // there is hope for it to become one if it validated, then it is needed. - if (candidate.satisfies(req)) { - // As soon as a network is found that satisfies a request, return. Specifically for - // multilayer requests, returning as soon as a NetworkAgentInfo satisfies a request - // is important so as to not evaluate lower priority requests further in - // nri.mRequests. - final NetworkAgentInfo champion = req.equals(nri.getActiveRequest()) - ? nri.getSatisfier() : null; - // Note that this catches two important cases: - // 1. Unvalidated cellular will not be reaped when unvalidated WiFi - // is currently satisfying the request. This is desirable when - // cellular ends up validating but WiFi does not. - // 2. Unvalidated WiFi will not be reaped when validated cellular - // is currently satisfying the request. This is desirable when - // WiFi ends up validating and out scoring cellular. - return mNetworkRanker.mightBeat(req, champion, candidate.getValidatedScoreable()); - } - } - - return false; - } - - private NetworkRequestInfo getNriForAppRequest( - NetworkRequest request, int callingUid, String requestedOperation) { - // Looking up the app passed param request in mRequests isn't possible since it may return - // null for a request managed by a per-app default. Therefore use getNriForAppRequest() to - // do the lookup since that will also find per-app default managed requests. - // Additionally, this lookup needs to be relatively fast (hence the lookup optimization) - // to avoid potential race conditions when validating a package->uid mapping when sending - // the callback on the very low-chance that an application shuts down prior to the callback - // being sent. - final NetworkRequestInfo nri = mNetworkRequests.get(request) != null - ? mNetworkRequests.get(request) : getNriForAppRequest(request); - - if (nri != null) { - if (Process.SYSTEM_UID != callingUid && nri.mUid != callingUid) { - log(String.format("UID %d attempted to %s for unowned request %s", - callingUid, requestedOperation, nri)); - return null; - } - } - - return nri; - } - - private void ensureNotMultilayerRequest(@NonNull final NetworkRequestInfo nri, - final String callingMethod) { - if (nri.isMultilayerRequest()) { - throw new IllegalStateException( - callingMethod + " does not support multilayer requests."); - } - } - - private void handleTimedOutNetworkRequest(@NonNull final NetworkRequestInfo nri) { - ensureRunningOnConnectivityServiceThread(); - // handleTimedOutNetworkRequest() is part of the requestNetwork() flow which works off of a - // single NetworkRequest and thus does not apply to multilayer requests. - ensureNotMultilayerRequest(nri, "handleTimedOutNetworkRequest"); - if (mNetworkRequests.get(nri.mRequests.get(0)) == null) { - return; - } - if (nri.isBeingSatisfied()) { - return; - } - if (VDBG || (DBG && nri.mRequests.get(0).isRequest())) { - log("releasing " + nri.mRequests.get(0) + " (timeout)"); - } - handleRemoveNetworkRequest(nri); - callCallbackForRequest( - nri, null, ConnectivityManager.CALLBACK_UNAVAIL, 0); - } - - private void handleReleaseNetworkRequest(@NonNull final NetworkRequest request, - final int callingUid, - final boolean callOnUnavailable) { - final NetworkRequestInfo nri = - getNriForAppRequest(request, callingUid, "release NetworkRequest"); - if (nri == null) { - return; - } - if (VDBG || (DBG && request.isRequest())) { - log("releasing " + request + " (release request)"); - } - handleRemoveNetworkRequest(nri); - if (callOnUnavailable) { - callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_UNAVAIL, 0); - } - } - - private void handleRemoveNetworkRequest(@NonNull final NetworkRequestInfo nri) { - ensureRunningOnConnectivityServiceThread(); - nri.unlinkDeathRecipient(); - for (final NetworkRequest req : nri.mRequests) { - mNetworkRequests.remove(req); - if (req.isListen()) { - removeListenRequestFromNetworks(req); - } - } - if (mDefaultNetworkRequests.remove(nri)) { - // If this request was one of the defaults, then the UID rules need to be updated - // WARNING : if the app(s) for which this network request is the default are doing - // traffic, this will kill their connected sockets, even if an equivalent request - // is going to be reinstated right away ; unconnected traffic will go on the default - // until the new default is set, which will happen very soon. - // TODO : The only way out of this is to diff old defaults and new defaults, and only - // remove ranges for those requests that won't have a replacement - final NetworkAgentInfo satisfier = nri.getSatisfier(); - if (null != satisfier) { - try { - mNetd.networkRemoveUidRanges(satisfier.network.getNetId(), - toUidRangeStableParcels(nri.getUids())); - } catch (RemoteException e) { - loge("Exception setting network preference default network", e); - } - } - } - nri.decrementRequestCount(); - mNetworkRequestInfoLogs.log("RELEASE " + nri); - - if (null != nri.getActiveRequest()) { - if (!nri.getActiveRequest().isListen()) { - removeSatisfiedNetworkRequestFromNetwork(nri); - } else { - nri.setSatisfier(null, null); - } - } - - // For all outstanding offers, cancel any of the layers of this NRI that used to be - // needed for this offer. - for (final NetworkOfferInfo noi : mNetworkOffers) { - for (final NetworkRequest req : nri.mRequests) { - if (req.isRequest() && noi.offer.neededFor(req)) { - noi.offer.onNetworkUnneeded(req); - } - } - } - } - - private void handleRemoveNetworkRequests(@NonNull final Set nris) { - for (final NetworkRequestInfo nri : nris) { - if (mDefaultRequest == nri) { - // Make sure we never remove the default request. - continue; - } - handleRemoveNetworkRequest(nri); - } - } - - private void removeListenRequestFromNetworks(@NonNull final NetworkRequest req) { - // listens don't have a singular affected Network. Check all networks to see - // if this listen request applies and remove it. - for (final NetworkAgentInfo nai : mNetworkAgentInfos) { - nai.removeRequest(req.requestId); - if (req.networkCapabilities.hasSignalStrength() - && nai.satisfiesImmutableCapabilitiesOf(req)) { - updateSignalStrengthThresholds(nai, "RELEASE", req); - } - } - } - - /** - * Remove a NetworkRequestInfo's satisfied request from its 'satisfier' (NetworkAgentInfo) and - * manage the necessary upkeep (linger, teardown networks, etc.) when doing so. - * @param nri the NetworkRequestInfo to disassociate from its current NetworkAgentInfo - */ - private void removeSatisfiedNetworkRequestFromNetwork(@NonNull final NetworkRequestInfo nri) { - boolean wasKept = false; - final NetworkAgentInfo nai = nri.getSatisfier(); - if (nai != null) { - final int requestLegacyType = nri.getActiveRequest().legacyType; - final boolean wasBackgroundNetwork = nai.isBackgroundNetwork(); - nai.removeRequest(nri.getActiveRequest().requestId); - if (VDBG || DDBG) { - log(" Removing from current network " + nai.toShortString() - + ", leaving " + nai.numNetworkRequests() + " requests."); - } - // If there are still lingered requests on this network, don't tear it down, - // but resume lingering instead. - final long now = SystemClock.elapsedRealtime(); - if (updateInactivityState(nai, now)) { - notifyNetworkLosing(nai, now); - } - if (unneeded(nai, UnneededFor.TEARDOWN)) { - if (DBG) log("no live requests for " + nai.toShortString() + "; disconnecting"); - teardownUnneededNetwork(nai); - } else { - wasKept = true; - } - nri.setSatisfier(null, null); - if (!wasBackgroundNetwork && nai.isBackgroundNetwork()) { - // Went from foreground to background. - updateCapabilitiesForNetwork(nai); - } - - // Maintain the illusion. When this request arrived, we might have pretended - // that a network connected to serve it, even though the network was already - // connected. Now that this request has gone away, we might have to pretend - // that the network disconnected. LegacyTypeTracker will generate that - // phantom disconnect for this type. - if (requestLegacyType != TYPE_NONE) { - boolean doRemove = true; - if (wasKept) { - // check if any of the remaining requests for this network are for the - // same legacy type - if so, don't remove the nai - for (int i = 0; i < nai.numNetworkRequests(); i++) { - NetworkRequest otherRequest = nai.requestAt(i); - if (otherRequest.legacyType == requestLegacyType - && otherRequest.isRequest()) { - if (DBG) log(" still have other legacy request - leaving"); - doRemove = false; - } - } - } - - if (doRemove) { - mLegacyTypeTracker.remove(requestLegacyType, nai, false); - } - } - } - } - - private PerUidCounter getRequestCounter(NetworkRequestInfo nri) { - return checkAnyPermissionOf( - nri.mPid, nri.mUid, NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) - ? mSystemNetworkRequestCounter : mNetworkRequestCounter; - } - - @Override - public void setAcceptUnvalidated(Network network, boolean accept, boolean always) { - enforceNetworkStackSettingsOrSetup(); - mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_ACCEPT_UNVALIDATED, - encodeBool(accept), encodeBool(always), network)); - } - - @Override - public void setAcceptPartialConnectivity(Network network, boolean accept, boolean always) { - enforceNetworkStackSettingsOrSetup(); - mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_ACCEPT_PARTIAL_CONNECTIVITY, - encodeBool(accept), encodeBool(always), network)); - } - - @Override - public void setAvoidUnvalidated(Network network) { - enforceNetworkStackSettingsOrSetup(); - mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_AVOID_UNVALIDATED, network)); - } - - private void handleSetAcceptUnvalidated(Network network, boolean accept, boolean always) { - if (DBG) log("handleSetAcceptUnvalidated network=" + network + - " accept=" + accept + " always=" + always); - - NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network); - if (nai == null) { - // Nothing to do. - return; - } - - if (nai.everValidated) { - // The network validated while the dialog box was up. Take no action. - return; - } - - if (!nai.networkAgentConfig.explicitlySelected) { - Log.wtf(TAG, "BUG: setAcceptUnvalidated non non-explicitly selected network"); - } - - if (accept != nai.networkAgentConfig.acceptUnvalidated) { - nai.networkAgentConfig.acceptUnvalidated = accept; - // If network becomes partial connectivity and user already accepted to use this - // network, we should respect the user's option and don't need to popup the - // PARTIAL_CONNECTIVITY notification to user again. - nai.networkAgentConfig.acceptPartialConnectivity = accept; - nai.updateScoreForNetworkAgentUpdate(); - rematchAllNetworksAndRequests(); - } - - if (always) { - nai.onSaveAcceptUnvalidated(accept); - } - - if (!accept) { - // Tell the NetworkAgent to not automatically reconnect to the network. - nai.onPreventAutomaticReconnect(); - // Teardown the network. - teardownUnneededNetwork(nai); - } - - } - - private void handleSetAcceptPartialConnectivity(Network network, boolean accept, - boolean always) { - if (DBG) { - log("handleSetAcceptPartialConnectivity network=" + network + " accept=" + accept - + " always=" + always); - } - - final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network); - if (nai == null) { - // Nothing to do. - return; - } - - if (nai.lastValidated) { - // The network validated while the dialog box was up. Take no action. - return; - } - - if (accept != nai.networkAgentConfig.acceptPartialConnectivity) { - nai.networkAgentConfig.acceptPartialConnectivity = accept; - } - - // TODO: Use the current design or save the user choice into IpMemoryStore. - if (always) { - nai.onSaveAcceptUnvalidated(accept); - } - - if (!accept) { - // Tell the NetworkAgent to not automatically reconnect to the network. - nai.onPreventAutomaticReconnect(); - // Tear down the network. - teardownUnneededNetwork(nai); - } else { - // Inform NetworkMonitor that partial connectivity is acceptable. This will likely - // result in a partial connectivity result which will be processed by - // maybeHandleNetworkMonitorMessage. - // - // TODO: NetworkMonitor does not refer to the "never ask again" bit. The bit is stored - // per network. Therefore, NetworkMonitor may still do https probe. - nai.networkMonitor().setAcceptPartialConnectivity(); - } - } - - private void handleSetAvoidUnvalidated(Network network) { - NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network); - if (nai == null || nai.lastValidated) { - // Nothing to do. The network either disconnected or revalidated. - return; - } - if (!nai.avoidUnvalidated) { - nai.avoidUnvalidated = true; - nai.updateScoreForNetworkAgentUpdate(); - rematchAllNetworksAndRequests(); - } - } - - private void scheduleUnvalidatedPrompt(NetworkAgentInfo nai) { - if (VDBG) log("scheduleUnvalidatedPrompt " + nai.network); - mHandler.sendMessageDelayed( - mHandler.obtainMessage(EVENT_PROMPT_UNVALIDATED, nai.network), - PROMPT_UNVALIDATED_DELAY_MS); - } - - @Override - public void startCaptivePortalApp(Network network) { - enforceNetworkStackOrSettingsPermission(); - mHandler.post(() -> { - NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network); - if (nai == null) return; - if (!nai.networkCapabilities.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL)) return; - nai.networkMonitor().launchCaptivePortalApp(); - }); - } - - /** - * NetworkStack endpoint to start the captive portal app. The NetworkStack needs to use this - * endpoint as it does not have INTERACT_ACROSS_USERS_FULL itself. - * @param network Network on which the captive portal was detected. - * @param appExtras Bundle to use as intent extras for the captive portal application. - * Must be treated as opaque to avoid preventing the captive portal app to - * update its arguments. - */ - @Override - public void startCaptivePortalAppInternal(Network network, Bundle appExtras) { - mContext.enforceCallingOrSelfPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, - "ConnectivityService"); - - final Intent appIntent = new Intent(ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN); - appIntent.putExtras(appExtras); - appIntent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL, - new CaptivePortal(new CaptivePortalImpl(network).asBinder())); - appIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK); - - final long token = Binder.clearCallingIdentity(); - try { - mContext.startActivityAsUser(appIntent, UserHandle.CURRENT); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - private class CaptivePortalImpl extends ICaptivePortal.Stub { - private final Network mNetwork; - - private CaptivePortalImpl(Network network) { - mNetwork = network; - } - - @Override - public void appResponse(final int response) { - if (response == CaptivePortal.APP_RETURN_WANTED_AS_IS) { - enforceSettingsPermission(); - } - - final NetworkMonitorManager nm = getNetworkMonitorManager(mNetwork); - if (nm == null) return; - nm.notifyCaptivePortalAppFinished(response); - } - - @Override - public void appRequest(final int request) { - final NetworkMonitorManager nm = getNetworkMonitorManager(mNetwork); - if (nm == null) return; - - if (request == CaptivePortal.APP_REQUEST_REEVALUATION_REQUIRED) { - checkNetworkStackPermission(); - nm.forceReevaluation(mDeps.getCallingUid()); - } - } - - @Nullable - private NetworkMonitorManager getNetworkMonitorManager(final Network network) { - // getNetworkAgentInfoForNetwork is thread-safe - final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network); - if (nai == null) return null; - - // nai.networkMonitor() is thread-safe - return nai.networkMonitor(); - } - } - - public boolean avoidBadWifi() { - return mMultinetworkPolicyTracker.getAvoidBadWifi(); - } - - /** - * Return whether the device should maintain continuous, working connectivity by switching away - * from WiFi networks having no connectivity. - * @see MultinetworkPolicyTracker#getAvoidBadWifi() - */ - public boolean shouldAvoidBadWifi() { - if (!checkNetworkStackPermission()) { - throw new SecurityException("avoidBadWifi requires NETWORK_STACK permission"); - } - return avoidBadWifi(); - } - - private void updateAvoidBadWifi() { - for (final NetworkAgentInfo nai : mNetworkAgentInfos) { - nai.updateScoreForNetworkAgentUpdate(); - } - rematchAllNetworksAndRequests(); - } - - // TODO: Evaluate whether this is of interest to other consumers of - // MultinetworkPolicyTracker and worth moving out of here. - private void dumpAvoidBadWifiSettings(IndentingPrintWriter pw) { - final boolean configRestrict = mMultinetworkPolicyTracker.configRestrictsAvoidBadWifi(); - if (!configRestrict) { - pw.println("Bad Wi-Fi avoidance: unrestricted"); - return; - } - - pw.println("Bad Wi-Fi avoidance: " + avoidBadWifi()); - pw.increaseIndent(); - pw.println("Config restrict: " + configRestrict); - - final String value = mMultinetworkPolicyTracker.getAvoidBadWifiSetting(); - String description; - // Can't use a switch statement because strings are legal case labels, but null is not. - if ("0".equals(value)) { - description = "get stuck"; - } else if (value == null) { - description = "prompt"; - } else if ("1".equals(value)) { - description = "avoid"; - } else { - description = value + " (?)"; - } - pw.println("User setting: " + description); - pw.println("Network overrides:"); - pw.increaseIndent(); - for (NetworkAgentInfo nai : networksSortedById()) { - if (nai.avoidUnvalidated) { - pw.println(nai.toShortString()); - } - } - pw.decreaseIndent(); - pw.decreaseIndent(); - } - - // TODO: This method is copied from TetheringNotificationUpdater. Should have a utility class to - // unify the method. - private static @NonNull String getSettingsPackageName(@NonNull final PackageManager pm) { - final Intent settingsIntent = new Intent(Settings.ACTION_SETTINGS); - final ComponentName settingsComponent = settingsIntent.resolveActivity(pm); - return settingsComponent != null - ? settingsComponent.getPackageName() : "com.android.settings"; - } - - private void showNetworkNotification(NetworkAgentInfo nai, NotificationType type) { - final String action; - final boolean highPriority; - switch (type) { - case NO_INTERNET: - action = ConnectivityManager.ACTION_PROMPT_UNVALIDATED; - // High priority because it is only displayed for explicitly selected networks. - highPriority = true; - break; - case PRIVATE_DNS_BROKEN: - action = Settings.ACTION_WIRELESS_SETTINGS; - // High priority because we should let user know why there is no internet. - highPriority = true; - break; - case LOST_INTERNET: - action = ConnectivityManager.ACTION_PROMPT_LOST_VALIDATION; - // High priority because it could help the user avoid unexpected data usage. - highPriority = true; - break; - case PARTIAL_CONNECTIVITY: - action = ConnectivityManager.ACTION_PROMPT_PARTIAL_CONNECTIVITY; - // Don't bother the user with a high-priority notification if the network was not - // explicitly selected by the user. - highPriority = nai.networkAgentConfig.explicitlySelected; - break; - default: - Log.wtf(TAG, "Unknown notification type " + type); - return; - } - - Intent intent = new Intent(action); - if (type != NotificationType.PRIVATE_DNS_BROKEN) { - intent.putExtra(ConnectivityManager.EXTRA_NETWORK, nai.network); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - // Some OEMs have their own Settings package. Thus, need to get the current using - // Settings package name instead of just use default name "com.android.settings". - final String settingsPkgName = getSettingsPackageName(mContext.getPackageManager()); - intent.setClassName(settingsPkgName, - settingsPkgName + ".wifi.WifiNoInternetDialog"); - } - - PendingIntent pendingIntent = PendingIntent.getActivity( - mContext.createContextAsUser(UserHandle.CURRENT, 0 /* flags */), - 0 /* requestCode */, - intent, - PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE); - - mNotifier.showNotification( - nai.network.getNetId(), type, nai, null, pendingIntent, highPriority); - } - - private boolean shouldPromptUnvalidated(NetworkAgentInfo nai) { - // Don't prompt if the network is validated, and don't prompt on captive portals - // because we're already prompting the user to sign in. - if (nai.everValidated || nai.everCaptivePortalDetected) { - return false; - } - - // If a network has partial connectivity, always prompt unless the user has already accepted - // partial connectivity and selected don't ask again. This ensures that if the device - // automatically connects to a network that has partial Internet access, the user will - // always be able to use it, either because they've already chosen "don't ask again" or - // because we have prompt them. - if (nai.partialConnectivity && !nai.networkAgentConfig.acceptPartialConnectivity) { - return true; - } - - // If a network has no Internet access, only prompt if the network was explicitly selected - // and if the user has not already told us to use the network regardless of whether it - // validated or not. - if (nai.networkAgentConfig.explicitlySelected - && !nai.networkAgentConfig.acceptUnvalidated) { - return true; - } - - return false; - } - - private void handlePromptUnvalidated(Network network) { - if (VDBG || DDBG) log("handlePromptUnvalidated " + network); - NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network); - - if (nai == null || !shouldPromptUnvalidated(nai)) { - return; - } - - // Stop automatically reconnecting to this network in the future. Automatically connecting - // to a network that provides no or limited connectivity is not useful, because the user - // cannot use that network except through the notification shown by this method, and the - // notification is only shown if the network is explicitly selected by the user. - nai.onPreventAutomaticReconnect(); - - // TODO: Evaluate if it's needed to wait 8 seconds for triggering notification when - // NetworkMonitor detects the network is partial connectivity. Need to change the design to - // popup the notification immediately when the network is partial connectivity. - if (nai.partialConnectivity) { - showNetworkNotification(nai, NotificationType.PARTIAL_CONNECTIVITY); - } else { - showNetworkNotification(nai, NotificationType.NO_INTERNET); - } - } - - private void handleNetworkUnvalidated(NetworkAgentInfo nai) { - NetworkCapabilities nc = nai.networkCapabilities; - if (DBG) log("handleNetworkUnvalidated " + nai.toShortString() + " cap=" + nc); - - if (!nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { - return; - } - - if (mMultinetworkPolicyTracker.shouldNotifyWifiUnvalidated()) { - showNetworkNotification(nai, NotificationType.LOST_INTERNET); - } - } - - @Override - public int getMultipathPreference(Network network) { - enforceAccessPermission(); - - NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network); - if (nai != null && nai.networkCapabilities - .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)) { - return ConnectivityManager.MULTIPATH_PREFERENCE_UNMETERED; - } - - final NetworkPolicyManager netPolicyManager = - mContext.getSystemService(NetworkPolicyManager.class); - - final long token = Binder.clearCallingIdentity(); - final int networkPreference; - try { - networkPreference = netPolicyManager.getMultipathPreference(network); - } finally { - Binder.restoreCallingIdentity(token); - } - if (networkPreference != 0) { - return networkPreference; - } - return mMultinetworkPolicyTracker.getMeteredMultipathPreference(); - } - - @Override - public NetworkRequest getDefaultRequest() { - return mDefaultRequest.mRequests.get(0); - } - - private class InternalHandler extends Handler { - public InternalHandler(Looper looper) { - super(looper); - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case EVENT_EXPIRE_NET_TRANSITION_WAKELOCK: - case EVENT_CLEAR_NET_TRANSITION_WAKELOCK: { - handleReleaseNetworkTransitionWakelock(msg.what); - break; - } - case EVENT_APPLY_GLOBAL_HTTP_PROXY: { - mProxyTracker.loadDeprecatedGlobalHttpProxy(); - break; - } - case EVENT_PROXY_HAS_CHANGED: { - final Pair arg = (Pair) msg.obj; - handleApplyDefaultProxy(arg.second); - break; - } - case EVENT_REGISTER_NETWORK_PROVIDER: { - handleRegisterNetworkProvider((NetworkProviderInfo) msg.obj); - break; - } - case EVENT_UNREGISTER_NETWORK_PROVIDER: { - handleUnregisterNetworkProvider((Messenger) msg.obj); - break; - } - case EVENT_REGISTER_NETWORK_OFFER: { - handleRegisterNetworkOffer((NetworkOffer) msg.obj); - break; - } - case EVENT_UNREGISTER_NETWORK_OFFER: { - final NetworkOfferInfo offer = - findNetworkOfferInfoByCallback((INetworkOfferCallback) msg.obj); - if (null != offer) { - handleUnregisterNetworkOffer(offer); - } - break; - } - case EVENT_REGISTER_NETWORK_AGENT: { - final Pair arg = - (Pair) msg.obj; - handleRegisterNetworkAgent(arg.first, arg.second); - break; - } - case EVENT_REGISTER_NETWORK_REQUEST: - case EVENT_REGISTER_NETWORK_LISTENER: { - handleRegisterNetworkRequest((NetworkRequestInfo) msg.obj); - break; - } - case EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT: - case EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT: { - handleRegisterNetworkRequestWithIntent(msg); - break; - } - case EVENT_TIMEOUT_NETWORK_REQUEST: { - NetworkRequestInfo nri = (NetworkRequestInfo) msg.obj; - handleTimedOutNetworkRequest(nri); - break; - } - case EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT: { - handleReleaseNetworkRequestWithIntent((PendingIntent) msg.obj, msg.arg1); - break; - } - case EVENT_RELEASE_NETWORK_REQUEST: { - handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.arg1, - /* callOnUnavailable */ false); - break; - } - case EVENT_SET_ACCEPT_UNVALIDATED: { - Network network = (Network) msg.obj; - handleSetAcceptUnvalidated(network, toBool(msg.arg1), toBool(msg.arg2)); - break; - } - case EVENT_SET_ACCEPT_PARTIAL_CONNECTIVITY: { - Network network = (Network) msg.obj; - handleSetAcceptPartialConnectivity(network, toBool(msg.arg1), - toBool(msg.arg2)); - break; - } - case EVENT_SET_AVOID_UNVALIDATED: { - handleSetAvoidUnvalidated((Network) msg.obj); - break; - } - case EVENT_PROMPT_UNVALIDATED: { - handlePromptUnvalidated((Network) msg.obj); - break; - } - case EVENT_CONFIGURE_ALWAYS_ON_NETWORKS: { - handleConfigureAlwaysOnNetworks(); - break; - } - // Sent by KeepaliveTracker to process an app request on the state machine thread. - case NetworkAgent.CMD_START_SOCKET_KEEPALIVE: { - mKeepaliveTracker.handleStartKeepalive(msg); - break; - } - // Sent by KeepaliveTracker to process an app request on the state machine thread. - case NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE: { - NetworkAgentInfo nai = getNetworkAgentInfoForNetwork((Network) msg.obj); - int slot = msg.arg1; - int reason = msg.arg2; - mKeepaliveTracker.handleStopKeepalive(nai, slot, reason); - break; - } - case EVENT_REVALIDATE_NETWORK: { - handleReportNetworkConnectivity((Network) msg.obj, msg.arg1, toBool(msg.arg2)); - break; - } - case EVENT_PRIVATE_DNS_SETTINGS_CHANGED: - handlePrivateDnsSettingsChanged(); - break; - case EVENT_PRIVATE_DNS_VALIDATION_UPDATE: - handlePrivateDnsValidationUpdate( - (PrivateDnsValidationUpdate) msg.obj); - break; - case EVENT_UID_BLOCKED_REASON_CHANGED: - handleUidBlockedReasonChanged(msg.arg1, msg.arg2); - break; - case EVENT_SET_REQUIRE_VPN_FOR_UIDS: - handleSetRequireVpnForUids(toBool(msg.arg1), (UidRange[]) msg.obj); - break; - case EVENT_SET_OEM_NETWORK_PREFERENCE: { - final Pair arg = - (Pair) msg.obj; - handleSetOemNetworkPreference(arg.first, arg.second); - break; - } - case EVENT_SET_PROFILE_NETWORK_PREFERENCE: { - final Pair arg = - (Pair) - msg.obj; - handleSetProfileNetworkPreference(arg.first, arg.second); - break; - } - case EVENT_REPORT_NETWORK_ACTIVITY: - mNetworkActivityTracker.handleReportNetworkActivity(); - break; - } - } - } - - @Override - @Deprecated - public int getLastTetherError(String iface) { - final TetheringManager tm = (TetheringManager) mContext.getSystemService( - Context.TETHERING_SERVICE); - return tm.getLastTetherError(iface); - } - - @Override - @Deprecated - public String[] getTetherableIfaces() { - final TetheringManager tm = (TetheringManager) mContext.getSystemService( - Context.TETHERING_SERVICE); - return tm.getTetherableIfaces(); - } - - @Override - @Deprecated - public String[] getTetheredIfaces() { - final TetheringManager tm = (TetheringManager) mContext.getSystemService( - Context.TETHERING_SERVICE); - return tm.getTetheredIfaces(); - } - - - @Override - @Deprecated - public String[] getTetheringErroredIfaces() { - final TetheringManager tm = (TetheringManager) mContext.getSystemService( - Context.TETHERING_SERVICE); - - return tm.getTetheringErroredIfaces(); - } - - @Override - @Deprecated - public String[] getTetherableUsbRegexs() { - final TetheringManager tm = (TetheringManager) mContext.getSystemService( - Context.TETHERING_SERVICE); - - return tm.getTetherableUsbRegexs(); - } - - @Override - @Deprecated - public String[] getTetherableWifiRegexs() { - final TetheringManager tm = (TetheringManager) mContext.getSystemService( - Context.TETHERING_SERVICE); - return tm.getTetherableWifiRegexs(); - } - - // Called when we lose the default network and have no replacement yet. - // This will automatically be cleared after X seconds or a new default network - // becomes CONNECTED, whichever happens first. The timer is started by the - // first caller and not restarted by subsequent callers. - private void ensureNetworkTransitionWakelock(String forWhom) { - synchronized (this) { - if (mNetTransitionWakeLock.isHeld()) { - return; - } - mNetTransitionWakeLock.acquire(); - mLastWakeLockAcquireTimestamp = SystemClock.elapsedRealtime(); - mTotalWakelockAcquisitions++; - } - mWakelockLogs.log("ACQUIRE for " + forWhom); - Message msg = mHandler.obtainMessage(EVENT_EXPIRE_NET_TRANSITION_WAKELOCK); - final int lockTimeout = mResources.get().getInteger( - R.integer.config_networkTransitionTimeout); - mHandler.sendMessageDelayed(msg, lockTimeout); - } - - // Called when we gain a new default network to release the network transition wakelock in a - // second, to allow a grace period for apps to reconnect over the new network. Pending expiry - // message is cancelled. - private void scheduleReleaseNetworkTransitionWakelock() { - synchronized (this) { - if (!mNetTransitionWakeLock.isHeld()) { - return; // expiry message released the lock first. - } - } - // Cancel self timeout on wakelock hold. - mHandler.removeMessages(EVENT_EXPIRE_NET_TRANSITION_WAKELOCK); - Message msg = mHandler.obtainMessage(EVENT_CLEAR_NET_TRANSITION_WAKELOCK); - mHandler.sendMessageDelayed(msg, 1000); - } - - // Called when either message of ensureNetworkTransitionWakelock or - // scheduleReleaseNetworkTransitionWakelock is processed. - private void handleReleaseNetworkTransitionWakelock(int eventId) { - String event = eventName(eventId); - synchronized (this) { - if (!mNetTransitionWakeLock.isHeld()) { - mWakelockLogs.log(String.format("RELEASE: already released (%s)", event)); - Log.w(TAG, "expected Net Transition WakeLock to be held"); - return; - } - mNetTransitionWakeLock.release(); - long lockDuration = SystemClock.elapsedRealtime() - mLastWakeLockAcquireTimestamp; - mTotalWakelockDurationMs += lockDuration; - mMaxWakelockDurationMs = Math.max(mMaxWakelockDurationMs, lockDuration); - mTotalWakelockReleases++; - } - mWakelockLogs.log(String.format("RELEASE (%s)", event)); - } - - // 100 percent is full good, 0 is full bad. - @Override - public void reportInetCondition(int networkType, int percentage) { - NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType); - if (nai == null) return; - reportNetworkConnectivity(nai.network, percentage > 50); - } - - @Override - public void reportNetworkConnectivity(Network network, boolean hasConnectivity) { - enforceAccessPermission(); - enforceInternetPermission(); - final int uid = mDeps.getCallingUid(); - final int connectivityInfo = encodeBool(hasConnectivity); - - // Handle ConnectivityDiagnostics event before attempting to revalidate the network. This - // forces an ordering of ConnectivityDiagnostics events in the case where hasConnectivity - // does not match the known connectivity of the network - this causes NetworkMonitor to - // revalidate the network and generate a ConnectivityDiagnostics ConnectivityReport event. - final NetworkAgentInfo nai; - if (network == null) { - nai = getDefaultNetwork(); - } else { - nai = getNetworkAgentInfoForNetwork(network); - } - if (nai != null) { - mConnectivityDiagnosticsHandler.sendMessage( - mConnectivityDiagnosticsHandler.obtainMessage( - ConnectivityDiagnosticsHandler.EVENT_NETWORK_CONNECTIVITY_REPORTED, - connectivityInfo, 0, nai)); - } - - mHandler.sendMessage( - mHandler.obtainMessage(EVENT_REVALIDATE_NETWORK, uid, connectivityInfo, network)); - } - - private void handleReportNetworkConnectivity( - Network network, int uid, boolean hasConnectivity) { - final NetworkAgentInfo nai; - if (network == null) { - nai = getDefaultNetwork(); - } else { - nai = getNetworkAgentInfoForNetwork(network); - } - if (nai == null || nai.networkInfo.getState() == NetworkInfo.State.DISCONNECTING || - nai.networkInfo.getState() == NetworkInfo.State.DISCONNECTED) { - return; - } - // Revalidate if the app report does not match our current validated state. - if (hasConnectivity == nai.lastValidated) { - return; - } - if (DBG) { - int netid = nai.network.getNetId(); - log("reportNetworkConnectivity(" + netid + ", " + hasConnectivity + ") by " + uid); - } - // Validating a network that has not yet connected could result in a call to - // rematchNetworkAndRequests() which is not meant to work on such networks. - if (!nai.everConnected) { - return; - } - final NetworkCapabilities nc = getNetworkCapabilitiesInternal(nai); - if (isNetworkWithCapabilitiesBlocked(nc, uid, false)) { - return; - } - nai.networkMonitor().forceReevaluation(uid); - } - - // TODO: call into netd. - private boolean queryUserAccess(int uid, Network network) { - final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network); - if (nai == null) return false; - - // Any UID can use its default network. - if (nai == getDefaultNetworkForUid(uid)) return true; - - // Privileged apps can use any network. - if (mPermissionMonitor.hasRestrictedNetworksPermission(uid)) { - return true; - } - - // An unprivileged UID can use a VPN iff the VPN applies to it. - if (nai.isVPN()) { - return nai.networkCapabilities.appliesToUid(uid); - } - - // An unprivileged UID can bypass the VPN that applies to it only if it can protect its - // sockets, i.e., if it is the owner. - final NetworkAgentInfo vpn = getVpnForUid(uid); - if (vpn != null && !vpn.networkAgentConfig.allowBypass - && uid != vpn.networkCapabilities.getOwnerUid()) { - return false; - } - - // The UID's permission must be at least sufficient for the network. Since the restricted - // permission was already checked above, that just leaves background networks. - if (!nai.networkCapabilities.hasCapability(NET_CAPABILITY_FOREGROUND)) { - return mPermissionMonitor.hasUseBackgroundNetworksPermission(uid); - } - - // Unrestricted network. Anyone gets to use it. - return true; - } - - /** - * Returns information about the proxy a certain network is using. If given a null network, it - * it will return the proxy for the bound network for the caller app or the default proxy if - * none. - * - * @param network the network we want to get the proxy information for. - * @return Proxy information if a network has a proxy configured, or otherwise null. - */ - @Override - public ProxyInfo getProxyForNetwork(Network network) { - final ProxyInfo globalProxy = mProxyTracker.getGlobalProxy(); - if (globalProxy != null) return globalProxy; - if (network == null) { - // Get the network associated with the calling UID. - final Network activeNetwork = getActiveNetworkForUidInternal(mDeps.getCallingUid(), - true); - if (activeNetwork == null) { - return null; - } - return getLinkPropertiesProxyInfo(activeNetwork); - } else if (mDeps.queryUserAccess(mDeps.getCallingUid(), network, this)) { - // Don't call getLinkProperties() as it requires ACCESS_NETWORK_STATE permission, which - // caller may not have. - return getLinkPropertiesProxyInfo(network); - } - // No proxy info available if the calling UID does not have network access. - return null; - } - - - private ProxyInfo getLinkPropertiesProxyInfo(Network network) { - final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network); - if (nai == null) return null; - synchronized (nai) { - final ProxyInfo linkHttpProxy = nai.linkProperties.getHttpProxy(); - return linkHttpProxy == null ? null : new ProxyInfo(linkHttpProxy); - } - } - - @Override - public void setGlobalProxy(@Nullable final ProxyInfo proxyProperties) { - PermissionUtils.enforceNetworkStackPermission(mContext); - mProxyTracker.setGlobalProxy(proxyProperties); - } - - @Override - @Nullable - public ProxyInfo getGlobalProxy() { - return mProxyTracker.getGlobalProxy(); - } - - private void handleApplyDefaultProxy(ProxyInfo proxy) { - if (proxy != null && TextUtils.isEmpty(proxy.getHost()) - && Uri.EMPTY.equals(proxy.getPacFileUrl())) { - proxy = null; - } - mProxyTracker.setDefaultProxy(proxy); - } - - // If the proxy has changed from oldLp to newLp, resend proxy broadcast. This method gets called - // when any network changes proxy. - // TODO: Remove usage of broadcast extras as they are deprecated and not applicable in a - // multi-network world where an app might be bound to a non-default network. - private void updateProxy(LinkProperties newLp, LinkProperties oldLp) { - ProxyInfo newProxyInfo = newLp == null ? null : newLp.getHttpProxy(); - ProxyInfo oldProxyInfo = oldLp == null ? null : oldLp.getHttpProxy(); - - if (!ProxyTracker.proxyInfoEqual(newProxyInfo, oldProxyInfo)) { - mProxyTracker.sendProxyBroadcast(); - } - } - - private static class SettingsObserver extends ContentObserver { - final private HashMap mUriEventMap; - final private Context mContext; - final private Handler mHandler; - - SettingsObserver(Context context, Handler handler) { - super(null); - mUriEventMap = new HashMap<>(); - mContext = context; - mHandler = handler; - } - - void observe(Uri uri, int what) { - mUriEventMap.put(uri, what); - final ContentResolver resolver = mContext.getContentResolver(); - resolver.registerContentObserver(uri, false, this); - } - - @Override - public void onChange(boolean selfChange) { - Log.wtf(TAG, "Should never be reached."); - } - - @Override - public void onChange(boolean selfChange, Uri uri) { - final Integer what = mUriEventMap.get(uri); - if (what != null) { - mHandler.obtainMessage(what).sendToTarget(); - } else { - loge("No matching event to send for URI=" + uri); - } - } - } - - private static void log(String s) { - Log.d(TAG, s); - } - - private static void logw(String s) { - Log.w(TAG, s); - } - - private static void logwtf(String s) { - Log.wtf(TAG, s); - } - - private static void logwtf(String s, Throwable t) { - Log.wtf(TAG, s, t); - } - - private static void loge(String s) { - Log.e(TAG, s); - } - - private static void loge(String s, Throwable t) { - Log.e(TAG, s, t); - } - - /** - * Return the information of all ongoing VPNs. - * - *

      This method is used to update NetworkStatsService. - * - *

      Must be called on the handler thread. - */ - private UnderlyingNetworkInfo[] getAllVpnInfo() { - ensureRunningOnConnectivityServiceThread(); - if (mLockdownEnabled) { - return new UnderlyingNetworkInfo[0]; - } - List infoList = new ArrayList<>(); - for (NetworkAgentInfo nai : mNetworkAgentInfos) { - UnderlyingNetworkInfo info = createVpnInfo(nai); - if (info != null) { - infoList.add(info); - } - } - return infoList.toArray(new UnderlyingNetworkInfo[infoList.size()]); - } - - /** - * @return VPN information for accounting, or null if we can't retrieve all required - * information, e.g underlying ifaces. - */ - private UnderlyingNetworkInfo createVpnInfo(NetworkAgentInfo nai) { - if (!nai.isVPN()) return null; - - Network[] underlyingNetworks = nai.declaredUnderlyingNetworks; - // see VpnService.setUnderlyingNetworks()'s javadoc about how to interpret - // the underlyingNetworks list. - if (underlyingNetworks == null) { - final NetworkAgentInfo defaultNai = getDefaultNetworkForUid( - nai.networkCapabilities.getOwnerUid()); - if (defaultNai != null) { - underlyingNetworks = new Network[] { defaultNai.network }; - } - } - - if (CollectionUtils.isEmpty(underlyingNetworks)) return null; - - List interfaces = new ArrayList<>(); - for (Network network : underlyingNetworks) { - NetworkAgentInfo underlyingNai = getNetworkAgentInfoForNetwork(network); - if (underlyingNai == null) continue; - LinkProperties lp = underlyingNai.linkProperties; - for (String iface : lp.getAllInterfaceNames()) { - if (!TextUtils.isEmpty(iface)) { - interfaces.add(iface); - } - } - } - - if (interfaces.isEmpty()) return null; - - // Must be non-null or NetworkStatsService will crash. - // Cannot happen in production code because Vpn only registers the NetworkAgent after the - // tun or ipsec interface is created. - // TODO: Remove this check. - if (nai.linkProperties.getInterfaceName() == null) return null; - - return new UnderlyingNetworkInfo(nai.networkCapabilities.getOwnerUid(), - nai.linkProperties.getInterfaceName(), interfaces); - } - - // TODO This needs to be the default network that applies to the NAI. - private Network[] underlyingNetworksOrDefault(final int ownerUid, - Network[] underlyingNetworks) { - final Network defaultNetwork = getNetwork(getDefaultNetworkForUid(ownerUid)); - if (underlyingNetworks == null && defaultNetwork != null) { - // null underlying networks means to track the default. - underlyingNetworks = new Network[] { defaultNetwork }; - } - return underlyingNetworks; - } - - // Returns true iff |network| is an underlying network of |nai|. - private boolean hasUnderlyingNetwork(NetworkAgentInfo nai, Network network) { - // TODO: support more than one level of underlying networks, either via a fixed-depth search - // (e.g., 2 levels of underlying networks), or via loop detection, or.... - if (!nai.supportsUnderlyingNetworks()) return false; - final Network[] underlying = underlyingNetworksOrDefault( - nai.networkCapabilities.getOwnerUid(), nai.declaredUnderlyingNetworks); - return CollectionUtils.contains(underlying, network); - } - - /** - * Recompute the capabilities for any networks that had a specific network as underlying. - * - * When underlying networks change, such networks may have to update capabilities to reflect - * things like the metered bit, their transports, and so on. The capabilities are calculated - * immediately. This method runs on the ConnectivityService thread. - */ - private void propagateUnderlyingNetworkCapabilities(Network updatedNetwork) { - ensureRunningOnConnectivityServiceThread(); - for (NetworkAgentInfo nai : mNetworkAgentInfos) { - if (updatedNetwork == null || hasUnderlyingNetwork(nai, updatedNetwork)) { - updateCapabilitiesForNetwork(nai); - } - } - } - - private boolean isUidBlockedByVpn(int uid, List blockedUidRanges) { - // Determine whether this UID is blocked because of always-on VPN lockdown. If a VPN applies - // to the UID, then the UID is not blocked because always-on VPN lockdown applies only when - // a VPN is not up. - final NetworkAgentInfo vpnNai = getVpnForUid(uid); - if (vpnNai != null && !vpnNai.networkAgentConfig.allowBypass) return false; - for (UidRange range : blockedUidRanges) { - if (range.contains(uid)) return true; - } - return false; - } - - @Override - public void setRequireVpnForUids(boolean requireVpn, UidRange[] ranges) { - enforceNetworkStackOrSettingsPermission(); - mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_REQUIRE_VPN_FOR_UIDS, - encodeBool(requireVpn), 0 /* arg2 */, ranges)); - } - - private void handleSetRequireVpnForUids(boolean requireVpn, UidRange[] ranges) { - if (DBG) { - Log.d(TAG, "Setting VPN " + (requireVpn ? "" : "not ") + "required for UIDs: " - + Arrays.toString(ranges)); - } - // Cannot use a Set since the list of UID ranges might contain duplicates. - final List newVpnBlockedUidRanges = new ArrayList(mVpnBlockedUidRanges); - for (int i = 0; i < ranges.length; i++) { - if (requireVpn) { - newVpnBlockedUidRanges.add(ranges[i]); - } else { - newVpnBlockedUidRanges.remove(ranges[i]); - } - } - - try { - mNetd.networkRejectNonSecureVpn(requireVpn, toUidRangeStableParcels(ranges)); - } catch (RemoteException | ServiceSpecificException e) { - Log.e(TAG, "setRequireVpnForUids(" + requireVpn + ", " - + Arrays.toString(ranges) + "): netd command failed: " + e); - } - - for (final NetworkAgentInfo nai : mNetworkAgentInfos) { - final boolean curMetered = nai.networkCapabilities.isMetered(); - maybeNotifyNetworkBlocked(nai, curMetered, curMetered, - mVpnBlockedUidRanges, newVpnBlockedUidRanges); - } - - mVpnBlockedUidRanges = newVpnBlockedUidRanges; - } - - @Override - public void setLegacyLockdownVpnEnabled(boolean enabled) { - enforceNetworkStackOrSettingsPermission(); - mHandler.post(() -> mLockdownEnabled = enabled); - } - - private boolean isLegacyLockdownNai(NetworkAgentInfo nai) { - return mLockdownEnabled - && getVpnType(nai) == VpnManager.TYPE_VPN_LEGACY - && nai.networkCapabilities.appliesToUid(Process.FIRST_APPLICATION_UID); - } - - private NetworkAgentInfo getLegacyLockdownNai() { - if (!mLockdownEnabled) { - return null; - } - // The legacy lockdown VPN always only applies to userId 0. - final NetworkAgentInfo nai = getVpnForUid(Process.FIRST_APPLICATION_UID); - if (nai == null || !isLegacyLockdownNai(nai)) return null; - - // The legacy lockdown VPN must always have exactly one underlying network. - // This code may run on any thread and declaredUnderlyingNetworks may change, so store it in - // a local variable. There is no need to make a copy because its contents cannot change. - final Network[] underlying = nai.declaredUnderlyingNetworks; - if (underlying == null || underlying.length != 1) { - return null; - } - - // The legacy lockdown VPN always uses the default network. - // If the VPN's underlying network is no longer the current default network, it means that - // the default network has just switched, and the VPN is about to disconnect. - // Report that the VPN is not connected, so the state of NetworkInfo objects overwritten - // by filterForLegacyLockdown will be set to CONNECTING and not CONNECTED. - final NetworkAgentInfo defaultNetwork = getDefaultNetwork(); - if (defaultNetwork == null || !defaultNetwork.network.equals(underlying[0])) { - return null; - } - - return nai; - }; - - // TODO: move all callers to filterForLegacyLockdown and delete this method. - // This likely requires making sendLegacyNetworkBroadcast take a NetworkInfo object instead of - // just a DetailedState object. - private DetailedState getLegacyLockdownState(DetailedState origState) { - if (origState != DetailedState.CONNECTED) { - return origState; - } - return (mLockdownEnabled && getLegacyLockdownNai() == null) - ? DetailedState.CONNECTING - : DetailedState.CONNECTED; - } - - private void filterForLegacyLockdown(NetworkInfo ni) { - if (!mLockdownEnabled || !ni.isConnected()) return; - // The legacy lockdown VPN replaces the state of every network in CONNECTED state with the - // state of its VPN. This is to ensure that when an underlying network connects, apps will - // not see a CONNECTIVITY_ACTION broadcast for a network in state CONNECTED until the VPN - // comes up, at which point there is a new CONNECTIVITY_ACTION broadcast for the underlying - // network, this time with a state of CONNECTED. - // - // Now that the legacy lockdown code lives in ConnectivityService, and no longer has access - // to the internal state of the Vpn object, always replace the state with CONNECTING. This - // is not too far off the truth, since an always-on VPN, when not connected, is always - // trying to reconnect. - if (getLegacyLockdownNai() == null) { - ni.setDetailedState(DetailedState.CONNECTING, "", null); - } - } - - @Override - public void setProvisioningNotificationVisible(boolean visible, int networkType, - String action) { - enforceSettingsPermission(); - if (!ConnectivityManager.isNetworkTypeValid(networkType)) { - return; - } - final long ident = Binder.clearCallingIdentity(); - try { - // Concatenate the range of types onto the range of NetIDs. - int id = NetIdManager.MAX_NET_ID + 1 + (networkType - ConnectivityManager.TYPE_NONE); - mNotifier.setProvNotificationVisible(visible, id, action); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - @Override - public void setAirplaneMode(boolean enable) { - enforceAirplaneModePermission(); - final long ident = Binder.clearCallingIdentity(); - try { - final ContentResolver cr = mContext.getContentResolver(); - Settings.Global.putInt(cr, Settings.Global.AIRPLANE_MODE_ON, encodeBool(enable)); - Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); - intent.putExtra("state", enable); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - private void onUserAdded(@NonNull final UserHandle user) { - mPermissionMonitor.onUserAdded(user); - if (mOemNetworkPreferences.getNetworkPreferences().size() > 0) { - handleSetOemNetworkPreference(mOemNetworkPreferences, null); - } - } - - private void onUserRemoved(@NonNull final UserHandle user) { - mPermissionMonitor.onUserRemoved(user); - // If there was a network preference for this user, remove it. - handleSetProfileNetworkPreference(new ProfileNetworkPreferences.Preference(user, null), - null /* listener */); - if (mOemNetworkPreferences.getNetworkPreferences().size() > 0) { - handleSetOemNetworkPreference(mOemNetworkPreferences, null); - } - } - - private void onPackageChanged(@NonNull final String packageName) { - // This is necessary in case a package is added or removed, but also when it's replaced to - // run as a new UID by its manifest rules. Also, if a separate package shares the same UID - // as one in the preferences, then it should follow the same routing as that other package, - // which means updating the rules is never to be needed in this case (whether it joins or - // leaves a UID with a preference). - if (isMappedInOemNetworkPreference(packageName)) { - handleSetOemNetworkPreference(mOemNetworkPreferences, null); - } - } - - private final BroadcastReceiver mUserIntentReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - ensureRunningOnConnectivityServiceThread(); - final String action = intent.getAction(); - final UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER); - - // User should be filled for below intents, check the existence. - if (user == null) { - Log.wtf(TAG, intent.getAction() + " broadcast without EXTRA_USER"); - return; - } - - if (Intent.ACTION_USER_ADDED.equals(action)) { - onUserAdded(user); - } else if (Intent.ACTION_USER_REMOVED.equals(action)) { - onUserRemoved(user); - } else { - Log.wtf(TAG, "received unexpected intent: " + action); - } - } - }; - - private final BroadcastReceiver mPackageIntentReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - ensureRunningOnConnectivityServiceThread(); - switch (intent.getAction()) { - case Intent.ACTION_PACKAGE_ADDED: - case Intent.ACTION_PACKAGE_REMOVED: - case Intent.ACTION_PACKAGE_REPLACED: - onPackageChanged(intent.getData().getSchemeSpecificPart()); - break; - default: - Log.wtf(TAG, "received unexpected intent: " + intent.getAction()); - } - } - }; - - private final HashMap mNetworkProviderInfos = new HashMap<>(); - private final HashMap mNetworkRequests = new HashMap<>(); - - private static class NetworkProviderInfo { - public final String name; - public final Messenger messenger; - private final IBinder.DeathRecipient mDeathRecipient; - public final int providerId; - - NetworkProviderInfo(String name, Messenger messenger, int providerId, - @NonNull IBinder.DeathRecipient deathRecipient) { - this.name = name; - this.messenger = messenger; - this.providerId = providerId; - mDeathRecipient = deathRecipient; - - if (mDeathRecipient == null) { - throw new AssertionError("Must pass a deathRecipient"); - } - } - - void connect(Context context, Handler handler) { - try { - messenger.getBinder().linkToDeath(mDeathRecipient, 0); - } catch (RemoteException e) { - mDeathRecipient.binderDied(); - } - } - } - - private void ensureAllNetworkRequestsHaveType(List requests) { - for (int i = 0; i < requests.size(); i++) { - ensureNetworkRequestHasType(requests.get(i)); - } - } - - private void ensureNetworkRequestHasType(NetworkRequest request) { - if (request.type == NetworkRequest.Type.NONE) { - throw new IllegalArgumentException( - "All NetworkRequests in ConnectivityService must have a type"); - } - } - - /** - * Tracks info about the requester. - * Also used to notice when the calling process dies so as to self-expire - */ - @VisibleForTesting - protected class NetworkRequestInfo implements IBinder.DeathRecipient { - // The requests to be satisfied in priority order. Non-multilayer requests will only have a - // single NetworkRequest in mRequests. - final List mRequests; - - // mSatisfier and mActiveRequest rely on one another therefore set them together. - void setSatisfier( - @Nullable final NetworkAgentInfo satisfier, - @Nullable final NetworkRequest activeRequest) { - mSatisfier = satisfier; - mActiveRequest = activeRequest; - } - - // The network currently satisfying this NRI. Only one request in an NRI can have a - // satisfier. For non-multilayer requests, only non-listen requests can have a satisfier. - @Nullable - private NetworkAgentInfo mSatisfier; - NetworkAgentInfo getSatisfier() { - return mSatisfier; - } - - // The request in mRequests assigned to a network agent. This is null if none of the - // requests in mRequests can be satisfied. This member has the constraint of only being - // accessible on the handler thread. - @Nullable - private NetworkRequest mActiveRequest; - NetworkRequest getActiveRequest() { - return mActiveRequest; - } - - final PendingIntent mPendingIntent; - boolean mPendingIntentSent; - @Nullable - final Messenger mMessenger; - - // Information about the caller that caused this object to be created. - @Nullable - private final IBinder mBinder; - final int mPid; - final int mUid; - final @NetworkCallback.Flag int mCallbackFlags; - @Nullable - final String mCallingAttributionTag; - - // Counter keeping track of this NRI. - final PerUidCounter mPerUidCounter; - - // Effective UID of this request. This is different from mUid when a privileged process - // files a request on behalf of another UID. This UID is used to determine blocked status, - // UID matching, and so on. mUid above is used for permission checks and to enforce the - // maximum limit of registered callbacks per UID. - final int mAsUid; - - // In order to preserve the mapping of NetworkRequest-to-callback when apps register - // callbacks using a returned NetworkRequest, the original NetworkRequest needs to be - // maintained for keying off of. This is only a concern when the original nri - // mNetworkRequests changes which happens currently for apps that register callbacks to - // track the default network. In those cases, the nri is updated to have mNetworkRequests - // that match the per-app default nri that currently tracks the calling app's uid so that - // callbacks are fired at the appropriate time. When the callbacks fire, - // mNetworkRequestForCallback will be used so as to preserve the caller's mapping. When - // callbacks are updated to key off of an nri vs NetworkRequest, this stops being an issue. - // TODO b/177608132: make sure callbacks are indexed by NRIs and not NetworkRequest objects. - @NonNull - private final NetworkRequest mNetworkRequestForCallback; - NetworkRequest getNetworkRequestForCallback() { - return mNetworkRequestForCallback; - } - - /** - * Get the list of UIDs this nri applies to. - */ - @NonNull - private Set getUids() { - // networkCapabilities.getUids() returns a defensive copy. - // multilayer requests will all have the same uids so return the first one. - final Set uids = mRequests.get(0).networkCapabilities.getUidRanges(); - return (null == uids) ? new ArraySet<>() : uids; - } - - NetworkRequestInfo(int asUid, @NonNull final NetworkRequest r, - @Nullable final PendingIntent pi, @Nullable String callingAttributionTag) { - this(asUid, Collections.singletonList(r), r, pi, callingAttributionTag); - } - - NetworkRequestInfo(int asUid, @NonNull final List r, - @NonNull final NetworkRequest requestForCallback, @Nullable final PendingIntent pi, - @Nullable String callingAttributionTag) { - ensureAllNetworkRequestsHaveType(r); - mRequests = initializeRequests(r); - mNetworkRequestForCallback = requestForCallback; - mPendingIntent = pi; - mMessenger = null; - mBinder = null; - mPid = getCallingPid(); - mUid = mDeps.getCallingUid(); - mAsUid = asUid; - mPerUidCounter = getRequestCounter(this); - mPerUidCounter.incrementCountOrThrow(mUid); - /** - * Location sensitive data not included in pending intent. Only included in - * {@link NetworkCallback}. - */ - mCallbackFlags = NetworkCallback.FLAG_NONE; - mCallingAttributionTag = callingAttributionTag; - } - - NetworkRequestInfo(int asUid, @NonNull final NetworkRequest r, @Nullable final Messenger m, - @Nullable final IBinder binder, - @NetworkCallback.Flag int callbackFlags, - @Nullable String callingAttributionTag) { - this(asUid, Collections.singletonList(r), r, m, binder, callbackFlags, - callingAttributionTag); - } - - NetworkRequestInfo(int asUid, @NonNull final List r, - @NonNull final NetworkRequest requestForCallback, @Nullable final Messenger m, - @Nullable final IBinder binder, - @NetworkCallback.Flag int callbackFlags, - @Nullable String callingAttributionTag) { - super(); - ensureAllNetworkRequestsHaveType(r); - mRequests = initializeRequests(r); - mNetworkRequestForCallback = requestForCallback; - mMessenger = m; - mBinder = binder; - mPid = getCallingPid(); - mUid = mDeps.getCallingUid(); - mAsUid = asUid; - mPendingIntent = null; - mPerUidCounter = getRequestCounter(this); - mPerUidCounter.incrementCountOrThrow(mUid); - mCallbackFlags = callbackFlags; - mCallingAttributionTag = callingAttributionTag; - linkDeathRecipient(); - } - - NetworkRequestInfo(@NonNull final NetworkRequestInfo nri, - @NonNull final List r) { - super(); - ensureAllNetworkRequestsHaveType(r); - mRequests = initializeRequests(r); - mNetworkRequestForCallback = nri.getNetworkRequestForCallback(); - final NetworkAgentInfo satisfier = nri.getSatisfier(); - if (null != satisfier) { - // If the old NRI was satisfied by an NAI, then it may have had an active request. - // The active request is necessary to figure out what callbacks to send, in - // particular then a network updates its capabilities. - // As this code creates a new NRI with a new set of requests, figure out which of - // the list of requests should be the active request. It is always the first - // request of the list that can be satisfied by the satisfier since the order of - // requests is a priority order. - // Note even in the presence of a satisfier there may not be an active request, - // when the satisfier is the no-service network. - NetworkRequest activeRequest = null; - for (final NetworkRequest candidate : r) { - if (candidate.canBeSatisfiedBy(satisfier.networkCapabilities)) { - activeRequest = candidate; - break; - } - } - setSatisfier(satisfier, activeRequest); - } - mMessenger = nri.mMessenger; - mBinder = nri.mBinder; - mPid = nri.mPid; - mUid = nri.mUid; - mAsUid = nri.mAsUid; - mPendingIntent = nri.mPendingIntent; - mPerUidCounter = getRequestCounter(this); - mPerUidCounter.incrementCountOrThrow(mUid); - mCallbackFlags = nri.mCallbackFlags; - mCallingAttributionTag = nri.mCallingAttributionTag; - linkDeathRecipient(); - } - - NetworkRequestInfo(int asUid, @NonNull final NetworkRequest r) { - this(asUid, Collections.singletonList(r)); - } - - NetworkRequestInfo(int asUid, @NonNull final List r) { - this(asUid, r, r.get(0), null /* pi */, null /* callingAttributionTag */); - } - - // True if this NRI is being satisfied. It also accounts for if the nri has its satisifer - // set to the mNoServiceNetwork in which case mActiveRequest will be null thus returning - // false. - boolean isBeingSatisfied() { - return (null != mSatisfier && null != mActiveRequest); - } - - boolean isMultilayerRequest() { - return mRequests.size() > 1; - } - - private List initializeRequests(List r) { - // Creating a defensive copy to prevent the sender from modifying the list being - // reflected in the return value of this method. - final List tempRequests = new ArrayList<>(r); - return Collections.unmodifiableList(tempRequests); - } - - void decrementRequestCount() { - mPerUidCounter.decrementCount(mUid); - } - - void linkDeathRecipient() { - if (null != mBinder) { - try { - mBinder.linkToDeath(this, 0); - } catch (RemoteException e) { - binderDied(); - } - } - } - - void unlinkDeathRecipient() { - if (null != mBinder) { - mBinder.unlinkToDeath(this, 0); - } - } - - @Override - public void binderDied() { - log("ConnectivityService NetworkRequestInfo binderDied(" + - mRequests + ", " + mBinder + ")"); - releaseNetworkRequests(mRequests); - } - - @Override - public String toString() { - final String asUidString = (mAsUid == mUid) ? "" : " asUid: " + mAsUid; - return "uid/pid:" + mUid + "/" + mPid + asUidString + " activeRequest: " - + (mActiveRequest == null ? null : mActiveRequest.requestId) - + " callbackRequest: " - + mNetworkRequestForCallback.requestId - + " " + mRequests - + (mPendingIntent == null ? "" : " to trigger " + mPendingIntent) - + " callback flags: " + mCallbackFlags; - } - } - - private void ensureRequestableCapabilities(NetworkCapabilities networkCapabilities) { - final String badCapability = networkCapabilities.describeFirstNonRequestableCapability(); - if (badCapability != null) { - throw new IllegalArgumentException("Cannot request network with " + badCapability); - } - } - - // This checks that the passed capabilities either do not request a - // specific SSID/SignalStrength, or the calling app has permission to do so. - private void ensureSufficientPermissionsForRequest(NetworkCapabilities nc, - int callerPid, int callerUid, String callerPackageName) { - if (null != nc.getSsid() && !checkSettingsPermission(callerPid, callerUid)) { - throw new SecurityException("Insufficient permissions to request a specific SSID"); - } - - if (nc.hasSignalStrength() - && !checkNetworkSignalStrengthWakeupPermission(callerPid, callerUid)) { - throw new SecurityException( - "Insufficient permissions to request a specific signal strength"); - } - mAppOpsManager.checkPackage(callerUid, callerPackageName); - - if (!nc.getSubscriptionIds().isEmpty()) { - enforceNetworkFactoryPermission(); - } - } - - private int[] getSignalStrengthThresholds(@NonNull final NetworkAgentInfo nai) { - final SortedSet thresholds = new TreeSet<>(); - synchronized (nai) { - // mNetworkRequests may contain the same value multiple times in case of - // multilayer requests. It won't matter in this case because the thresholds - // will then be the same and be deduplicated as they enter the `thresholds` set. - // TODO : have mNetworkRequests be a Set or the like. - for (final NetworkRequestInfo nri : mNetworkRequests.values()) { - for (final NetworkRequest req : nri.mRequests) { - if (req.networkCapabilities.hasSignalStrength() - && nai.satisfiesImmutableCapabilitiesOf(req)) { - thresholds.add(req.networkCapabilities.getSignalStrength()); - } - } - } - } - return CollectionUtils.toIntArray(new ArrayList<>(thresholds)); - } - - private void updateSignalStrengthThresholds( - NetworkAgentInfo nai, String reason, NetworkRequest request) { - final int[] thresholdsArray = getSignalStrengthThresholds(nai); - - if (VDBG || (DBG && !"CONNECT".equals(reason))) { - String detail; - if (request != null && request.networkCapabilities.hasSignalStrength()) { - detail = reason + " " + request.networkCapabilities.getSignalStrength(); - } else { - detail = reason; - } - log(String.format("updateSignalStrengthThresholds: %s, sending %s to %s", - detail, Arrays.toString(thresholdsArray), nai.toShortString())); - } - - nai.onSignalStrengthThresholdsUpdated(thresholdsArray); - } - - private void ensureValidNetworkSpecifier(NetworkCapabilities nc) { - if (nc == null) { - return; - } - NetworkSpecifier ns = nc.getNetworkSpecifier(); - if (ns == null) { - return; - } - if (ns instanceof MatchAllNetworkSpecifier) { - throw new IllegalArgumentException("A MatchAllNetworkSpecifier is not permitted"); - } - } - - private void ensureValid(NetworkCapabilities nc) { - ensureValidNetworkSpecifier(nc); - if (nc.isPrivateDnsBroken()) { - throw new IllegalArgumentException("Can't request broken private DNS"); - } - } - - private boolean isTargetSdkAtleast(int version, int callingUid, - @NonNull String callingPackageName) { - final UserHandle user = UserHandle.getUserHandleForUid(callingUid); - final PackageManager pm = - mContext.createContextAsUser(user, 0 /* flags */).getPackageManager(); - try { - final int callingVersion = pm.getTargetSdkVersion(callingPackageName); - if (callingVersion < version) return false; - } catch (PackageManager.NameNotFoundException e) { } - return true; - } - - @Override - public NetworkRequest requestNetwork(int asUid, NetworkCapabilities networkCapabilities, - int reqTypeInt, Messenger messenger, int timeoutMs, IBinder binder, - int legacyType, int callbackFlags, @NonNull String callingPackageName, - @Nullable String callingAttributionTag) { - if (legacyType != TYPE_NONE && !checkNetworkStackPermission()) { - if (isTargetSdkAtleast(Build.VERSION_CODES.M, mDeps.getCallingUid(), - callingPackageName)) { - throw new SecurityException("Insufficient permissions to specify legacy type"); - } - } - final NetworkCapabilities defaultNc = mDefaultRequest.mRequests.get(0).networkCapabilities; - final int callingUid = mDeps.getCallingUid(); - // Privileged callers can track the default network of another UID by passing in a UID. - if (asUid != Process.INVALID_UID) { - enforceSettingsPermission(); - } else { - asUid = callingUid; - } - final NetworkRequest.Type reqType; - try { - reqType = NetworkRequest.Type.values()[reqTypeInt]; - } catch (ArrayIndexOutOfBoundsException e) { - throw new IllegalArgumentException("Unsupported request type " + reqTypeInt); - } - switch (reqType) { - case TRACK_DEFAULT: - // If the request type is TRACK_DEFAULT, the passed {@code networkCapabilities} - // is unused and will be replaced by ones appropriate for the UID (usually, the - // calling app). This allows callers to keep track of the default network. - networkCapabilities = copyDefaultNetworkCapabilitiesForUid( - defaultNc, asUid, callingUid, callingPackageName); - enforceAccessPermission(); - break; - case TRACK_SYSTEM_DEFAULT: - enforceSettingsPermission(); - networkCapabilities = new NetworkCapabilities(defaultNc); - break; - case BACKGROUND_REQUEST: - enforceNetworkStackOrSettingsPermission(); - // Fall-through since other checks are the same with normal requests. - case REQUEST: - networkCapabilities = new NetworkCapabilities(networkCapabilities); - enforceNetworkRequestPermissions(networkCapabilities, callingPackageName, - callingAttributionTag); - // TODO: this is incorrect. We mark the request as metered or not depending on - // the state of the app when the request is filed, but we never change the - // request if the app changes network state. http://b/29964605 - enforceMeteredApnPolicy(networkCapabilities); - break; - case LISTEN_FOR_BEST: - enforceAccessPermission(); - networkCapabilities = new NetworkCapabilities(networkCapabilities); - break; - default: - throw new IllegalArgumentException("Unsupported request type " + reqType); - } - ensureRequestableCapabilities(networkCapabilities); - ensureSufficientPermissionsForRequest(networkCapabilities, - Binder.getCallingPid(), callingUid, callingPackageName); - - // Enforce FOREGROUND if the caller does not have permission to use background network. - if (reqType == LISTEN_FOR_BEST) { - restrictBackgroundRequestForCaller(networkCapabilities); - } - - // Set the UID range for this request to the single UID of the requester, unless the - // requester has the permission to specify other UIDs. - // This will overwrite any allowed UIDs in the requested capabilities. Though there - // are no visible methods to set the UIDs, an app could use reflection to try and get - // networks for other apps so it's essential that the UIDs are overwritten. - // Also set the requester UID and package name in the request. - restrictRequestUidsForCallerAndSetRequestorInfo(networkCapabilities, - callingUid, callingPackageName); - - if (timeoutMs < 0) { - throw new IllegalArgumentException("Bad timeout specified"); - } - ensureValid(networkCapabilities); - - final NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType, - nextNetworkRequestId(), reqType); - final NetworkRequestInfo nri = getNriToRegister( - asUid, networkRequest, messenger, binder, callbackFlags, - callingAttributionTag); - if (DBG) log("requestNetwork for " + nri); - - // For TRACK_SYSTEM_DEFAULT callbacks, the capabilities have been modified since they were - // copied from the default request above. (This is necessary to ensure, for example, that - // the callback does not leak sensitive information to unprivileged apps.) Check that the - // changes don't alter request matching. - if (reqType == NetworkRequest.Type.TRACK_SYSTEM_DEFAULT && - (!networkCapabilities.equalRequestableCapabilities(defaultNc))) { - throw new IllegalStateException( - "TRACK_SYSTEM_DEFAULT capabilities don't match default request: " - + networkCapabilities + " vs. " + defaultNc); - } - - mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_REQUEST, nri)); - if (timeoutMs > 0) { - mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_TIMEOUT_NETWORK_REQUEST, - nri), timeoutMs); - } - return networkRequest; - } - - /** - * Return the nri to be used when registering a network request. Specifically, this is used with - * requests registered to track the default request. If there is currently a per-app default - * tracking the app requestor, then we need to create a version of this nri that mirrors that of - * the tracking per-app default so that callbacks are sent to the app requestor appropriately. - * @param asUid the uid on behalf of which to file the request. Different from requestorUid - * when a privileged caller is tracking the default network for another uid. - * @param nr the network request for the nri. - * @param msgr the messenger for the nri. - * @param binder the binder for the nri. - * @param callingAttributionTag the calling attribution tag for the nri. - * @return the nri to register. - */ - private NetworkRequestInfo getNriToRegister(final int asUid, @NonNull final NetworkRequest nr, - @Nullable final Messenger msgr, @Nullable final IBinder binder, - @NetworkCallback.Flag int callbackFlags, - @Nullable String callingAttributionTag) { - final List requests; - if (NetworkRequest.Type.TRACK_DEFAULT == nr.type) { - requests = copyDefaultNetworkRequestsForUid( - asUid, nr.getRequestorUid(), nr.getRequestorPackageName()); - } else { - requests = Collections.singletonList(nr); - } - return new NetworkRequestInfo( - asUid, requests, nr, msgr, binder, callbackFlags, callingAttributionTag); - } - - private void enforceNetworkRequestPermissions(NetworkCapabilities networkCapabilities, - String callingPackageName, String callingAttributionTag) { - if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) == false) { - enforceConnectivityRestrictedNetworksPermission(); - } else { - enforceChangePermission(callingPackageName, callingAttributionTag); - } - } - - @Override - public boolean requestBandwidthUpdate(Network network) { - enforceAccessPermission(); - NetworkAgentInfo nai = null; - if (network == null) { - return false; - } - synchronized (mNetworkForNetId) { - nai = mNetworkForNetId.get(network.getNetId()); - } - if (nai != null) { - nai.onBandwidthUpdateRequested(); - synchronized (mBandwidthRequests) { - final int uid = mDeps.getCallingUid(); - Integer uidReqs = mBandwidthRequests.get(uid); - if (uidReqs == null) { - uidReqs = 0; - } - mBandwidthRequests.put(uid, ++uidReqs); - } - return true; - } - return false; - } - - private boolean isSystem(int uid) { - return uid < Process.FIRST_APPLICATION_UID; - } - - private void enforceMeteredApnPolicy(NetworkCapabilities networkCapabilities) { - final int uid = mDeps.getCallingUid(); - if (isSystem(uid)) { - // Exemption for system uid. - return; - } - if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED)) { - // Policy already enforced. - return; - } - final long ident = Binder.clearCallingIdentity(); - try { - if (mPolicyManager.isUidRestrictedOnMeteredNetworks(uid)) { - // If UID is restricted, don't allow them to bring up metered APNs. - networkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED); - } - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - @Override - public NetworkRequest pendingRequestForNetwork(NetworkCapabilities networkCapabilities, - PendingIntent operation, @NonNull String callingPackageName, - @Nullable String callingAttributionTag) { - Objects.requireNonNull(operation, "PendingIntent cannot be null."); - final int callingUid = mDeps.getCallingUid(); - networkCapabilities = new NetworkCapabilities(networkCapabilities); - enforceNetworkRequestPermissions(networkCapabilities, callingPackageName, - callingAttributionTag); - enforceMeteredApnPolicy(networkCapabilities); - ensureRequestableCapabilities(networkCapabilities); - ensureSufficientPermissionsForRequest(networkCapabilities, - Binder.getCallingPid(), callingUid, callingPackageName); - ensureValidNetworkSpecifier(networkCapabilities); - restrictRequestUidsForCallerAndSetRequestorInfo(networkCapabilities, - callingUid, callingPackageName); - - NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, TYPE_NONE, - nextNetworkRequestId(), NetworkRequest.Type.REQUEST); - NetworkRequestInfo nri = new NetworkRequestInfo(callingUid, networkRequest, operation, - callingAttributionTag); - if (DBG) log("pendingRequest for " + nri); - mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT, - nri)); - return networkRequest; - } - - private void releasePendingNetworkRequestWithDelay(PendingIntent operation) { - mHandler.sendMessageDelayed( - mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT, - mDeps.getCallingUid(), 0, operation), mReleasePendingIntentDelayMs); - } - - @Override - public void releasePendingNetworkRequest(PendingIntent operation) { - Objects.requireNonNull(operation, "PendingIntent cannot be null."); - mHandler.sendMessage(mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT, - mDeps.getCallingUid(), 0, operation)); - } - - // In order to implement the compatibility measure for pre-M apps that call - // WifiManager.enableNetwork(..., true) without also binding to that network explicitly, - // WifiManager registers a network listen for the purpose of calling setProcessDefaultNetwork. - // This ensures it has permission to do so. - private boolean hasWifiNetworkListenPermission(NetworkCapabilities nc) { - if (nc == null) { - return false; - } - int[] transportTypes = nc.getTransportTypes(); - if (transportTypes.length != 1 || transportTypes[0] != NetworkCapabilities.TRANSPORT_WIFI) { - return false; - } - try { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.ACCESS_WIFI_STATE, - "ConnectivityService"); - } catch (SecurityException e) { - return false; - } - return true; - } - - @Override - public NetworkRequest listenForNetwork(NetworkCapabilities networkCapabilities, - Messenger messenger, IBinder binder, - @NetworkCallback.Flag int callbackFlags, - @NonNull String callingPackageName, @NonNull String callingAttributionTag) { - final int callingUid = mDeps.getCallingUid(); - if (!hasWifiNetworkListenPermission(networkCapabilities)) { - enforceAccessPermission(); - } - - NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities); - ensureSufficientPermissionsForRequest(networkCapabilities, - Binder.getCallingPid(), callingUid, callingPackageName); - restrictRequestUidsForCallerAndSetRequestorInfo(nc, callingUid, callingPackageName); - // Apps without the CHANGE_NETWORK_STATE permission can't use background networks, so - // make all their listens include NET_CAPABILITY_FOREGROUND. That way, they will get - // onLost and onAvailable callbacks when networks move in and out of the background. - // There is no need to do this for requests because an app without CHANGE_NETWORK_STATE - // can't request networks. - restrictBackgroundRequestForCaller(nc); - ensureValid(nc); - - NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(), - NetworkRequest.Type.LISTEN); - NetworkRequestInfo nri = - new NetworkRequestInfo(callingUid, networkRequest, messenger, binder, callbackFlags, - callingAttributionTag); - if (VDBG) log("listenForNetwork for " + nri); - - mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri)); - return networkRequest; - } - - @Override - public void pendingListenForNetwork(NetworkCapabilities networkCapabilities, - PendingIntent operation, @NonNull String callingPackageName, - @Nullable String callingAttributionTag) { - Objects.requireNonNull(operation, "PendingIntent cannot be null."); - final int callingUid = mDeps.getCallingUid(); - if (!hasWifiNetworkListenPermission(networkCapabilities)) { - enforceAccessPermission(); - } - ensureValid(networkCapabilities); - ensureSufficientPermissionsForRequest(networkCapabilities, - Binder.getCallingPid(), callingUid, callingPackageName); - final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities); - restrictRequestUidsForCallerAndSetRequestorInfo(nc, callingUid, callingPackageName); - - NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(), - NetworkRequest.Type.LISTEN); - NetworkRequestInfo nri = new NetworkRequestInfo(callingUid, networkRequest, operation, - callingAttributionTag); - if (VDBG) log("pendingListenForNetwork for " + nri); - - mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri)); - } - - /** Returns the next Network provider ID. */ - public final int nextNetworkProviderId() { - return mNextNetworkProviderId.getAndIncrement(); - } - - private void releaseNetworkRequests(List networkRequests) { - for (int i = 0; i < networkRequests.size(); i++) { - releaseNetworkRequest(networkRequests.get(i)); - } - } - - @Override - public void releaseNetworkRequest(NetworkRequest networkRequest) { - ensureNetworkRequestHasType(networkRequest); - mHandler.sendMessage(mHandler.obtainMessage( - EVENT_RELEASE_NETWORK_REQUEST, mDeps.getCallingUid(), 0, networkRequest)); - } - - private void handleRegisterNetworkProvider(NetworkProviderInfo npi) { - if (mNetworkProviderInfos.containsKey(npi.messenger)) { - // Avoid creating duplicates. even if an app makes a direct AIDL call. - // This will never happen if an app calls ConnectivityManager#registerNetworkProvider, - // as that will throw if a duplicate provider is registered. - loge("Attempt to register existing NetworkProviderInfo " - + mNetworkProviderInfos.get(npi.messenger).name); - return; - } - - if (DBG) log("Got NetworkProvider Messenger for " + npi.name); - mNetworkProviderInfos.put(npi.messenger, npi); - npi.connect(mContext, mTrackerHandler); - } - - @Override - public int registerNetworkProvider(Messenger messenger, String name) { - enforceNetworkFactoryOrSettingsPermission(); - Objects.requireNonNull(messenger, "messenger must be non-null"); - NetworkProviderInfo npi = new NetworkProviderInfo(name, messenger, - nextNetworkProviderId(), () -> unregisterNetworkProvider(messenger)); - mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_PROVIDER, npi)); - return npi.providerId; - } - - @Override - public void unregisterNetworkProvider(Messenger messenger) { - enforceNetworkFactoryOrSettingsPermission(); - mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_PROVIDER, messenger)); - } - - @Override - public void offerNetwork(final int providerId, - @NonNull final NetworkScore score, @NonNull final NetworkCapabilities caps, - @NonNull final INetworkOfferCallback callback) { - Objects.requireNonNull(score); - Objects.requireNonNull(caps); - Objects.requireNonNull(callback); - final NetworkOffer offer = new NetworkOffer( - FullScore.makeProspectiveScore(score, caps), caps, callback, providerId); - mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_OFFER, offer)); - } - - @Override - public void unofferNetwork(@NonNull final INetworkOfferCallback callback) { - mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_OFFER, callback)); - } - - private void handleUnregisterNetworkProvider(Messenger messenger) { - NetworkProviderInfo npi = mNetworkProviderInfos.remove(messenger); - if (npi == null) { - loge("Failed to find Messenger in unregisterNetworkProvider"); - return; - } - // Unregister all the offers from this provider - final ArrayList toRemove = new ArrayList<>(); - for (final NetworkOfferInfo noi : mNetworkOffers) { - if (noi.offer.providerId == npi.providerId) { - // Can't call handleUnregisterNetworkOffer here because iteration is in progress - toRemove.add(noi); - } - } - for (final NetworkOfferInfo noi : toRemove) { - handleUnregisterNetworkOffer(noi); - } - if (DBG) log("unregisterNetworkProvider for " + npi.name); - } - - @Override - public void declareNetworkRequestUnfulfillable(@NonNull final NetworkRequest request) { - if (request.hasTransport(TRANSPORT_TEST)) { - enforceNetworkFactoryOrTestNetworksPermission(); - } else { - enforceNetworkFactoryPermission(); - } - final NetworkRequestInfo nri = mNetworkRequests.get(request); - if (nri != null) { - // declareNetworkRequestUnfulfillable() paths don't apply to multilayer requests. - ensureNotMultilayerRequest(nri, "declareNetworkRequestUnfulfillable"); - mHandler.post(() -> handleReleaseNetworkRequest( - nri.mRequests.get(0), mDeps.getCallingUid(), true)); - } - } - - // NOTE: Accessed on multiple threads, must be synchronized on itself. - @GuardedBy("mNetworkForNetId") - private final SparseArray mNetworkForNetId = new SparseArray<>(); - // NOTE: Accessed on multiple threads, synchronized with mNetworkForNetId. - // An entry is first reserved with NetIdManager, prior to being added to mNetworkForNetId, so - // there may not be a strict 1:1 correlation between the two. - private final NetIdManager mNetIdManager; - - // NetworkAgentInfo keyed off its connecting messenger - // TODO - eval if we can reduce the number of lists/hashmaps/sparsearrays - // NOTE: Only should be accessed on ConnectivityServiceThread, except dump(). - private final ArraySet mNetworkAgentInfos = new ArraySet<>(); - - // UID ranges for users that are currently blocked by VPNs. - // This array is accessed and iterated on multiple threads without holding locks, so its - // contents must never be mutated. When the ranges change, the array is replaced with a new one - // (on the handler thread). - private volatile List mVpnBlockedUidRanges = new ArrayList<>(); - - // Must only be accessed on the handler thread - @NonNull - private final ArrayList mNetworkOffers = new ArrayList<>(); - - @GuardedBy("mBlockedAppUids") - private final HashSet mBlockedAppUids = new HashSet<>(); - - // Current OEM network preferences. This object must only be written to on the handler thread. - // Since it is immutable and always non-null, other threads may read it if they only care - // about seeing a consistent object but not that it is current. - @NonNull - private OemNetworkPreferences mOemNetworkPreferences = - new OemNetworkPreferences.Builder().build(); - // Current per-profile network preferences. This object follows the same threading rules as - // the OEM network preferences above. - @NonNull - private ProfileNetworkPreferences mProfileNetworkPreferences = new ProfileNetworkPreferences(); - - // OemNetworkPreferences activity String log entries. - private static final int MAX_OEM_NETWORK_PREFERENCE_LOGS = 20; - @NonNull - private final LocalLog mOemNetworkPreferencesLogs = - new LocalLog(MAX_OEM_NETWORK_PREFERENCE_LOGS); - - /** - * Determine whether a given package has a mapping in the current OemNetworkPreferences. - * @param packageName the package name to check existence of a mapping for. - * @return true if a mapping exists, false otherwise - */ - private boolean isMappedInOemNetworkPreference(@NonNull final String packageName) { - return mOemNetworkPreferences.getNetworkPreferences().containsKey(packageName); - } - - // The always-on request for an Internet-capable network that apps without a specific default - // fall back to. - @VisibleForTesting - @NonNull - final NetworkRequestInfo mDefaultRequest; - // Collection of NetworkRequestInfo's used for default networks. - @VisibleForTesting - @NonNull - final ArraySet mDefaultNetworkRequests = new ArraySet<>(); - - private boolean isPerAppDefaultRequest(@NonNull final NetworkRequestInfo nri) { - return (mDefaultNetworkRequests.contains(nri) && mDefaultRequest != nri); - } - - /** - * Return the default network request currently tracking the given uid. - * @param uid the uid to check. - * @return the NetworkRequestInfo tracking the given uid. - */ - @NonNull - private NetworkRequestInfo getDefaultRequestTrackingUid(final int uid) { - for (final NetworkRequestInfo nri : mDefaultNetworkRequests) { - if (nri == mDefaultRequest) { - continue; - } - // Checking the first request is sufficient as only multilayer requests will have more - // than one request and for multilayer, all requests will track the same uids. - if (nri.mRequests.get(0).networkCapabilities.appliesToUid(uid)) { - return nri; - } - } - return mDefaultRequest; - } - - /** - * Get a copy of the network requests of the default request that is currently tracking the - * given uid. - * @param asUid the uid on behalf of which to file the request. Different from requestorUid - * when a privileged caller is tracking the default network for another uid. - * @param requestorUid the uid to check the default for. - * @param requestorPackageName the requestor's package name. - * @return a copy of the default's NetworkRequest that is tracking the given uid. - */ - @NonNull - private List copyDefaultNetworkRequestsForUid( - final int asUid, final int requestorUid, @NonNull final String requestorPackageName) { - return copyNetworkRequestsForUid( - getDefaultRequestTrackingUid(asUid).mRequests, - asUid, requestorUid, requestorPackageName); - } - - /** - * Copy the given nri's NetworkRequest collection. - * @param requestsToCopy the NetworkRequest collection to be copied. - * @param asUid the uid on behalf of which to file the request. Different from requestorUid - * when a privileged caller is tracking the default network for another uid. - * @param requestorUid the uid to set on the copied collection. - * @param requestorPackageName the package name to set on the copied collection. - * @return the copied NetworkRequest collection. - */ - @NonNull - private List copyNetworkRequestsForUid( - @NonNull final List requestsToCopy, final int asUid, - final int requestorUid, @NonNull final String requestorPackageName) { - final List requests = new ArrayList<>(); - for (final NetworkRequest nr : requestsToCopy) { - requests.add(new NetworkRequest(copyDefaultNetworkCapabilitiesForUid( - nr.networkCapabilities, asUid, requestorUid, requestorPackageName), - nr.legacyType, nextNetworkRequestId(), nr.type)); - } - return requests; - } - - @NonNull - private NetworkCapabilities copyDefaultNetworkCapabilitiesForUid( - @NonNull final NetworkCapabilities netCapToCopy, final int asUid, - final int requestorUid, @NonNull final String requestorPackageName) { - // These capabilities are for a TRACK_DEFAULT callback, so: - // 1. Remove NET_CAPABILITY_VPN, because it's (currently!) the only difference between - // mDefaultRequest and a per-UID default request. - // TODO: stop depending on the fact that these two unrelated things happen to be the same - // 2. Always set the UIDs to asUid. restrictRequestUidsForCallerAndSetRequestorInfo will - // not do this in the case of a privileged application. - final NetworkCapabilities netCap = new NetworkCapabilities(netCapToCopy); - netCap.removeCapability(NET_CAPABILITY_NOT_VPN); - netCap.setSingleUid(asUid); - restrictRequestUidsForCallerAndSetRequestorInfo( - netCap, requestorUid, requestorPackageName); - return netCap; - } - - /** - * Get the nri that is currently being tracked for callbacks by per-app defaults. - * @param nr the network request to check for equality against. - * @return the nri if one exists, null otherwise. - */ - @Nullable - private NetworkRequestInfo getNriForAppRequest(@NonNull final NetworkRequest nr) { - for (final NetworkRequestInfo nri : mNetworkRequests.values()) { - if (nri.getNetworkRequestForCallback().equals(nr)) { - return nri; - } - } - return null; - } - - /** - * Check if an nri is currently being managed by per-app default networking. - * @param nri the nri to check. - * @return true if this nri is currently being managed by per-app default networking. - */ - private boolean isPerAppTrackedNri(@NonNull final NetworkRequestInfo nri) { - // nri.mRequests.get(0) is only different from the original request filed in - // nri.getNetworkRequestForCallback() if nri.mRequests was changed by per-app default - // functionality therefore if these two don't match, it means this particular nri is - // currently being managed by a per-app default. - return nri.getNetworkRequestForCallback() != nri.mRequests.get(0); - } - - /** - * Determine if an nri is a managed default request that disallows default networking. - * @param nri the request to evaluate - * @return true if device-default networking is disallowed - */ - private boolean isDefaultBlocked(@NonNull final NetworkRequestInfo nri) { - // Check if this nri is a managed default that supports the default network at its - // lowest priority request. - final NetworkRequest defaultNetworkRequest = mDefaultRequest.mRequests.get(0); - final NetworkCapabilities lowestPriorityNetCap = - nri.mRequests.get(nri.mRequests.size() - 1).networkCapabilities; - return isPerAppDefaultRequest(nri) - && !(defaultNetworkRequest.networkCapabilities.equalRequestableCapabilities( - lowestPriorityNetCap)); - } - - // Request used to optionally keep mobile data active even when higher - // priority networks like Wi-Fi are active. - private final NetworkRequest mDefaultMobileDataRequest; - - // Request used to optionally keep wifi data active even when higher - // priority networks like ethernet are active. - private final NetworkRequest mDefaultWifiRequest; - - // Request used to optionally keep vehicle internal network always active - private final NetworkRequest mDefaultVehicleRequest; - - // Sentinel NAI used to direct apps with default networks that should have no connectivity to a - // network with no service. This NAI should never be matched against, nor should any public API - // ever return the associated network. For this reason, this NAI is not in the list of available - // NAIs. It is used in computeNetworkReassignment() to be set as the satisfier for non-device - // default requests that don't support using the device default network which will ultimately - // allow ConnectivityService to use this no-service network when calling makeDefaultForApps(). - @VisibleForTesting - final NetworkAgentInfo mNoServiceNetwork; - - // The NetworkAgentInfo currently satisfying the default request, if any. - private NetworkAgentInfo getDefaultNetwork() { - return mDefaultRequest.mSatisfier; - } - - private NetworkAgentInfo getDefaultNetworkForUid(final int uid) { - for (final NetworkRequestInfo nri : mDefaultNetworkRequests) { - // Currently, all network requests will have the same uids therefore checking the first - // one is sufficient. If/when uids are tracked at the nri level, this can change. - final Set uids = nri.mRequests.get(0).networkCapabilities.getUidRanges(); - if (null == uids) { - continue; - } - for (final UidRange range : uids) { - if (range.contains(uid)) { - return nri.getSatisfier(); - } - } - } - return getDefaultNetwork(); - } - - @Nullable - private Network getNetwork(@Nullable NetworkAgentInfo nai) { - return nai != null ? nai.network : null; - } - - private void ensureRunningOnConnectivityServiceThread() { - if (mHandler.getLooper().getThread() != Thread.currentThread()) { - throw new IllegalStateException( - "Not running on ConnectivityService thread: " - + Thread.currentThread().getName()); - } - } - - @VisibleForTesting - protected boolean isDefaultNetwork(NetworkAgentInfo nai) { - return nai == getDefaultNetwork(); - } - - /** - * Register a new agent with ConnectivityService to handle a network. - * - * @param na a reference for ConnectivityService to contact the agent asynchronously. - * @param networkInfo the initial info associated with this network. It can be updated later : - * see {@link #updateNetworkInfo}. - * @param linkProperties the initial link properties of this network. They can be updated - * later : see {@link #updateLinkProperties}. - * @param networkCapabilities the initial capabilites of this network. They can be updated - * later : see {@link #updateCapabilities}. - * @param initialScore the initial score of the network. See - * {@link NetworkAgentInfo#getCurrentScore}. - * @param networkAgentConfig metadata about the network. This is never updated. - * @param providerId the ID of the provider owning this NetworkAgent. - * @return the network created for this agent. - */ - public Network registerNetworkAgent(INetworkAgent na, NetworkInfo networkInfo, - LinkProperties linkProperties, NetworkCapabilities networkCapabilities, - @NonNull NetworkScore initialScore, NetworkAgentConfig networkAgentConfig, - int providerId) { - Objects.requireNonNull(networkInfo, "networkInfo must not be null"); - Objects.requireNonNull(linkProperties, "linkProperties must not be null"); - Objects.requireNonNull(networkCapabilities, "networkCapabilities must not be null"); - Objects.requireNonNull(initialScore, "initialScore must not be null"); - Objects.requireNonNull(networkAgentConfig, "networkAgentConfig must not be null"); - if (networkCapabilities.hasTransport(TRANSPORT_TEST)) { - enforceAnyPermissionOf(Manifest.permission.MANAGE_TEST_NETWORKS); - } else { - enforceNetworkFactoryPermission(); - } - - final int uid = mDeps.getCallingUid(); - final long token = Binder.clearCallingIdentity(); - try { - return registerNetworkAgentInternal(na, networkInfo, linkProperties, - networkCapabilities, initialScore, networkAgentConfig, providerId, uid); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - private Network registerNetworkAgentInternal(INetworkAgent na, NetworkInfo networkInfo, - LinkProperties linkProperties, NetworkCapabilities networkCapabilities, - NetworkScore currentScore, NetworkAgentConfig networkAgentConfig, int providerId, - int uid) { - if (networkCapabilities.hasTransport(TRANSPORT_TEST)) { - // Strictly, sanitizing here is unnecessary as the capabilities will be sanitized in - // the call to mixInCapabilities below anyway, but sanitizing here means the NAI never - // sees capabilities that may be malicious, which might prevent mistakes in the future. - networkCapabilities = new NetworkCapabilities(networkCapabilities); - networkCapabilities.restrictCapabilitesForTestNetwork(uid); - } - - LinkProperties lp = new LinkProperties(linkProperties); - - final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities); - final NetworkAgentInfo nai = new NetworkAgentInfo(na, - new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc, - currentScore, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig), - this, mNetd, mDnsResolver, providerId, uid, mLingerDelayMs, - mQosCallbackTracker, mDeps); - - // Make sure the LinkProperties and NetworkCapabilities reflect what the agent info says. - processCapabilitiesFromAgent(nai, nc); - nai.getAndSetNetworkCapabilities(mixInCapabilities(nai, nc)); - processLinkPropertiesFromAgent(nai, nai.linkProperties); - - final String extraInfo = networkInfo.getExtraInfo(); - final String name = TextUtils.isEmpty(extraInfo) - ? nai.networkCapabilities.getSsid() : extraInfo; - if (DBG) log("registerNetworkAgent " + nai); - mDeps.getNetworkStack().makeNetworkMonitor( - nai.network, name, new NetworkMonitorCallbacks(nai)); - // NetworkAgentInfo registration will finish when the NetworkMonitor is created. - // If the network disconnects or sends any other event before that, messages are deferred by - // NetworkAgent until nai.connect(), which will be called when finalizing the - // registration. - return nai.network; - } - - private void handleRegisterNetworkAgent(NetworkAgentInfo nai, INetworkMonitor networkMonitor) { - nai.onNetworkMonitorCreated(networkMonitor); - if (VDBG) log("Got NetworkAgent Messenger"); - mNetworkAgentInfos.add(nai); - synchronized (mNetworkForNetId) { - mNetworkForNetId.put(nai.network.getNetId(), nai); - } - - try { - networkMonitor.start(); - } catch (RemoteException e) { - e.rethrowAsRuntimeException(); - } - nai.notifyRegistered(); - NetworkInfo networkInfo = nai.networkInfo; - updateNetworkInfo(nai, networkInfo); - updateUids(nai, null, nai.networkCapabilities); - } - - private class NetworkOfferInfo implements IBinder.DeathRecipient { - @NonNull public final NetworkOffer offer; - - NetworkOfferInfo(@NonNull final NetworkOffer offer) { - this.offer = offer; - } - - @Override - public void binderDied() { - mHandler.post(() -> handleUnregisterNetworkOffer(this)); - } - } - - private boolean isNetworkProviderWithIdRegistered(final int providerId) { - for (final NetworkProviderInfo npi : mNetworkProviderInfos.values()) { - if (npi.providerId == providerId) return true; - } - return false; - } - - /** - * Register or update a network offer. - * @param newOffer The new offer. If the callback member is the same as an existing - * offer, it is an update of that offer. - */ - private void handleRegisterNetworkOffer(@NonNull final NetworkOffer newOffer) { - ensureRunningOnConnectivityServiceThread(); - if (!isNetworkProviderWithIdRegistered(newOffer.providerId)) { - // This may actually happen if a provider updates its score or registers and then - // immediately unregisters. The offer would still be in the handler queue, but the - // provider would have been removed. - if (DBG) log("Received offer from an unregistered provider"); - return; - } - final NetworkOfferInfo existingOffer = findNetworkOfferInfoByCallback(newOffer.callback); - if (null != existingOffer) { - handleUnregisterNetworkOffer(existingOffer); - newOffer.migrateFrom(existingOffer.offer); - } - final NetworkOfferInfo noi = new NetworkOfferInfo(newOffer); - try { - noi.offer.callback.asBinder().linkToDeath(noi, 0 /* flags */); - } catch (RemoteException e) { - noi.binderDied(); - return; - } - mNetworkOffers.add(noi); - issueNetworkNeeds(noi); - } - - private void handleUnregisterNetworkOffer(@NonNull final NetworkOfferInfo noi) { - ensureRunningOnConnectivityServiceThread(); - mNetworkOffers.remove(noi); - noi.offer.callback.asBinder().unlinkToDeath(noi, 0 /* flags */); - } - - @Nullable private NetworkOfferInfo findNetworkOfferInfoByCallback( - @NonNull final INetworkOfferCallback callback) { - ensureRunningOnConnectivityServiceThread(); - for (final NetworkOfferInfo noi : mNetworkOffers) { - if (noi.offer.callback.asBinder().equals(callback.asBinder())) return noi; - } - return null; - } - - /** - * Called when receiving LinkProperties directly from a NetworkAgent. - * Stores into |nai| any data coming from the agent that might also be written to the network's - * LinkProperties by ConnectivityService itself. This ensures that the data provided by the - * agent is not lost when updateLinkProperties is called. - * This method should never alter the agent's LinkProperties, only store data in |nai|. - */ - private void processLinkPropertiesFromAgent(NetworkAgentInfo nai, LinkProperties lp) { - lp.ensureDirectlyConnectedRoutes(); - nai.clatd.setNat64PrefixFromRa(lp.getNat64Prefix()); - nai.networkAgentPortalData = lp.getCaptivePortalData(); - } - - private void updateLinkProperties(NetworkAgentInfo networkAgent, @NonNull LinkProperties newLp, - @NonNull LinkProperties oldLp) { - int netId = networkAgent.network.getNetId(); - - // The NetworkAgent does not know whether clatd is running on its network or not, or whether - // a NAT64 prefix was discovered by the DNS resolver. Before we do anything else, make sure - // the LinkProperties for the network are accurate. - networkAgent.clatd.fixupLinkProperties(oldLp, newLp); - - updateInterfaces(newLp, oldLp, netId, networkAgent.networkCapabilities); - - // update filtering rules, need to happen after the interface update so netd knows about the - // new interface (the interface name -> index map becomes initialized) - updateVpnFiltering(newLp, oldLp, networkAgent); - - updateMtu(newLp, oldLp); - // TODO - figure out what to do for clat -// for (LinkProperties lp : newLp.getStackedLinks()) { -// updateMtu(lp, null); -// } - if (isDefaultNetwork(networkAgent)) { - updateTcpBufferSizes(newLp.getTcpBufferSizes()); - } - - updateRoutes(newLp, oldLp, netId); - updateDnses(newLp, oldLp, netId); - // Make sure LinkProperties represents the latest private DNS status. - // This does not need to be done before updateDnses because the - // LinkProperties are not the source of the private DNS configuration. - // updateDnses will fetch the private DNS configuration from DnsManager. - mDnsManager.updatePrivateDnsStatus(netId, newLp); - - if (isDefaultNetwork(networkAgent)) { - handleApplyDefaultProxy(newLp.getHttpProxy()); - } else { - updateProxy(newLp, oldLp); - } - - updateWakeOnLan(newLp); - - // Captive portal data is obtained from NetworkMonitor and stored in NetworkAgentInfo. - // It is not always contained in the LinkProperties sent from NetworkAgents, and if it - // does, it needs to be merged here. - newLp.setCaptivePortalData(mergeCaptivePortalData(networkAgent.networkAgentPortalData, - networkAgent.capportApiData)); - - // TODO - move this check to cover the whole function - if (!Objects.equals(newLp, oldLp)) { - synchronized (networkAgent) { - networkAgent.linkProperties = newLp; - } - // Start or stop DNS64 detection and 464xlat according to network state. - networkAgent.clatd.update(); - notifyIfacesChangedForNetworkStats(); - networkAgent.networkMonitor().notifyLinkPropertiesChanged( - new LinkProperties(newLp, true /* parcelSensitiveFields */)); - if (networkAgent.everConnected) { - notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_IP_CHANGED); - } - } - - mKeepaliveTracker.handleCheckKeepalivesStillValid(networkAgent); - } - - /** - * @param naData captive portal data from NetworkAgent - * @param apiData captive portal data from capport API - */ - @Nullable - private CaptivePortalData mergeCaptivePortalData(CaptivePortalData naData, - CaptivePortalData apiData) { - if (naData == null || apiData == null) { - return naData == null ? apiData : naData; - } - final CaptivePortalData.Builder captivePortalBuilder = - new CaptivePortalData.Builder(naData); - - if (apiData.isCaptive()) { - captivePortalBuilder.setCaptive(true); - } - if (apiData.isSessionExtendable()) { - captivePortalBuilder.setSessionExtendable(true); - } - if (apiData.getExpiryTimeMillis() >= 0 || apiData.getByteLimit() >= 0) { - // Expiry time, bytes remaining, refresh time all need to come from the same source, - // otherwise data would be inconsistent. Prefer the capport API info if present, - // as it can generally be refreshed more often. - captivePortalBuilder.setExpiryTime(apiData.getExpiryTimeMillis()); - captivePortalBuilder.setBytesRemaining(apiData.getByteLimit()); - captivePortalBuilder.setRefreshTime(apiData.getRefreshTimeMillis()); - } else if (naData.getExpiryTimeMillis() < 0 && naData.getByteLimit() < 0) { - // No source has time / bytes remaining information: surface the newest refresh time - // for other fields - captivePortalBuilder.setRefreshTime( - Math.max(naData.getRefreshTimeMillis(), apiData.getRefreshTimeMillis())); - } - - // Prioritize the user portal URL from the network agent if the source is authenticated. - if (apiData.getUserPortalUrl() != null && naData.getUserPortalUrlSource() - != CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) { - captivePortalBuilder.setUserPortalUrl(apiData.getUserPortalUrl(), - apiData.getUserPortalUrlSource()); - } - // Prioritize the venue information URL from the network agent if the source is - // authenticated. - if (apiData.getVenueInfoUrl() != null && naData.getVenueInfoUrlSource() - != CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) { - captivePortalBuilder.setVenueInfoUrl(apiData.getVenueInfoUrl(), - apiData.getVenueInfoUrlSource()); - } - return captivePortalBuilder.build(); - } - - private void wakeupModifyInterface(String iface, NetworkCapabilities caps, boolean add) { - // Marks are only available on WiFi interfaces. Checking for - // marks on unsupported interfaces is harmless. - if (!caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { - return; - } - - int mark = mResources.get().getInteger(R.integer.config_networkWakeupPacketMark); - int mask = mResources.get().getInteger(R.integer.config_networkWakeupPacketMask); - - // Mask/mark of zero will not detect anything interesting. - // Don't install rules unless both values are nonzero. - if (mark == 0 || mask == 0) { - return; - } - - final String prefix = "iface:" + iface; - try { - if (add) { - mNetd.wakeupAddInterface(iface, prefix, mark, mask); - } else { - mNetd.wakeupDelInterface(iface, prefix, mark, mask); - } - } catch (Exception e) { - loge("Exception modifying wakeup packet monitoring: " + e); - } - - } - - private void updateInterfaces(final @Nullable LinkProperties newLp, - final @Nullable LinkProperties oldLp, final int netId, - final @NonNull NetworkCapabilities caps) { - final CompareResult interfaceDiff = new CompareResult<>( - oldLp != null ? oldLp.getAllInterfaceNames() : null, - newLp != null ? newLp.getAllInterfaceNames() : null); - if (!interfaceDiff.added.isEmpty()) { - for (final String iface : interfaceDiff.added) { - try { - if (DBG) log("Adding iface " + iface + " to network " + netId); - mNetd.networkAddInterface(netId, iface); - wakeupModifyInterface(iface, caps, true); - mDeps.reportNetworkInterfaceForTransports(mContext, iface, - caps.getTransportTypes()); - } catch (Exception e) { - logw("Exception adding interface: " + e); - } - } - } - for (final String iface : interfaceDiff.removed) { - try { - if (DBG) log("Removing iface " + iface + " from network " + netId); - wakeupModifyInterface(iface, caps, false); - mNetd.networkRemoveInterface(netId, iface); - } catch (Exception e) { - loge("Exception removing interface: " + e); - } - } - } - - // TODO: move to frameworks/libs/net. - private RouteInfoParcel convertRouteInfo(RouteInfo route) { - final String nextHop; - - switch (route.getType()) { - case RouteInfo.RTN_UNICAST: - if (route.hasGateway()) { - nextHop = route.getGateway().getHostAddress(); - } else { - nextHop = INetd.NEXTHOP_NONE; - } - break; - case RouteInfo.RTN_UNREACHABLE: - nextHop = INetd.NEXTHOP_UNREACHABLE; - break; - case RouteInfo.RTN_THROW: - nextHop = INetd.NEXTHOP_THROW; - break; - default: - nextHop = INetd.NEXTHOP_NONE; - break; - } - - final RouteInfoParcel rip = new RouteInfoParcel(); - rip.ifName = route.getInterface(); - rip.destination = route.getDestination().toString(); - rip.nextHop = nextHop; - rip.mtu = route.getMtu(); - - return rip; - } - - /** - * Have netd update routes from oldLp to newLp. - * @return true if routes changed between oldLp and newLp - */ - private boolean updateRoutes(LinkProperties newLp, LinkProperties oldLp, int netId) { - // compare the route diff to determine which routes have been updated - final CompareOrUpdateResult routeDiff = - new CompareOrUpdateResult<>( - oldLp != null ? oldLp.getAllRoutes() : null, - newLp != null ? newLp.getAllRoutes() : null, - (r) -> r.getRouteKey()); - - // add routes before removing old in case it helps with continuous connectivity - - // do this twice, adding non-next-hop routes first, then routes they are dependent on - for (RouteInfo route : routeDiff.added) { - if (route.hasGateway()) continue; - if (VDBG || DDBG) log("Adding Route [" + route + "] to network " + netId); - try { - mNetd.networkAddRouteParcel(netId, convertRouteInfo(route)); - } catch (Exception e) { - if ((route.getDestination().getAddress() instanceof Inet4Address) || VDBG) { - loge("Exception in networkAddRouteParcel for non-gateway: " + e); - } - } - } - for (RouteInfo route : routeDiff.added) { - if (!route.hasGateway()) continue; - if (VDBG || DDBG) log("Adding Route [" + route + "] to network " + netId); - try { - mNetd.networkAddRouteParcel(netId, convertRouteInfo(route)); - } catch (Exception e) { - if ((route.getGateway() instanceof Inet4Address) || VDBG) { - loge("Exception in networkAddRouteParcel for gateway: " + e); - } - } - } - - for (RouteInfo route : routeDiff.removed) { - if (VDBG || DDBG) log("Removing Route [" + route + "] from network " + netId); - try { - mNetd.networkRemoveRouteParcel(netId, convertRouteInfo(route)); - } catch (Exception e) { - loge("Exception in networkRemoveRouteParcel: " + e); - } - } - - for (RouteInfo route : routeDiff.updated) { - if (VDBG || DDBG) log("Updating Route [" + route + "] from network " + netId); - try { - mNetd.networkUpdateRouteParcel(netId, convertRouteInfo(route)); - } catch (Exception e) { - loge("Exception in networkUpdateRouteParcel: " + e); - } - } - return !routeDiff.added.isEmpty() || !routeDiff.removed.isEmpty() - || !routeDiff.updated.isEmpty(); - } - - private void updateDnses(LinkProperties newLp, LinkProperties oldLp, int netId) { - if (oldLp != null && newLp.isIdenticalDnses(oldLp)) { - return; // no updating necessary - } - - if (DBG) { - final Collection dnses = newLp.getDnsServers(); - log("Setting DNS servers for network " + netId + " to " + dnses); - } - try { - mDnsManager.noteDnsServersForNetwork(netId, newLp); - mDnsManager.flushVmDnsCache(); - } catch (Exception e) { - loge("Exception in setDnsConfigurationForNetwork: " + e); - } - } - - private void updateVpnFiltering(LinkProperties newLp, LinkProperties oldLp, - NetworkAgentInfo nai) { - final String oldIface = oldLp != null ? oldLp.getInterfaceName() : null; - final String newIface = newLp != null ? newLp.getInterfaceName() : null; - final boolean wasFiltering = requiresVpnIsolation(nai, nai.networkCapabilities, oldLp); - final boolean needsFiltering = requiresVpnIsolation(nai, nai.networkCapabilities, newLp); - - if (!wasFiltering && !needsFiltering) { - // Nothing to do. - return; - } - - if (Objects.equals(oldIface, newIface) && (wasFiltering == needsFiltering)) { - // Nothing changed. - return; - } - - final Set ranges = nai.networkCapabilities.getUidRanges(); - final int vpnAppUid = nai.networkCapabilities.getOwnerUid(); - // TODO: this create a window of opportunity for apps to receive traffic between the time - // when the old rules are removed and the time when new rules are added. To fix this, - // make eBPF support two allowlisted interfaces so here new rules can be added before the - // old rules are being removed. - if (wasFiltering) { - mPermissionMonitor.onVpnUidRangesRemoved(oldIface, ranges, vpnAppUid); - } - if (needsFiltering) { - mPermissionMonitor.onVpnUidRangesAdded(newIface, ranges, vpnAppUid); - } - } - - private void updateWakeOnLan(@NonNull LinkProperties lp) { - if (mWolSupportedInterfaces == null) { - mWolSupportedInterfaces = new ArraySet<>(mResources.get().getStringArray( - R.array.config_wakeonlan_supported_interfaces)); - } - lp.setWakeOnLanSupported(mWolSupportedInterfaces.contains(lp.getInterfaceName())); - } - - private int getNetworkPermission(NetworkCapabilities nc) { - if (!nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) { - return INetd.PERMISSION_SYSTEM; - } - if (!nc.hasCapability(NET_CAPABILITY_FOREGROUND)) { - return INetd.PERMISSION_NETWORK; - } - return INetd.PERMISSION_NONE; - } - - private void updateNetworkPermissions(@NonNull final NetworkAgentInfo nai, - @NonNull final NetworkCapabilities newNc) { - final int oldPermission = getNetworkPermission(nai.networkCapabilities); - final int newPermission = getNetworkPermission(newNc); - if (oldPermission != newPermission && nai.created && !nai.isVPN()) { - try { - mNetd.networkSetPermissionForNetwork(nai.network.getNetId(), newPermission); - } catch (RemoteException | ServiceSpecificException e) { - loge("Exception in networkSetPermissionForNetwork: " + e); - } - } - } - - /** - * Called when receiving NetworkCapabilities directly from a NetworkAgent. - * Stores into |nai| any data coming from the agent that might also be written to the network's - * NetworkCapabilities by ConnectivityService itself. This ensures that the data provided by the - * agent is not lost when updateCapabilities is called. - * This method should never alter the agent's NetworkCapabilities, only store data in |nai|. - */ - private void processCapabilitiesFromAgent(NetworkAgentInfo nai, NetworkCapabilities nc) { - // Note: resetting the owner UID before storing the agent capabilities in NAI means that if - // the agent attempts to change the owner UID, then nai.declaredCapabilities will not - // actually be the same as the capabilities sent by the agent. Still, it is safer to reset - // the owner UID here and behave as if the agent had never tried to change it. - if (nai.networkCapabilities.getOwnerUid() != nc.getOwnerUid()) { - Log.e(TAG, nai.toShortString() + ": ignoring attempt to change owner from " - + nai.networkCapabilities.getOwnerUid() + " to " + nc.getOwnerUid()); - nc.setOwnerUid(nai.networkCapabilities.getOwnerUid()); - } - nai.declaredCapabilities = new NetworkCapabilities(nc); - } - - /** Modifies |newNc| based on the capabilities of |underlyingNetworks| and |agentCaps|. */ - @VisibleForTesting - void applyUnderlyingCapabilities(@Nullable Network[] underlyingNetworks, - @NonNull NetworkCapabilities agentCaps, @NonNull NetworkCapabilities newNc) { - underlyingNetworks = underlyingNetworksOrDefault( - agentCaps.getOwnerUid(), underlyingNetworks); - long transportTypes = NetworkCapabilitiesUtils.packBits(agentCaps.getTransportTypes()); - int downKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED; - int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED; - // metered if any underlying is metered, or originally declared metered by the agent. - boolean metered = !agentCaps.hasCapability(NET_CAPABILITY_NOT_METERED); - boolean roaming = false; // roaming if any underlying is roaming - boolean congested = false; // congested if any underlying is congested - boolean suspended = true; // suspended if all underlying are suspended - - boolean hadUnderlyingNetworks = false; - if (null != underlyingNetworks) { - for (Network underlyingNetwork : underlyingNetworks) { - final NetworkAgentInfo underlying = - getNetworkAgentInfoForNetwork(underlyingNetwork); - if (underlying == null) continue; - - final NetworkCapabilities underlyingCaps = underlying.networkCapabilities; - hadUnderlyingNetworks = true; - for (int underlyingType : underlyingCaps.getTransportTypes()) { - transportTypes |= 1L << underlyingType; - } - - // Merge capabilities of this underlying network. For bandwidth, assume the - // worst case. - downKbps = NetworkCapabilities.minBandwidth(downKbps, - underlyingCaps.getLinkDownstreamBandwidthKbps()); - upKbps = NetworkCapabilities.minBandwidth(upKbps, - underlyingCaps.getLinkUpstreamBandwidthKbps()); - // If this underlying network is metered, the VPN is metered (it may cost money - // to send packets on this network). - metered |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_METERED); - // If this underlying network is roaming, the VPN is roaming (the billing structure - // is different than the usual, local one). - roaming |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_ROAMING); - // If this underlying network is congested, the VPN is congested (the current - // condition of the network affects the performance of this network). - congested |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_CONGESTED); - // If this network is not suspended, the VPN is not suspended (the VPN - // is able to transfer some data). - suspended &= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED); - } - } - if (!hadUnderlyingNetworks) { - // No idea what the underlying networks are; assume reasonable defaults - metered = true; - roaming = false; - congested = false; - suspended = false; - } - - newNc.setTransportTypes(NetworkCapabilitiesUtils.unpackBits(transportTypes)); - newNc.setLinkDownstreamBandwidthKbps(downKbps); - newNc.setLinkUpstreamBandwidthKbps(upKbps); - newNc.setCapability(NET_CAPABILITY_NOT_METERED, !metered); - newNc.setCapability(NET_CAPABILITY_NOT_ROAMING, !roaming); - newNc.setCapability(NET_CAPABILITY_NOT_CONGESTED, !congested); - newNc.setCapability(NET_CAPABILITY_NOT_SUSPENDED, !suspended); - } - - /** - * Augments the NetworkCapabilities passed in by a NetworkAgent with capabilities that are - * maintained here that the NetworkAgent is not aware of (e.g., validated, captive portal, - * and foreground status). - */ - @NonNull - private NetworkCapabilities mixInCapabilities(NetworkAgentInfo nai, NetworkCapabilities nc) { - // Once a NetworkAgent is connected, complain if some immutable capabilities are removed. - // Don't complain for VPNs since they're not driven by requests and there is no risk of - // causing a connect/teardown loop. - // TODO: remove this altogether and make it the responsibility of the NetworkProviders to - // avoid connect/teardown loops. - if (nai.everConnected && - !nai.isVPN() && - !nai.networkCapabilities.satisfiedByImmutableNetworkCapabilities(nc)) { - // TODO: consider not complaining when a network agent degrades its capabilities if this - // does not cause any request (that is not a listen) currently matching that agent to - // stop being matched by the updated agent. - String diff = nai.networkCapabilities.describeImmutableDifferences(nc); - if (!TextUtils.isEmpty(diff)) { - Log.wtf(TAG, "BUG: " + nai + " lost immutable capabilities:" + diff); - } - } - - // Don't modify caller's NetworkCapabilities. - final NetworkCapabilities newNc = new NetworkCapabilities(nc); - if (nai.lastValidated) { - newNc.addCapability(NET_CAPABILITY_VALIDATED); - } else { - newNc.removeCapability(NET_CAPABILITY_VALIDATED); - } - if (nai.lastCaptivePortalDetected) { - newNc.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL); - } else { - newNc.removeCapability(NET_CAPABILITY_CAPTIVE_PORTAL); - } - if (nai.isBackgroundNetwork()) { - newNc.removeCapability(NET_CAPABILITY_FOREGROUND); - } else { - newNc.addCapability(NET_CAPABILITY_FOREGROUND); - } - if (nai.partialConnectivity) { - newNc.addCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY); - } else { - newNc.removeCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY); - } - newNc.setPrivateDnsBroken(nai.networkCapabilities.isPrivateDnsBroken()); - - // TODO : remove this once all factories are updated to send NOT_SUSPENDED and NOT_ROAMING - if (!newNc.hasTransport(TRANSPORT_CELLULAR)) { - newNc.addCapability(NET_CAPABILITY_NOT_SUSPENDED); - newNc.addCapability(NET_CAPABILITY_NOT_ROAMING); - } - - if (nai.supportsUnderlyingNetworks()) { - applyUnderlyingCapabilities(nai.declaredUnderlyingNetworks, nai.declaredCapabilities, - newNc); - } - - return newNc; - } - - private void updateNetworkInfoForRoamingAndSuspended(NetworkAgentInfo nai, - NetworkCapabilities prevNc, NetworkCapabilities newNc) { - final boolean prevSuspended = !prevNc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED); - final boolean suspended = !newNc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED); - final boolean prevRoaming = !prevNc.hasCapability(NET_CAPABILITY_NOT_ROAMING); - final boolean roaming = !newNc.hasCapability(NET_CAPABILITY_NOT_ROAMING); - if (prevSuspended != suspended) { - // TODO (b/73132094) : remove this call once the few users of onSuspended and - // onResumed have been removed. - notifyNetworkCallbacks(nai, suspended ? ConnectivityManager.CALLBACK_SUSPENDED - : ConnectivityManager.CALLBACK_RESUMED); - } - if (prevSuspended != suspended || prevRoaming != roaming) { - // updateNetworkInfo will mix in the suspended info from the capabilities and - // take appropriate action for the network having possibly changed state. - updateNetworkInfo(nai, nai.networkInfo); - } - } - - /** - * Update the NetworkCapabilities for {@code nai} to {@code nc}. Specifically: - * - * 1. Calls mixInCapabilities to merge the passed-in NetworkCapabilities {@code nc} with the - * capabilities we manage and store in {@code nai}, such as validated status and captive - * portal status) - * 2. Takes action on the result: changes network permissions, sends CAP_CHANGED callbacks, and - * potentially triggers rematches. - * 3. Directly informs other network stack components (NetworkStatsService, VPNs, etc. of the - * change.) - * - * @param oldScore score of the network before any of the changes that prompted us - * to call this function. - * @param nai the network having its capabilities updated. - * @param nc the new network capabilities. - */ - private void updateCapabilities(final int oldScore, @NonNull final NetworkAgentInfo nai, - @NonNull final NetworkCapabilities nc) { - NetworkCapabilities newNc = mixInCapabilities(nai, nc); - if (Objects.equals(nai.networkCapabilities, newNc)) return; - updateNetworkPermissions(nai, newNc); - final NetworkCapabilities prevNc = nai.getAndSetNetworkCapabilities(newNc); - - updateUids(nai, prevNc, newNc); - nai.updateScoreForNetworkAgentUpdate(); - - if (nai.getCurrentScore() == oldScore && newNc.equalRequestableCapabilities(prevNc)) { - // If the requestable capabilities haven't changed, and the score hasn't changed, then - // the change we're processing can't affect any requests, it can only affect the listens - // on this network. We might have been called by rematchNetworkAndRequests when a - // network changed foreground state. - processListenRequests(nai); - } else { - // If the requestable capabilities have changed or the score changed, we can't have been - // called by rematchNetworkAndRequests, so it's safe to start a rematch. - rematchAllNetworksAndRequests(); - notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED); - } - updateNetworkInfoForRoamingAndSuspended(nai, prevNc, newNc); - - final boolean oldMetered = prevNc.isMetered(); - final boolean newMetered = newNc.isMetered(); - final boolean meteredChanged = oldMetered != newMetered; - - if (meteredChanged) { - maybeNotifyNetworkBlocked(nai, oldMetered, newMetered, - mVpnBlockedUidRanges, mVpnBlockedUidRanges); - } - - final boolean roamingChanged = prevNc.hasCapability(NET_CAPABILITY_NOT_ROAMING) - != newNc.hasCapability(NET_CAPABILITY_NOT_ROAMING); - - // Report changes that are interesting for network statistics tracking. - if (meteredChanged || roamingChanged) { - notifyIfacesChangedForNetworkStats(); - } - - // This network might have been underlying another network. Propagate its capabilities. - propagateUnderlyingNetworkCapabilities(nai.network); - - if (!newNc.equalsTransportTypes(prevNc)) { - mDnsManager.updateTransportsForNetwork( - nai.network.getNetId(), newNc.getTransportTypes()); - } - } - - /** Convenience method to update the capabilities for a given network. */ - private void updateCapabilitiesForNetwork(NetworkAgentInfo nai) { - updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities); - } - - /** - * Returns whether VPN isolation (ingress interface filtering) should be applied on the given - * network. - * - * Ingress interface filtering enforces that all apps under the given network can only receive - * packets from the network's interface (and loopback). This is important for VPNs because - * apps that cannot bypass a fully-routed VPN shouldn't be able to receive packets from any - * non-VPN interfaces. - * - * As a result, this method should return true iff - * 1. the network is an app VPN (not legacy VPN) - * 2. the VPN does not allow bypass - * 3. the VPN is fully-routed - * 4. the VPN interface is non-null - * - * @see INetd#firewallAddUidInterfaceRules - * @see INetd#firewallRemoveUidInterfaceRules - */ - private boolean requiresVpnIsolation(@NonNull NetworkAgentInfo nai, NetworkCapabilities nc, - LinkProperties lp) { - if (nc == null || lp == null) return false; - return nai.isVPN() - && !nai.networkAgentConfig.allowBypass - && nc.getOwnerUid() != Process.SYSTEM_UID - && lp.getInterfaceName() != null - && (lp.hasIpv4DefaultRoute() || lp.hasIpv4UnreachableDefaultRoute()) - && (lp.hasIpv6DefaultRoute() || lp.hasIpv6UnreachableDefaultRoute()); - } - - private static UidRangeParcel[] toUidRangeStableParcels(final @NonNull Set ranges) { - final UidRangeParcel[] stableRanges = new UidRangeParcel[ranges.size()]; - int index = 0; - for (UidRange range : ranges) { - stableRanges[index] = new UidRangeParcel(range.start, range.stop); - index++; - } - return stableRanges; - } - - private static UidRangeParcel[] toUidRangeStableParcels(UidRange[] ranges) { - final UidRangeParcel[] stableRanges = new UidRangeParcel[ranges.length]; - for (int i = 0; i < ranges.length; i++) { - stableRanges[i] = new UidRangeParcel(ranges[i].start, ranges[i].stop); - } - return stableRanges; - } - - private void maybeCloseSockets(NetworkAgentInfo nai, UidRangeParcel[] ranges, - int[] exemptUids) { - if (nai.isVPN() && !nai.networkAgentConfig.allowBypass) { - try { - mNetd.socketDestroy(ranges, exemptUids); - } catch (Exception e) { - loge("Exception in socket destroy: ", e); - } - } - } - - private void updateUidRanges(boolean add, NetworkAgentInfo nai, Set uidRanges) { - int[] exemptUids = new int[2]; - // TODO: Excluding VPN_UID is necessary in order to not to kill the TCP connection used - // by PPTP. Fix this by making Vpn set the owner UID to VPN_UID instead of system when - // starting a legacy VPN, and remove VPN_UID here. (b/176542831) - exemptUids[0] = VPN_UID; - exemptUids[1] = nai.networkCapabilities.getOwnerUid(); - UidRangeParcel[] ranges = toUidRangeStableParcels(uidRanges); - - maybeCloseSockets(nai, ranges, exemptUids); - try { - if (add) { - mNetd.networkAddUidRanges(nai.network.netId, ranges); - } else { - mNetd.networkRemoveUidRanges(nai.network.netId, ranges); - } - } catch (Exception e) { - loge("Exception while " + (add ? "adding" : "removing") + " uid ranges " + uidRanges + - " on netId " + nai.network.netId + ". " + e); - } - maybeCloseSockets(nai, ranges, exemptUids); - } - - private void updateUids(NetworkAgentInfo nai, NetworkCapabilities prevNc, - NetworkCapabilities newNc) { - Set prevRanges = null == prevNc ? null : prevNc.getUidRanges(); - Set newRanges = null == newNc ? null : newNc.getUidRanges(); - if (null == prevRanges) prevRanges = new ArraySet<>(); - if (null == newRanges) newRanges = new ArraySet<>(); - final Set prevRangesCopy = new ArraySet<>(prevRanges); - - prevRanges.removeAll(newRanges); - newRanges.removeAll(prevRangesCopy); - - try { - // When updating the VPN uid routing rules, add the new range first then remove the old - // range. If old range were removed first, there would be a window between the old - // range being removed and the new range being added, during which UIDs contained - // in both ranges are not subject to any VPN routing rules. Adding new range before - // removing old range works because, unlike the filtering rules below, it's possible to - // add duplicate UID routing rules. - // TODO: calculate the intersection of add & remove. Imagining that we are trying to - // remove uid 3 from a set containing 1-5. Intersection of the prev and new sets is: - // [1-5] & [1-2],[4-5] == [3] - // Then we can do: - // maybeCloseSockets([3]) - // mNetd.networkAddUidRanges([1-2],[4-5]) - // mNetd.networkRemoveUidRanges([1-5]) - // maybeCloseSockets([3]) - // This can prevent the sockets of uid 1-2, 4-5 from being closed. It also reduce the - // number of binder calls from 6 to 4. - if (!newRanges.isEmpty()) { - updateUidRanges(true, nai, newRanges); - } - if (!prevRanges.isEmpty()) { - updateUidRanges(false, nai, prevRanges); - } - final boolean wasFiltering = requiresVpnIsolation(nai, prevNc, nai.linkProperties); - final boolean shouldFilter = requiresVpnIsolation(nai, newNc, nai.linkProperties); - final String iface = nai.linkProperties.getInterfaceName(); - // For VPN uid interface filtering, old ranges need to be removed before new ranges can - // be added, due to the range being expanded and stored as individual UIDs. For example - // the UIDs might be updated from [0, 99999] to ([0, 10012], [10014, 99999]) which means - // prevRanges = [0, 99999] while newRanges = [0, 10012], [10014, 99999]. If prevRanges - // were added first and then newRanges got removed later, there would be only one uid - // 10013 left. A consequence of removing old ranges before adding new ranges is that - // there is now a window of opportunity when the UIDs are not subject to any filtering. - // Note that this is in contrast with the (more robust) update of VPN routing rules - // above, where the addition of new ranges happens before the removal of old ranges. - // TODO Fix this window by computing an accurate diff on Set, so the old range - // to be removed will never overlap with the new range to be added. - if (wasFiltering && !prevRanges.isEmpty()) { - mPermissionMonitor.onVpnUidRangesRemoved(iface, prevRanges, prevNc.getOwnerUid()); - } - if (shouldFilter && !newRanges.isEmpty()) { - mPermissionMonitor.onVpnUidRangesAdded(iface, newRanges, newNc.getOwnerUid()); - } - } catch (Exception e) { - // Never crash! - loge("Exception in updateUids: ", e); - } - } - - public void handleUpdateLinkProperties(NetworkAgentInfo nai, LinkProperties newLp) { - ensureRunningOnConnectivityServiceThread(); - - if (getNetworkAgentInfoForNetId(nai.network.getNetId()) != nai) { - // Ignore updates for disconnected networks - return; - } - if (VDBG || DDBG) { - log("Update of LinkProperties for " + nai.toShortString() - + "; created=" + nai.created - + "; everConnected=" + nai.everConnected); - } - // TODO: eliminate this defensive copy after confirming that updateLinkProperties does not - // modify its oldLp parameter. - updateLinkProperties(nai, newLp, new LinkProperties(nai.linkProperties)); - } - - private void sendPendingIntentForRequest(NetworkRequestInfo nri, NetworkAgentInfo networkAgent, - int notificationType) { - if (notificationType == ConnectivityManager.CALLBACK_AVAILABLE && !nri.mPendingIntentSent) { - Intent intent = new Intent(); - intent.putExtra(ConnectivityManager.EXTRA_NETWORK, networkAgent.network); - // If apps could file multi-layer requests with PendingIntents, they'd need to know - // which of the layer is satisfied alongside with some ID for the request. Hence, if - // such an API is ever implemented, there is no doubt the right request to send in - // EXTRA_NETWORK_REQUEST is mActiveRequest, and whatever ID would be added would need to - // be sent as a separate extra. - intent.putExtra(ConnectivityManager.EXTRA_NETWORK_REQUEST, nri.getActiveRequest()); - nri.mPendingIntentSent = true; - sendIntent(nri.mPendingIntent, intent); - } - // else not handled - } - - private void sendIntent(PendingIntent pendingIntent, Intent intent) { - mPendingIntentWakeLock.acquire(); - try { - if (DBG) log("Sending " + pendingIntent); - pendingIntent.send(mContext, 0, intent, this /* onFinished */, null /* Handler */); - } catch (PendingIntent.CanceledException e) { - if (DBG) log(pendingIntent + " was not sent, it had been canceled."); - mPendingIntentWakeLock.release(); - releasePendingNetworkRequest(pendingIntent); - } - // ...otherwise, mPendingIntentWakeLock.release() gets called by onSendFinished() - } - - @Override - public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode, - String resultData, Bundle resultExtras) { - if (DBG) log("Finished sending " + pendingIntent); - mPendingIntentWakeLock.release(); - // Release with a delay so the receiving client has an opportunity to put in its - // own request. - releasePendingNetworkRequestWithDelay(pendingIntent); - } - - private void callCallbackForRequest(@NonNull final NetworkRequestInfo nri, - @NonNull final NetworkAgentInfo networkAgent, final int notificationType, - final int arg1) { - if (nri.mMessenger == null) { - // Default request has no msgr. Also prevents callbacks from being invoked for - // NetworkRequestInfos registered with ConnectivityDiagnostics requests. Those callbacks - // are Type.LISTEN, but should not have NetworkCallbacks invoked. - return; - } - Bundle bundle = new Bundle(); - // TODO b/177608132: make sure callbacks are indexed by NRIs and not NetworkRequest objects. - // TODO: check if defensive copies of data is needed. - final NetworkRequest nrForCallback = nri.getNetworkRequestForCallback(); - putParcelable(bundle, nrForCallback); - Message msg = Message.obtain(); - if (notificationType != ConnectivityManager.CALLBACK_UNAVAIL) { - putParcelable(bundle, networkAgent.network); - } - final boolean includeLocationSensitiveInfo = - (nri.mCallbackFlags & NetworkCallback.FLAG_INCLUDE_LOCATION_INFO) != 0; - switch (notificationType) { - case ConnectivityManager.CALLBACK_AVAILABLE: { - final NetworkCapabilities nc = - networkCapabilitiesRestrictedForCallerPermissions( - networkAgent.networkCapabilities, nri.mPid, nri.mUid); - putParcelable( - bundle, - createWithLocationInfoSanitizedIfNecessaryWhenParceled( - nc, includeLocationSensitiveInfo, nri.mPid, nri.mUid, - nrForCallback.getRequestorPackageName(), - nri.mCallingAttributionTag)); - putParcelable(bundle, linkPropertiesRestrictedForCallerPermissions( - networkAgent.linkProperties, nri.mPid, nri.mUid)); - // For this notification, arg1 contains the blocked status. - msg.arg1 = arg1; - break; - } - case ConnectivityManager.CALLBACK_LOSING: { - msg.arg1 = arg1; - break; - } - case ConnectivityManager.CALLBACK_CAP_CHANGED: { - // networkAgent can't be null as it has been accessed a few lines above. - final NetworkCapabilities netCap = - networkCapabilitiesRestrictedForCallerPermissions( - networkAgent.networkCapabilities, nri.mPid, nri.mUid); - putParcelable( - bundle, - createWithLocationInfoSanitizedIfNecessaryWhenParceled( - netCap, includeLocationSensitiveInfo, nri.mPid, nri.mUid, - nrForCallback.getRequestorPackageName(), - nri.mCallingAttributionTag)); - break; - } - case ConnectivityManager.CALLBACK_IP_CHANGED: { - putParcelable(bundle, linkPropertiesRestrictedForCallerPermissions( - networkAgent.linkProperties, nri.mPid, nri.mUid)); - break; - } - case ConnectivityManager.CALLBACK_BLK_CHANGED: { - maybeLogBlockedStatusChanged(nri, networkAgent.network, arg1); - msg.arg1 = arg1; - break; - } - } - msg.what = notificationType; - msg.setData(bundle); - try { - if (VDBG) { - String notification = ConnectivityManager.getCallbackName(notificationType); - log("sending notification " + notification + " for " + nrForCallback); - } - nri.mMessenger.send(msg); - } catch (RemoteException e) { - // may occur naturally in the race of binder death. - loge("RemoteException caught trying to send a callback msg for " + nrForCallback); - } - } - - private static void putParcelable(Bundle bundle, T t) { - bundle.putParcelable(t.getClass().getSimpleName(), t); - } - - private void teardownUnneededNetwork(NetworkAgentInfo nai) { - if (nai.numRequestNetworkRequests() != 0) { - for (int i = 0; i < nai.numNetworkRequests(); i++) { - NetworkRequest nr = nai.requestAt(i); - // Ignore listening and track default requests. - if (!nr.isRequest()) continue; - loge("Dead network still had at least " + nr); - break; - } - } - nai.disconnect(); - } - - private void handleLingerComplete(NetworkAgentInfo oldNetwork) { - if (oldNetwork == null) { - loge("Unknown NetworkAgentInfo in handleLingerComplete"); - return; - } - if (DBG) log("handleLingerComplete for " + oldNetwork.toShortString()); - - // If we get here it means that the last linger timeout for this network expired. So there - // must be no other active linger timers, and we must stop lingering. - oldNetwork.clearInactivityState(); - - if (unneeded(oldNetwork, UnneededFor.TEARDOWN)) { - // Tear the network down. - teardownUnneededNetwork(oldNetwork); - } else { - // Put the network in the background if it doesn't satisfy any foreground request. - updateCapabilitiesForNetwork(oldNetwork); - } - } - - private void processDefaultNetworkChanges(@NonNull final NetworkReassignment changes) { - boolean isDefaultChanged = false; - for (final NetworkRequestInfo defaultRequestInfo : mDefaultNetworkRequests) { - final NetworkReassignment.RequestReassignment reassignment = - changes.getReassignment(defaultRequestInfo); - if (null == reassignment) { - continue; - } - // reassignment only contains those instances where the satisfying network changed. - isDefaultChanged = true; - // Notify system services of the new default. - makeDefault(defaultRequestInfo, reassignment.mOldNetwork, reassignment.mNewNetwork); - } - - if (isDefaultChanged) { - // Hold a wakelock for a short time to help apps in migrating to a new default. - scheduleReleaseNetworkTransitionWakelock(); - } - } - - private void makeDefault(@NonNull final NetworkRequestInfo nri, - @Nullable final NetworkAgentInfo oldDefaultNetwork, - @Nullable final NetworkAgentInfo newDefaultNetwork) { - if (DBG) { - log("Switching to new default network for: " + nri + " using " + newDefaultNetwork); - } - - // Fix up the NetworkCapabilities of any networks that have this network as underlying. - if (newDefaultNetwork != null) { - propagateUnderlyingNetworkCapabilities(newDefaultNetwork.network); - } - - // Set an app level managed default and return since further processing only applies to the - // default network. - if (mDefaultRequest != nri) { - makeDefaultForApps(nri, oldDefaultNetwork, newDefaultNetwork); - return; - } - - makeDefaultNetwork(newDefaultNetwork); - - if (oldDefaultNetwork != null) { - mLingerMonitor.noteLingerDefaultNetwork(oldDefaultNetwork, newDefaultNetwork); - } - mNetworkActivityTracker.updateDataActivityTracking(newDefaultNetwork, oldDefaultNetwork); - handleApplyDefaultProxy(null != newDefaultNetwork - ? newDefaultNetwork.linkProperties.getHttpProxy() : null); - updateTcpBufferSizes(null != newDefaultNetwork - ? newDefaultNetwork.linkProperties.getTcpBufferSizes() : null); - notifyIfacesChangedForNetworkStats(); - } - - private void makeDefaultForApps(@NonNull final NetworkRequestInfo nri, - @Nullable final NetworkAgentInfo oldDefaultNetwork, - @Nullable final NetworkAgentInfo newDefaultNetwork) { - try { - if (VDBG) { - log("Setting default network for " + nri - + " using UIDs " + nri.getUids() - + " with old network " + (oldDefaultNetwork != null - ? oldDefaultNetwork.network().getNetId() : "null") - + " and new network " + (newDefaultNetwork != null - ? newDefaultNetwork.network().getNetId() : "null")); - } - if (nri.getUids().isEmpty()) { - throw new IllegalStateException("makeDefaultForApps called without specifying" - + " any applications to set as the default." + nri); - } - if (null != newDefaultNetwork) { - mNetd.networkAddUidRanges( - newDefaultNetwork.network.getNetId(), - toUidRangeStableParcels(nri.getUids())); - } - if (null != oldDefaultNetwork) { - mNetd.networkRemoveUidRanges( - oldDefaultNetwork.network.getNetId(), - toUidRangeStableParcels(nri.getUids())); - } - } catch (RemoteException | ServiceSpecificException e) { - loge("Exception setting app default network", e); - } - } - - private void makeDefaultNetwork(@Nullable final NetworkAgentInfo newDefaultNetwork) { - try { - if (null != newDefaultNetwork) { - mNetd.networkSetDefault(newDefaultNetwork.network.getNetId()); - } else { - mNetd.networkClearDefault(); - } - } catch (RemoteException | ServiceSpecificException e) { - loge("Exception setting default network :" + e); - } - } - - private void processListenRequests(@NonNull final NetworkAgentInfo nai) { - // For consistency with previous behaviour, send onLost callbacks before onAvailable. - processNewlyLostListenRequests(nai); - notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED); - processNewlySatisfiedListenRequests(nai); - } - - private void processNewlyLostListenRequests(@NonNull final NetworkAgentInfo nai) { - for (final NetworkRequestInfo nri : mNetworkRequests.values()) { - if (nri.isMultilayerRequest()) { - continue; - } - final NetworkRequest nr = nri.mRequests.get(0); - if (!nr.isListen()) continue; - if (nai.isSatisfyingRequest(nr.requestId) && !nai.satisfies(nr)) { - nai.removeRequest(nr.requestId); - callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_LOST, 0); - } - } - } - - private void processNewlySatisfiedListenRequests(@NonNull final NetworkAgentInfo nai) { - for (final NetworkRequestInfo nri : mNetworkRequests.values()) { - if (nri.isMultilayerRequest()) { - continue; - } - final NetworkRequest nr = nri.mRequests.get(0); - if (!nr.isListen()) continue; - if (nai.satisfies(nr) && !nai.isSatisfyingRequest(nr.requestId)) { - nai.addRequest(nr); - notifyNetworkAvailable(nai, nri); - } - } - } - - // An accumulator class to gather the list of changes that result from a rematch. - private static class NetworkReassignment { - static class RequestReassignment { - @NonNull public final NetworkRequestInfo mNetworkRequestInfo; - @Nullable public final NetworkRequest mOldNetworkRequest; - @Nullable public final NetworkRequest mNewNetworkRequest; - @Nullable public final NetworkAgentInfo mOldNetwork; - @Nullable public final NetworkAgentInfo mNewNetwork; - RequestReassignment(@NonNull final NetworkRequestInfo networkRequestInfo, - @Nullable final NetworkRequest oldNetworkRequest, - @Nullable final NetworkRequest newNetworkRequest, - @Nullable final NetworkAgentInfo oldNetwork, - @Nullable final NetworkAgentInfo newNetwork) { - mNetworkRequestInfo = networkRequestInfo; - mOldNetworkRequest = oldNetworkRequest; - mNewNetworkRequest = newNetworkRequest; - mOldNetwork = oldNetwork; - mNewNetwork = newNetwork; - } - - public String toString() { - final NetworkRequest requestToShow = null != mNewNetworkRequest - ? mNewNetworkRequest : mNetworkRequestInfo.mRequests.get(0); - return requestToShow.requestId + " : " - + (null != mOldNetwork ? mOldNetwork.network.getNetId() : "null") - + " → " + (null != mNewNetwork ? mNewNetwork.network.getNetId() : "null"); - } - } - - @NonNull private final ArrayList mReassignments = new ArrayList<>(); - - @NonNull Iterable getRequestReassignments() { - return mReassignments; - } - - void addRequestReassignment(@NonNull final RequestReassignment reassignment) { - if (Build.isDebuggable()) { - // The code is never supposed to add two reassignments of the same request. Make - // sure this stays true, but without imposing this expensive check on all - // reassignments on all user devices. - for (final RequestReassignment existing : mReassignments) { - if (existing.mNetworkRequestInfo.equals(reassignment.mNetworkRequestInfo)) { - throw new IllegalStateException("Trying to reassign [" - + reassignment + "] but already have [" - + existing + "]"); - } - } - } - mReassignments.add(reassignment); - } - - // Will return null if this reassignment does not change the network assigned to - // the passed request. - @Nullable - private RequestReassignment getReassignment(@NonNull final NetworkRequestInfo nri) { - for (final RequestReassignment event : getRequestReassignments()) { - if (nri == event.mNetworkRequestInfo) return event; - } - return null; - } - - public String toString() { - final StringJoiner sj = new StringJoiner(", " /* delimiter */, - "NetReassign [" /* prefix */, "]" /* suffix */); - if (mReassignments.isEmpty()) return sj.add("no changes").toString(); - for (final RequestReassignment rr : getRequestReassignments()) { - sj.add(rr.toString()); - } - return sj.toString(); - } - - public String debugString() { - final StringBuilder sb = new StringBuilder(); - sb.append("NetworkReassignment :"); - if (mReassignments.isEmpty()) return sb.append(" no changes").toString(); - for (final RequestReassignment rr : getRequestReassignments()) { - sb.append("\n ").append(rr); - } - return sb.append("\n").toString(); - } - } - - private void updateSatisfiersForRematchRequest(@NonNull final NetworkRequestInfo nri, - @Nullable final NetworkRequest previousRequest, - @Nullable final NetworkRequest newRequest, - @Nullable final NetworkAgentInfo previousSatisfier, - @Nullable final NetworkAgentInfo newSatisfier, - final long now) { - if (null != newSatisfier && mNoServiceNetwork != newSatisfier) { - if (VDBG) log("rematch for " + newSatisfier.toShortString()); - if (null != previousRequest && null != previousSatisfier) { - if (VDBG || DDBG) { - log(" accepting network in place of " + previousSatisfier.toShortString()); - } - previousSatisfier.removeRequest(previousRequest.requestId); - previousSatisfier.lingerRequest(previousRequest.requestId, now); - } else { - if (VDBG || DDBG) log(" accepting network in place of null"); - } - - // To prevent constantly CPU wake up for nascent timer, if a network comes up - // and immediately satisfies a request then remove the timer. This will happen for - // all networks except in the case of an underlying network for a VCN. - if (newSatisfier.isNascent()) { - newSatisfier.unlingerRequest(NetworkRequest.REQUEST_ID_NONE); - newSatisfier.unsetInactive(); - } - - // if newSatisfier is not null, then newRequest may not be null. - newSatisfier.unlingerRequest(newRequest.requestId); - if (!newSatisfier.addRequest(newRequest)) { - Log.wtf(TAG, "BUG: " + newSatisfier.toShortString() + " already has " - + newRequest); - } - } else if (null != previousRequest && null != previousSatisfier) { - if (DBG) { - log("Network " + previousSatisfier.toShortString() + " stopped satisfying" - + " request " + previousRequest.requestId); - } - previousSatisfier.removeRequest(previousRequest.requestId); - } - nri.setSatisfier(newSatisfier, newRequest); - } - - /** - * This function is triggered when something can affect what network should satisfy what - * request, and it computes the network reassignment from the passed collection of requests to - * network match to the one that the system should now have. That data is encoded in an - * object that is a list of changes, each of them having an NRI, and old satisfier, and a new - * satisfier. - * - * After the reassignment is computed, it is applied to the state objects. - * - * @param networkRequests the nri objects to evaluate for possible network reassignment - * @return NetworkReassignment listing of proposed network assignment changes - */ - @NonNull - private NetworkReassignment computeNetworkReassignment( - @NonNull final Collection networkRequests) { - final NetworkReassignment changes = new NetworkReassignment(); - - // Gather the list of all relevant agents. - final ArrayList nais = new ArrayList<>(); - for (final NetworkAgentInfo nai : mNetworkAgentInfos) { - if (!nai.everConnected) { - continue; - } - nais.add(nai); - } - - for (final NetworkRequestInfo nri : networkRequests) { - // Non-multilayer listen requests can be ignored. - if (!nri.isMultilayerRequest() && nri.mRequests.get(0).isListen()) { - continue; - } - NetworkAgentInfo bestNetwork = null; - NetworkRequest bestRequest = null; - for (final NetworkRequest req : nri.mRequests) { - bestNetwork = mNetworkRanker.getBestNetwork(req, nais, nri.getSatisfier()); - // Stop evaluating as the highest possible priority request is satisfied. - if (null != bestNetwork) { - bestRequest = req; - break; - } - } - if (null == bestNetwork && isDefaultBlocked(nri)) { - // Remove default networking if disallowed for managed default requests. - bestNetwork = mNoServiceNetwork; - } - if (nri.getSatisfier() != bestNetwork) { - // bestNetwork may be null if no network can satisfy this request. - changes.addRequestReassignment(new NetworkReassignment.RequestReassignment( - nri, nri.mActiveRequest, bestRequest, nri.getSatisfier(), bestNetwork)); - } - } - return changes; - } - - private Set getNrisFromGlobalRequests() { - return new HashSet<>(mNetworkRequests.values()); - } - - /** - * Attempt to rematch all Networks with all NetworkRequests. This may result in Networks - * being disconnected. - */ - private void rematchAllNetworksAndRequests() { - rematchNetworksAndRequests(getNrisFromGlobalRequests()); - } - - /** - * Attempt to rematch all Networks with given NetworkRequests. This may result in Networks - * being disconnected. - */ - private void rematchNetworksAndRequests( - @NonNull final Set networkRequests) { - ensureRunningOnConnectivityServiceThread(); - // TODO: This may be slow, and should be optimized. - final long now = SystemClock.elapsedRealtime(); - final NetworkReassignment changes = computeNetworkReassignment(networkRequests); - if (VDBG || DDBG) { - log(changes.debugString()); - } else if (DBG) { - log(changes.toString()); // Shorter form, only one line of log - } - applyNetworkReassignment(changes, now); - issueNetworkNeeds(); - } - - private void applyNetworkReassignment(@NonNull final NetworkReassignment changes, - final long now) { - final Collection nais = mNetworkAgentInfos; - - // Since most of the time there are only 0 or 1 background networks, it would probably - // be more efficient to just use an ArrayList here. TODO : measure performance - final ArraySet oldBgNetworks = new ArraySet<>(); - for (final NetworkAgentInfo nai : nais) { - if (nai.isBackgroundNetwork()) oldBgNetworks.add(nai); - } - - // First, update the lists of satisfied requests in the network agents. This is necessary - // because some code later depends on this state to be correct, most prominently computing - // the linger status. - for (final NetworkReassignment.RequestReassignment event : - changes.getRequestReassignments()) { - updateSatisfiersForRematchRequest(event.mNetworkRequestInfo, - event.mOldNetworkRequest, event.mNewNetworkRequest, - event.mOldNetwork, event.mNewNetwork, - now); - } - - // Process default network changes if applicable. - processDefaultNetworkChanges(changes); - - // Notify requested networks are available after the default net is switched, but - // before LegacyTypeTracker sends legacy broadcasts - for (final NetworkReassignment.RequestReassignment event : - changes.getRequestReassignments()) { - if (null != event.mNewNetwork) { - notifyNetworkAvailable(event.mNewNetwork, event.mNetworkRequestInfo); - } else { - callCallbackForRequest(event.mNetworkRequestInfo, event.mOldNetwork, - ConnectivityManager.CALLBACK_LOST, 0); - } - } - - // Update the inactivity state before processing listen callbacks, because the background - // computation depends on whether the network is inactive. Don't send the LOSING callbacks - // just yet though, because they have to be sent after the listens are processed to keep - // backward compatibility. - final ArrayList inactiveNetworks = new ArrayList<>(); - for (final NetworkAgentInfo nai : nais) { - // Rematching may have altered the inactivity state of some networks, so update all - // inactivity timers. updateInactivityState reads the state from the network agent - // and does nothing if the state has not changed : the source of truth is controlled - // with NetworkAgentInfo#lingerRequest and NetworkAgentInfo#unlingerRequest, which - // have been called while rematching the individual networks above. - if (updateInactivityState(nai, now)) { - inactiveNetworks.add(nai); - } - } - - for (final NetworkAgentInfo nai : nais) { - if (!nai.everConnected) continue; - final boolean oldBackground = oldBgNetworks.contains(nai); - // Process listen requests and update capabilities if the background state has - // changed for this network. For consistency with previous behavior, send onLost - // callbacks before onAvailable. - processNewlyLostListenRequests(nai); - if (oldBackground != nai.isBackgroundNetwork()) { - applyBackgroundChangeForRematch(nai); - } - processNewlySatisfiedListenRequests(nai); - } - - for (final NetworkAgentInfo nai : inactiveNetworks) { - // For nascent networks, if connecting with no foreground request, skip broadcasting - // LOSING for backward compatibility. This is typical when mobile data connected while - // wifi connected with mobile data always-on enabled. - if (nai.isNascent()) continue; - notifyNetworkLosing(nai, now); - } - - updateLegacyTypeTrackerAndVpnLockdownForRematch(changes, nais); - - // Tear down all unneeded networks. - for (NetworkAgentInfo nai : mNetworkAgentInfos) { - if (unneeded(nai, UnneededFor.TEARDOWN)) { - if (nai.getInactivityExpiry() > 0) { - // This network has active linger timers and no requests, but is not - // lingering. Linger it. - // - // One way (the only way?) this can happen if this network is unvalidated - // and became unneeded due to another network improving its score to the - // point where this network will no longer be able to satisfy any requests - // even if it validates. - if (updateInactivityState(nai, now)) { - notifyNetworkLosing(nai, now); - } - } else { - if (DBG) log("Reaping " + nai.toShortString()); - teardownUnneededNetwork(nai); - } - } - } - } - - /** - * Apply a change in background state resulting from rematching networks with requests. - * - * During rematch, a network may change background states by starting to satisfy or stopping - * to satisfy a foreground request. Listens don't count for this. When a network changes - * background states, its capabilities need to be updated and callbacks fired for the - * capability change. - * - * @param nai The network that changed background states - */ - private void applyBackgroundChangeForRematch(@NonNull final NetworkAgentInfo nai) { - final NetworkCapabilities newNc = mixInCapabilities(nai, nai.networkCapabilities); - if (Objects.equals(nai.networkCapabilities, newNc)) return; - updateNetworkPermissions(nai, newNc); - nai.getAndSetNetworkCapabilities(newNc); - notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED); - } - - private void updateLegacyTypeTrackerAndVpnLockdownForRematch( - @NonNull final NetworkReassignment changes, - @NonNull final Collection nais) { - final NetworkReassignment.RequestReassignment reassignmentOfDefault = - changes.getReassignment(mDefaultRequest); - final NetworkAgentInfo oldDefaultNetwork = - null != reassignmentOfDefault ? reassignmentOfDefault.mOldNetwork : null; - final NetworkAgentInfo newDefaultNetwork = - null != reassignmentOfDefault ? reassignmentOfDefault.mNewNetwork : null; - - if (oldDefaultNetwork != newDefaultNetwork) { - // Maintain the illusion : since the legacy API only understands one network at a time, - // if the default network changed, apps should see a disconnected broadcast for the - // old default network before they see a connected broadcast for the new one. - if (oldDefaultNetwork != null) { - mLegacyTypeTracker.remove(oldDefaultNetwork.networkInfo.getType(), - oldDefaultNetwork, true); - } - if (newDefaultNetwork != null) { - // The new default network can be newly null if and only if the old default - // network doesn't satisfy the default request any more because it lost a - // capability. - mDefaultInetConditionPublished = newDefaultNetwork.lastValidated ? 100 : 0; - mLegacyTypeTracker.add( - newDefaultNetwork.networkInfo.getType(), newDefaultNetwork); - } - } - - // Now that all the callbacks have been sent, send the legacy network broadcasts - // as needed. This is necessary so that legacy requests correctly bind dns - // requests to this network. The legacy users are listening for this broadcast - // and will generally do a dns request so they can ensureRouteToHost and if - // they do that before the callbacks happen they'll use the default network. - // - // TODO: Is there still a race here? The legacy broadcast will be sent after sending - // callbacks, but if apps can receive the broadcast before the callback, they still might - // have an inconsistent view of networking. - // - // This *does* introduce a race where if the user uses the new api - // (notification callbacks) and then uses the old api (getNetworkInfo(type)) - // they may get old info. Reverse this after the old startUsing api is removed. - // This is on top of the multiple intent sequencing referenced in the todo above. - for (NetworkAgentInfo nai : nais) { - if (nai.everConnected) { - addNetworkToLegacyTypeTracker(nai); - } - } - } - - private void issueNetworkNeeds() { - ensureRunningOnConnectivityServiceThread(); - for (final NetworkOfferInfo noi : mNetworkOffers) { - issueNetworkNeeds(noi); - } - } - - private void issueNetworkNeeds(@NonNull final NetworkOfferInfo noi) { - ensureRunningOnConnectivityServiceThread(); - for (final NetworkRequestInfo nri : mNetworkRequests.values()) { - informOffer(nri, noi.offer, mNetworkRanker); - } - } - - /** - * Inform a NetworkOffer about any new situation of a request. - * - * This function handles updates to offers. A number of events may happen that require - * updating the registrant for this offer about the situation : - * • The offer itself was updated. This may lead the offer to no longer being able - * to satisfy a request or beat a satisfier (and therefore be no longer needed), - * or conversely being strengthened enough to beat the satisfier (and therefore - * start being needed) - * • The network satisfying a request changed (including cases where the request - * starts or stops being satisfied). The new network may be a stronger or weaker - * match than the old one, possibly affecting whether the offer is needed. - * • The network satisfying a request updated their score. This may lead the offer - * to no longer be able to beat it if the current satisfier got better, or - * conversely start being a good choice if the current satisfier got weaker. - * - * @param nri The request - * @param offer The offer. This may be an updated offer. - */ - private static void informOffer(@NonNull NetworkRequestInfo nri, - @NonNull final NetworkOffer offer, @NonNull final NetworkRanker networkRanker) { - final NetworkRequest activeRequest = nri.isBeingSatisfied() ? nri.getActiveRequest() : null; - final NetworkAgentInfo satisfier = null != activeRequest ? nri.getSatisfier() : null; - - // Multi-layer requests have a currently active request, the one being satisfied. - // Since the system will try to bring up a better network than is currently satisfying - // the request, NetworkProviders need to be told the offers matching the requests *above* - // the currently satisfied one are needed, that the ones *below* the satisfied one are - // not needed, and the offer is needed for the active request iff the offer can beat - // the satisfier. - // For non-multilayer requests, the logic above gracefully degenerates to only the - // last case. - // To achieve this, the loop below will proceed in three steps. In a first phase, inform - // providers that the offer is needed for this request, until the active request is found. - // In a second phase, deal with the currently active request. In a third phase, inform - // the providers that offer is unneeded for the remaining requests. - - // First phase : inform providers of all requests above the active request. - int i; - for (i = 0; nri.mRequests.size() > i; ++i) { - final NetworkRequest request = nri.mRequests.get(i); - if (activeRequest == request) break; // Found the active request : go to phase 2 - if (!request.isRequest()) continue; // Listens/track defaults are never sent to offers - // Since this request is higher-priority than the one currently satisfied, if the - // offer can satisfy it, the provider should try and bring up the network for sure ; - // no need to even ask the ranker – an offer that can satisfy is always better than - // no network. Hence tell the provider so unless it already knew. - if (request.canBeSatisfiedBy(offer.caps) && !offer.neededFor(request)) { - offer.onNetworkNeeded(request); - } - } - - // Second phase : deal with the active request (if any) - if (null != activeRequest && activeRequest.isRequest()) { - final boolean oldNeeded = offer.neededFor(activeRequest); - // An offer is needed if it is currently served by this provider or if this offer - // can beat the current satisfier. - final boolean currentlyServing = satisfier != null - && satisfier.factorySerialNumber == offer.providerId; - final boolean newNeeded = (currentlyServing - || (activeRequest.canBeSatisfiedBy(offer.caps) - && networkRanker.mightBeat(activeRequest, satisfier, offer))); - if (newNeeded != oldNeeded) { - if (newNeeded) { - offer.onNetworkNeeded(activeRequest); - } else { - // The offer used to be able to beat the satisfier. Now it can't. - offer.onNetworkUnneeded(activeRequest); - } - } - } - - // Third phase : inform the providers that the offer isn't needed for any request - // below the active one. - for (++i /* skip the active request */; nri.mRequests.size() > i; ++i) { - final NetworkRequest request = nri.mRequests.get(i); - if (!request.isRequest()) continue; // Listens/track defaults are never sent to offers - // Since this request is lower-priority than the one currently satisfied, if the - // offer can satisfy it, the provider should not try and bring up the network. - // Hence tell the provider so unless it already knew. - if (offer.neededFor(request)) { - offer.onNetworkUnneeded(request); - } - } - } - - private void addNetworkToLegacyTypeTracker(@NonNull final NetworkAgentInfo nai) { - for (int i = 0; i < nai.numNetworkRequests(); i++) { - NetworkRequest nr = nai.requestAt(i); - if (nr.legacyType != TYPE_NONE && nr.isRequest()) { - // legacy type tracker filters out repeat adds - mLegacyTypeTracker.add(nr.legacyType, nai); - } - } - - // A VPN generally won't get added to the legacy tracker in the "for (nri)" loop above, - // because usually there are no NetworkRequests it satisfies (e.g., mDefaultRequest - // wants the NOT_VPN capability, so it will never be satisfied by a VPN). So, add the - // newNetwork to the tracker explicitly (it's a no-op if it has already been added). - if (nai.isVPN()) { - mLegacyTypeTracker.add(TYPE_VPN, nai); - } - } - - private void updateInetCondition(NetworkAgentInfo nai) { - // Don't bother updating until we've graduated to validated at least once. - if (!nai.everValidated) return; - // For now only update icons for the default connection. - // TODO: Update WiFi and cellular icons separately. b/17237507 - if (!isDefaultNetwork(nai)) return; - - int newInetCondition = nai.lastValidated ? 100 : 0; - // Don't repeat publish. - if (newInetCondition == mDefaultInetConditionPublished) return; - - mDefaultInetConditionPublished = newInetCondition; - sendInetConditionBroadcast(nai.networkInfo); - } - - @NonNull - private NetworkInfo mixInInfo(@NonNull final NetworkAgentInfo nai, @NonNull NetworkInfo info) { - final NetworkInfo newInfo = new NetworkInfo(info); - // The suspended and roaming bits are managed in NetworkCapabilities. - final boolean suspended = - !nai.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_SUSPENDED); - if (suspended && info.getDetailedState() == NetworkInfo.DetailedState.CONNECTED) { - // Only override the state with SUSPENDED if the network is currently in CONNECTED - // state. This is because the network could have been suspended before connecting, - // or it could be disconnecting while being suspended, and in both these cases - // the state should not be overridden. Note that the only detailed state that - // maps to State.CONNECTED is DetailedState.CONNECTED, so there is also no need to - // worry about multiple different substates of CONNECTED. - newInfo.setDetailedState(NetworkInfo.DetailedState.SUSPENDED, info.getReason(), - info.getExtraInfo()); - } else if (!suspended && info.getDetailedState() == NetworkInfo.DetailedState.SUSPENDED) { - // SUSPENDED state is currently only overridden from CONNECTED state. In the case the - // network agent is created, then goes to suspended, then goes out of suspended without - // ever setting connected. Check if network agent is ever connected to update the state. - newInfo.setDetailedState(nai.everConnected - ? NetworkInfo.DetailedState.CONNECTED - : NetworkInfo.DetailedState.CONNECTING, - info.getReason(), - info.getExtraInfo()); - } - newInfo.setRoaming(!nai.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_ROAMING)); - return newInfo; - } - - private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo info) { - final NetworkInfo newInfo = mixInInfo(networkAgent, info); - - final NetworkInfo.State state = newInfo.getState(); - NetworkInfo oldInfo = null; - synchronized (networkAgent) { - oldInfo = networkAgent.networkInfo; - networkAgent.networkInfo = newInfo; - } - - if (DBG) { - log(networkAgent.toShortString() + " EVENT_NETWORK_INFO_CHANGED, going from " - + oldInfo.getState() + " to " + state); - } - - if (!networkAgent.created - && (state == NetworkInfo.State.CONNECTED - || (state == NetworkInfo.State.CONNECTING && networkAgent.isVPN()))) { - - // A network that has just connected has zero requests and is thus a foreground network. - networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND); - - if (!createNativeNetwork(networkAgent)) return; - if (networkAgent.supportsUnderlyingNetworks()) { - // Initialize the network's capabilities to their starting values according to the - // underlying networks. This ensures that the capabilities are correct before - // anything happens to the network. - updateCapabilitiesForNetwork(networkAgent); - } - networkAgent.created = true; - networkAgent.onNetworkCreated(); - } - - if (!networkAgent.everConnected && state == NetworkInfo.State.CONNECTED) { - networkAgent.everConnected = true; - - // NetworkCapabilities need to be set before sending the private DNS config to - // NetworkMonitor, otherwise NetworkMonitor cannot determine if validation is required. - networkAgent.getAndSetNetworkCapabilities(networkAgent.networkCapabilities); - - handlePerNetworkPrivateDnsConfig(networkAgent, mDnsManager.getPrivateDnsConfig()); - updateLinkProperties(networkAgent, new LinkProperties(networkAgent.linkProperties), - null); - - // Until parceled LinkProperties are sent directly to NetworkMonitor, the connect - // command must be sent after updating LinkProperties to maximize chances of - // NetworkMonitor seeing the correct LinkProperties when starting. - // TODO: pass LinkProperties to the NetworkMonitor in the notifyNetworkConnected call. - if (networkAgent.networkAgentConfig.acceptPartialConnectivity) { - networkAgent.networkMonitor().setAcceptPartialConnectivity(); - } - networkAgent.networkMonitor().notifyNetworkConnected( - new LinkProperties(networkAgent.linkProperties, - true /* parcelSensitiveFields */), - networkAgent.networkCapabilities); - scheduleUnvalidatedPrompt(networkAgent); - - // Whether a particular NetworkRequest listen should cause signal strength thresholds to - // be communicated to a particular NetworkAgent depends only on the network's immutable, - // capabilities, so it only needs to be done once on initial connect, not every time the - // network's capabilities change. Note that we do this before rematching the network, - // so we could decide to tear it down immediately afterwards. That's fine though - on - // disconnection NetworkAgents should stop any signal strength monitoring they have been - // doing. - updateSignalStrengthThresholds(networkAgent, "CONNECT", null); - - // Before first rematching networks, put an inactivity timer without any request, this - // allows {@code updateInactivityState} to update the state accordingly and prevent - // tearing down for any {@code unneeded} evaluation in this period. - // Note that the timer will not be rescheduled since the expiry time is - // fixed after connection regardless of the network satisfying other requests or not. - // But it will be removed as soon as the network satisfies a request for the first time. - networkAgent.lingerRequest(NetworkRequest.REQUEST_ID_NONE, - SystemClock.elapsedRealtime(), mNascentDelayMs); - networkAgent.setInactive(); - - // Consider network even though it is not yet validated. - rematchAllNetworksAndRequests(); - - // This has to happen after matching the requests, because callbacks are just requests. - notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_PRECHECK); - } else if (state == NetworkInfo.State.DISCONNECTED) { - networkAgent.disconnect(); - if (networkAgent.isVPN()) { - updateUids(networkAgent, networkAgent.networkCapabilities, null); - } - disconnectAndDestroyNetwork(networkAgent); - if (networkAgent.isVPN()) { - // As the active or bound network changes for apps, broadcast the default proxy, as - // apps may need to update their proxy data. This is called after disconnecting from - // VPN to make sure we do not broadcast the old proxy data. - // TODO(b/122649188): send the broadcast only to VPN users. - mProxyTracker.sendProxyBroadcast(); - } - } else if (networkAgent.created && (oldInfo.getState() == NetworkInfo.State.SUSPENDED || - state == NetworkInfo.State.SUSPENDED)) { - mLegacyTypeTracker.update(networkAgent); - } - } - - private void updateNetworkScore(@NonNull final NetworkAgentInfo nai, final NetworkScore score) { - if (VDBG || DDBG) log("updateNetworkScore for " + nai.toShortString() + " to " + score); - nai.setScore(score); - rematchAllNetworksAndRequests(); - } - - // Notify only this one new request of the current state. Transfer all the - // current state by calling NetworkCapabilities and LinkProperties callbacks - // so that callers can be guaranteed to have as close to atomicity in state - // transfer as can be supported by this current API. - protected void notifyNetworkAvailable(NetworkAgentInfo nai, NetworkRequestInfo nri) { - mHandler.removeMessages(EVENT_TIMEOUT_NETWORK_REQUEST, nri); - if (nri.mPendingIntent != null) { - sendPendingIntentForRequest(nri, nai, ConnectivityManager.CALLBACK_AVAILABLE); - // Attempt no subsequent state pushes where intents are involved. - return; - } - - final int blockedReasons = mUidBlockedReasons.get(nri.mAsUid, BLOCKED_REASON_NONE); - final boolean metered = nai.networkCapabilities.isMetered(); - final boolean vpnBlocked = isUidBlockedByVpn(nri.mAsUid, mVpnBlockedUidRanges); - callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_AVAILABLE, - getBlockedState(blockedReasons, metered, vpnBlocked)); - } - - // Notify the requests on this NAI that the network is now lingered. - private void notifyNetworkLosing(@NonNull final NetworkAgentInfo nai, final long now) { - final int lingerTime = (int) (nai.getInactivityExpiry() - now); - notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOSING, lingerTime); - } - - private static int getBlockedState(int reasons, boolean metered, boolean vpnBlocked) { - if (!metered) reasons &= ~BLOCKED_METERED_REASON_MASK; - return vpnBlocked - ? reasons | BLOCKED_REASON_LOCKDOWN_VPN - : reasons & ~BLOCKED_REASON_LOCKDOWN_VPN; - } - - private void setUidBlockedReasons(int uid, @BlockedReason int blockedReasons) { - if (blockedReasons == BLOCKED_REASON_NONE) { - mUidBlockedReasons.delete(uid); - } else { - mUidBlockedReasons.put(uid, blockedReasons); - } - } - - /** - * Notify of the blocked state apps with a registered callback matching a given NAI. - * - * Unlike other callbacks, blocked status is different between each individual uid. So for - * any given nai, all requests need to be considered according to the uid who filed it. - * - * @param nai The target NetworkAgentInfo. - * @param oldMetered True if the previous network capabilities were metered. - * @param newMetered True if the current network capabilities are metered. - * @param oldBlockedUidRanges list of UID ranges previously blocked by lockdown VPN. - * @param newBlockedUidRanges list of UID ranges blocked by lockdown VPN. - */ - private void maybeNotifyNetworkBlocked(NetworkAgentInfo nai, boolean oldMetered, - boolean newMetered, List oldBlockedUidRanges, - List newBlockedUidRanges) { - - for (int i = 0; i < nai.numNetworkRequests(); i++) { - NetworkRequest nr = nai.requestAt(i); - NetworkRequestInfo nri = mNetworkRequests.get(nr); - - final int blockedReasons = mUidBlockedReasons.get(nri.mAsUid, BLOCKED_REASON_NONE); - final boolean oldVpnBlocked = isUidBlockedByVpn(nri.mAsUid, oldBlockedUidRanges); - final boolean newVpnBlocked = (oldBlockedUidRanges != newBlockedUidRanges) - ? isUidBlockedByVpn(nri.mAsUid, newBlockedUidRanges) - : oldVpnBlocked; - - final int oldBlockedState = getBlockedState(blockedReasons, oldMetered, oldVpnBlocked); - final int newBlockedState = getBlockedState(blockedReasons, newMetered, newVpnBlocked); - if (oldBlockedState != newBlockedState) { - callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_BLK_CHANGED, - newBlockedState); - } - } - } - - /** - * Notify apps with a given UID of the new blocked state according to new uid state. - * @param uid The uid for which the rules changed. - * @param blockedReasons The reasons for why an uid is blocked. - */ - private void maybeNotifyNetworkBlockedForNewState(int uid, @BlockedReason int blockedReasons) { - for (final NetworkAgentInfo nai : mNetworkAgentInfos) { - final boolean metered = nai.networkCapabilities.isMetered(); - final boolean vpnBlocked = isUidBlockedByVpn(uid, mVpnBlockedUidRanges); - - final int oldBlockedState = getBlockedState( - mUidBlockedReasons.get(uid, BLOCKED_REASON_NONE), metered, vpnBlocked); - final int newBlockedState = getBlockedState(blockedReasons, metered, vpnBlocked); - if (oldBlockedState == newBlockedState) { - continue; - } - for (int i = 0; i < nai.numNetworkRequests(); i++) { - NetworkRequest nr = nai.requestAt(i); - NetworkRequestInfo nri = mNetworkRequests.get(nr); - if (nri != null && nri.mAsUid == uid) { - callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_BLK_CHANGED, - newBlockedState); - } - } - } - } - - @VisibleForTesting - protected void sendLegacyNetworkBroadcast(NetworkAgentInfo nai, DetailedState state, int type) { - // The NetworkInfo we actually send out has no bearing on the real - // state of affairs. For example, if the default connection is mobile, - // and a request for HIPRI has just gone away, we need to pretend that - // HIPRI has just disconnected. So we need to set the type to HIPRI and - // the state to DISCONNECTED, even though the network is of type MOBILE - // and is still connected. - NetworkInfo info = new NetworkInfo(nai.networkInfo); - info.setType(type); - filterForLegacyLockdown(info); - if (state != DetailedState.DISCONNECTED) { - info.setDetailedState(state, null, info.getExtraInfo()); - sendConnectedBroadcast(info); - } else { - info.setDetailedState(state, info.getReason(), info.getExtraInfo()); - Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION); - intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info); - intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType()); - if (info.isFailover()) { - intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true); - nai.networkInfo.setFailover(false); - } - if (info.getReason() != null) { - intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason()); - } - if (info.getExtraInfo() != null) { - intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, info.getExtraInfo()); - } - NetworkAgentInfo newDefaultAgent = null; - if (nai.isSatisfyingRequest(mDefaultRequest.mRequests.get(0).requestId)) { - newDefaultAgent = mDefaultRequest.getSatisfier(); - if (newDefaultAgent != null) { - intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, - newDefaultAgent.networkInfo); - } else { - intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true); - } - } - intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, - mDefaultInetConditionPublished); - sendStickyBroadcast(intent); - if (newDefaultAgent != null) { - sendConnectedBroadcast(newDefaultAgent.networkInfo); - } - } - } - - protected void notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType, int arg1) { - if (VDBG || DDBG) { - String notification = ConnectivityManager.getCallbackName(notifyType); - log("notifyType " + notification + " for " + networkAgent.toShortString()); - } - for (int i = 0; i < networkAgent.numNetworkRequests(); i++) { - NetworkRequest nr = networkAgent.requestAt(i); - NetworkRequestInfo nri = mNetworkRequests.get(nr); - if (VDBG) log(" sending notification for " + nr); - if (nri.mPendingIntent == null) { - callCallbackForRequest(nri, networkAgent, notifyType, arg1); - } else { - sendPendingIntentForRequest(nri, networkAgent, notifyType); - } - } - } - - protected void notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType) { - notifyNetworkCallbacks(networkAgent, notifyType, 0); - } - - /** - * Returns the list of all interfaces that could be used by network traffic that does not - * explicitly specify a network. This includes the default network, but also all VPNs that are - * currently connected. - * - * Must be called on the handler thread. - */ - @NonNull - private ArrayList getDefaultNetworks() { - ensureRunningOnConnectivityServiceThread(); - final ArrayList defaultNetworks = new ArrayList<>(); - final Set activeNetIds = new ArraySet<>(); - for (final NetworkRequestInfo nri : mDefaultNetworkRequests) { - if (nri.isBeingSatisfied()) { - activeNetIds.add(nri.getSatisfier().network().netId); - } - } - for (NetworkAgentInfo nai : mNetworkAgentInfos) { - if (nai.everConnected && (activeNetIds.contains(nai.network().netId) || nai.isVPN())) { - defaultNetworks.add(nai.network); - } - } - return defaultNetworks; - } - - /** - * Notify NetworkStatsService that the set of active ifaces has changed, or that one of the - * active iface's tracked properties has changed. - */ - private void notifyIfacesChangedForNetworkStats() { - ensureRunningOnConnectivityServiceThread(); - String activeIface = null; - LinkProperties activeLinkProperties = getActiveLinkProperties(); - if (activeLinkProperties != null) { - activeIface = activeLinkProperties.getInterfaceName(); - } - - final UnderlyingNetworkInfo[] underlyingNetworkInfos = getAllVpnInfo(); - try { - final ArrayList snapshots = new ArrayList<>(); - for (final NetworkStateSnapshot snapshot : getAllNetworkStateSnapshots()) { - snapshots.add(snapshot); - } - mStatsManager.notifyNetworkStatus(getDefaultNetworks(), - snapshots, activeIface, Arrays.asList(underlyingNetworkInfos)); - } catch (Exception ignored) { - } - } - - @Override - public String getCaptivePortalServerUrl() { - enforceNetworkStackOrSettingsPermission(); - String settingUrl = mResources.get().getString( - R.string.config_networkCaptivePortalServerUrl); - - if (!TextUtils.isEmpty(settingUrl)) { - return settingUrl; - } - - settingUrl = Settings.Global.getString(mContext.getContentResolver(), - ConnectivitySettingsManager.CAPTIVE_PORTAL_HTTP_URL); - if (!TextUtils.isEmpty(settingUrl)) { - return settingUrl; - } - - return DEFAULT_CAPTIVE_PORTAL_HTTP_URL; - } - - @Override - public void startNattKeepalive(Network network, int intervalSeconds, - ISocketKeepaliveCallback cb, String srcAddr, int srcPort, String dstAddr) { - enforceKeepalivePermission(); - mKeepaliveTracker.startNattKeepalive( - getNetworkAgentInfoForNetwork(network), null /* fd */, - intervalSeconds, cb, - srcAddr, srcPort, dstAddr, NattSocketKeepalive.NATT_PORT); - } - - @Override - public void startNattKeepaliveWithFd(Network network, ParcelFileDescriptor pfd, int resourceId, - int intervalSeconds, ISocketKeepaliveCallback cb, String srcAddr, - String dstAddr) { - try { - final FileDescriptor fd = pfd.getFileDescriptor(); - mKeepaliveTracker.startNattKeepalive( - getNetworkAgentInfoForNetwork(network), fd, resourceId, - intervalSeconds, cb, - srcAddr, dstAddr, NattSocketKeepalive.NATT_PORT); - } finally { - // FileDescriptors coming from AIDL calls must be manually closed to prevent leaks. - // startNattKeepalive calls Os.dup(fd) before returning, so we can close immediately. - if (pfd != null && Binder.getCallingPid() != Process.myPid()) { - IoUtils.closeQuietly(pfd); - } - } - } - - @Override - public void startTcpKeepalive(Network network, ParcelFileDescriptor pfd, int intervalSeconds, - ISocketKeepaliveCallback cb) { - try { - enforceKeepalivePermission(); - final FileDescriptor fd = pfd.getFileDescriptor(); - mKeepaliveTracker.startTcpKeepalive( - getNetworkAgentInfoForNetwork(network), fd, intervalSeconds, cb); - } finally { - // FileDescriptors coming from AIDL calls must be manually closed to prevent leaks. - // startTcpKeepalive calls Os.dup(fd) before returning, so we can close immediately. - if (pfd != null && Binder.getCallingPid() != Process.myPid()) { - IoUtils.closeQuietly(pfd); - } - } - } - - @Override - public void stopKeepalive(Network network, int slot) { - mHandler.sendMessage(mHandler.obtainMessage( - NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE, slot, SocketKeepalive.SUCCESS, network)); - } - - @Override - public void factoryReset() { - enforceSettingsPermission(); - - final int uid = mDeps.getCallingUid(); - final long token = Binder.clearCallingIdentity(); - try { - if (mUserManager.hasUserRestrictionForUser(UserManager.DISALLOW_NETWORK_RESET, - UserHandle.getUserHandleForUid(uid))) { - return; - } - - final IpMemoryStore ipMemoryStore = IpMemoryStore.getMemoryStore(mContext); - ipMemoryStore.factoryReset(); - - // Turn airplane mode off - setAirplaneMode(false); - - // restore private DNS settings to default mode (opportunistic) - if (!mUserManager.hasUserRestrictionForUser(UserManager.DISALLOW_CONFIG_PRIVATE_DNS, - UserHandle.getUserHandleForUid(uid))) { - ConnectivitySettingsManager.setPrivateDnsMode(mContext, - PRIVATE_DNS_MODE_OPPORTUNISTIC); - } - - Settings.Global.putString(mContext.getContentResolver(), - ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, null); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public byte[] getNetworkWatchlistConfigHash() { - NetworkWatchlistManager nwm = mContext.getSystemService(NetworkWatchlistManager.class); - if (nwm == null) { - loge("Unable to get NetworkWatchlistManager"); - return null; - } - // Redirect it to network watchlist service to access watchlist file and calculate hash. - return nwm.getWatchlistConfigHash(); - } - - private void logNetworkEvent(NetworkAgentInfo nai, int evtype) { - int[] transports = nai.networkCapabilities.getTransportTypes(); - mMetricsLog.log(nai.network.getNetId(), transports, new NetworkEvent(evtype)); - } - - private static boolean toBool(int encodedBoolean) { - return encodedBoolean != 0; // Only 0 means false. - } - - private static int encodeBool(boolean b) { - return b ? 1 : 0; - } - - @Override - public int handleShellCommand(@NonNull ParcelFileDescriptor in, - @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err, - @NonNull String[] args) { - return new ShellCmd().exec(this, in.getFileDescriptor(), out.getFileDescriptor(), - err.getFileDescriptor(), args); - } - - private class ShellCmd extends BasicShellCommandHandler { - @Override - public int onCommand(String cmd) { - if (cmd == null) { - return handleDefaultCommands(cmd); - } - final PrintWriter pw = getOutPrintWriter(); - try { - switch (cmd) { - case "airplane-mode": - final String action = getNextArg(); - if ("enable".equals(action)) { - setAirplaneMode(true); - return 0; - } else if ("disable".equals(action)) { - setAirplaneMode(false); - return 0; - } else if (action == null) { - final ContentResolver cr = mContext.getContentResolver(); - final int enabled = Settings.Global.getInt(cr, - Settings.Global.AIRPLANE_MODE_ON); - pw.println(enabled == 0 ? "disabled" : "enabled"); - return 0; - } else { - onHelp(); - return -1; - } - default: - return handleDefaultCommands(cmd); - } - } catch (Exception e) { - pw.println(e); - } - return -1; - } - - @Override - public void onHelp() { - PrintWriter pw = getOutPrintWriter(); - pw.println("Connectivity service commands:"); - pw.println(" help"); - pw.println(" Print this help text."); - pw.println(" airplane-mode [enable|disable]"); - pw.println(" Turn airplane mode on or off."); - pw.println(" airplane-mode"); - pw.println(" Get airplane mode."); - } - } - - private int getVpnType(@Nullable NetworkAgentInfo vpn) { - if (vpn == null) return VpnManager.TYPE_VPN_NONE; - final TransportInfo ti = vpn.networkCapabilities.getTransportInfo(); - if (!(ti instanceof VpnTransportInfo)) return VpnManager.TYPE_VPN_NONE; - return ((VpnTransportInfo) ti).getType(); - } - - /** - * @param connectionInfo the connection to resolve. - * @return {@code uid} if the connection is found and the app has permission to observe it - * (e.g., if it is associated with the calling VPN app's tunnel) or {@code INVALID_UID} if the - * connection is not found. - */ - public int getConnectionOwnerUid(ConnectionInfo connectionInfo) { - if (connectionInfo.protocol != IPPROTO_TCP && connectionInfo.protocol != IPPROTO_UDP) { - throw new IllegalArgumentException("Unsupported protocol " + connectionInfo.protocol); - } - - final int uid = mDeps.getConnectionOwnerUid(connectionInfo.protocol, - connectionInfo.local, connectionInfo.remote); - - if (uid == INVALID_UID) return uid; // Not found. - - // Connection owner UIDs are visible only to the network stack and to the VpnService-based - // VPN, if any, that applies to the UID that owns the connection. - if (checkNetworkStackPermission()) return uid; - - final NetworkAgentInfo vpn = getVpnForUid(uid); - if (vpn == null || getVpnType(vpn) != VpnManager.TYPE_VPN_SERVICE - || vpn.networkCapabilities.getOwnerUid() != mDeps.getCallingUid()) { - return INVALID_UID; - } - - return uid; - } - - /** - * Returns a IBinder to a TestNetworkService. Will be lazily created as needed. - * - *

      The TestNetworkService must be run in the system server due to TUN creation. - */ - @Override - public IBinder startOrGetTestNetworkService() { - synchronized (mTNSLock) { - TestNetworkService.enforceTestNetworkPermissions(mContext); - - if (mTNS == null) { - mTNS = new TestNetworkService(mContext); - } - - return mTNS; - } - } - - /** - * Handler used for managing all Connectivity Diagnostics related functions. - * - * @see android.net.ConnectivityDiagnosticsManager - * - * TODO(b/147816404): Explore moving ConnectivityDiagnosticsHandler to a separate file - */ - @VisibleForTesting - class ConnectivityDiagnosticsHandler extends Handler { - private final String mTag = ConnectivityDiagnosticsHandler.class.getSimpleName(); - - /** - * Used to handle ConnectivityDiagnosticsCallback registration events from {@link - * android.net.ConnectivityDiagnosticsManager}. - * obj = ConnectivityDiagnosticsCallbackInfo with IConnectivityDiagnosticsCallback and - * NetworkRequestInfo to be registered - */ - private static final int EVENT_REGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK = 1; - - /** - * Used to handle ConnectivityDiagnosticsCallback unregister events from {@link - * android.net.ConnectivityDiagnosticsManager}. - * obj = the IConnectivityDiagnosticsCallback to be unregistered - * arg1 = the uid of the caller - */ - private static final int EVENT_UNREGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK = 2; - - /** - * Event for {@link NetworkStateTrackerHandler} to trigger ConnectivityReport callbacks - * after processing {@link #EVENT_NETWORK_TESTED} events. - * obj = {@link ConnectivityReportEvent} representing ConnectivityReport info reported from - * NetworkMonitor. - * data = PersistableBundle of extras passed from NetworkMonitor. - * - *

      See {@link ConnectivityService#EVENT_NETWORK_TESTED}. - */ - private static final int EVENT_NETWORK_TESTED = ConnectivityService.EVENT_NETWORK_TESTED; - - /** - * Event for NetworkMonitor to inform ConnectivityService that a potential data stall has - * been detected on the network. - * obj = Long the timestamp (in millis) for when the suspected data stall was detected. - * arg1 = {@link DataStallReport#DetectionMethod} indicating the detection method. - * arg2 = NetID. - * data = PersistableBundle of extras passed from NetworkMonitor. - */ - private static final int EVENT_DATA_STALL_SUSPECTED = 4; - - /** - * Event for ConnectivityDiagnosticsHandler to handle network connectivity being reported to - * the platform. This event will invoke {@link - * IConnectivityDiagnosticsCallback#onNetworkConnectivityReported} for permissioned - * callbacks. - * obj = Network that was reported on - * arg1 = boolint for the quality reported - */ - private static final int EVENT_NETWORK_CONNECTIVITY_REPORTED = 5; - - private ConnectivityDiagnosticsHandler(Looper looper) { - super(looper); - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case EVENT_REGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK: { - handleRegisterConnectivityDiagnosticsCallback( - (ConnectivityDiagnosticsCallbackInfo) msg.obj); - break; - } - case EVENT_UNREGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK: { - handleUnregisterConnectivityDiagnosticsCallback( - (IConnectivityDiagnosticsCallback) msg.obj, msg.arg1); - break; - } - case EVENT_NETWORK_TESTED: { - final ConnectivityReportEvent reportEvent = - (ConnectivityReportEvent) msg.obj; - - handleNetworkTestedWithExtras(reportEvent, reportEvent.mExtras); - break; - } - case EVENT_DATA_STALL_SUSPECTED: { - final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2); - final Pair arg = - (Pair) msg.obj; - if (nai == null) break; - - handleDataStallSuspected(nai, arg.first, msg.arg1, arg.second); - break; - } - case EVENT_NETWORK_CONNECTIVITY_REPORTED: { - handleNetworkConnectivityReported((NetworkAgentInfo) msg.obj, toBool(msg.arg1)); - break; - } - default: { - Log.e(mTag, "Unrecognized event in ConnectivityDiagnostics: " + msg.what); - } - } - } - } - - /** Class used for cleaning up IConnectivityDiagnosticsCallback instances after their death. */ - @VisibleForTesting - class ConnectivityDiagnosticsCallbackInfo implements Binder.DeathRecipient { - @NonNull private final IConnectivityDiagnosticsCallback mCb; - @NonNull private final NetworkRequestInfo mRequestInfo; - @NonNull private final String mCallingPackageName; - - @VisibleForTesting - ConnectivityDiagnosticsCallbackInfo( - @NonNull IConnectivityDiagnosticsCallback cb, - @NonNull NetworkRequestInfo nri, - @NonNull String callingPackageName) { - mCb = cb; - mRequestInfo = nri; - mCallingPackageName = callingPackageName; - } - - @Override - public void binderDied() { - log("ConnectivityDiagnosticsCallback IBinder died."); - unregisterConnectivityDiagnosticsCallback(mCb); - } - } - - /** - * Class used for sending information from {@link - * NetworkMonitorCallbacks#notifyNetworkTestedWithExtras} to the handler for processing it. - */ - private static class NetworkTestedResults { - private final int mNetId; - private final int mTestResult; - private final long mTimestampMillis; - @Nullable private final String mRedirectUrl; - - private NetworkTestedResults( - int netId, int testResult, long timestampMillis, @Nullable String redirectUrl) { - mNetId = netId; - mTestResult = testResult; - mTimestampMillis = timestampMillis; - mRedirectUrl = redirectUrl; - } - } - - /** - * Class used for sending information from {@link NetworkStateTrackerHandler} to {@link - * ConnectivityDiagnosticsHandler}. - */ - private static class ConnectivityReportEvent { - private final long mTimestampMillis; - @NonNull private final NetworkAgentInfo mNai; - private final PersistableBundle mExtras; - - private ConnectivityReportEvent(long timestampMillis, @NonNull NetworkAgentInfo nai, - PersistableBundle p) { - mTimestampMillis = timestampMillis; - mNai = nai; - mExtras = p; - } - } - - private void handleRegisterConnectivityDiagnosticsCallback( - @NonNull ConnectivityDiagnosticsCallbackInfo cbInfo) { - ensureRunningOnConnectivityServiceThread(); - - final IConnectivityDiagnosticsCallback cb = cbInfo.mCb; - final IBinder iCb = cb.asBinder(); - final NetworkRequestInfo nri = cbInfo.mRequestInfo; - - // Connectivity Diagnostics are meant to be used with a single network request. It would be - // confusing for these networks to change when an NRI is satisfied in another layer. - if (nri.isMultilayerRequest()) { - throw new IllegalArgumentException("Connectivity Diagnostics do not support multilayer " - + "network requests."); - } - - // This means that the client registered the same callback multiple times. Do - // not override the previous entry, and exit silently. - if (mConnectivityDiagnosticsCallbacks.containsKey(iCb)) { - if (VDBG) log("Diagnostics callback is already registered"); - - // Decrement the reference count for this NetworkRequestInfo. The reference count is - // incremented when the NetworkRequestInfo is created as part of - // enforceRequestCountLimit(). - nri.decrementRequestCount(); - return; - } - - mConnectivityDiagnosticsCallbacks.put(iCb, cbInfo); - - try { - iCb.linkToDeath(cbInfo, 0); - } catch (RemoteException e) { - cbInfo.binderDied(); - return; - } - - // Once registered, provide ConnectivityReports for matching Networks - final List matchingNetworks = new ArrayList<>(); - synchronized (mNetworkForNetId) { - for (int i = 0; i < mNetworkForNetId.size(); i++) { - final NetworkAgentInfo nai = mNetworkForNetId.valueAt(i); - // Connectivity Diagnostics rejects multilayer requests at registration hence get(0) - if (nai.satisfies(nri.mRequests.get(0))) { - matchingNetworks.add(nai); - } - } - } - for (final NetworkAgentInfo nai : matchingNetworks) { - final ConnectivityReport report = nai.getConnectivityReport(); - if (report == null) { - continue; - } - if (!checkConnectivityDiagnosticsPermissions( - nri.mPid, nri.mUid, nai, cbInfo.mCallingPackageName)) { - continue; - } - - try { - cb.onConnectivityReportAvailable(report); - } catch (RemoteException e) { - // Exception while sending the ConnectivityReport. Move on to the next network. - } - } - } - - private void handleUnregisterConnectivityDiagnosticsCallback( - @NonNull IConnectivityDiagnosticsCallback cb, int uid) { - ensureRunningOnConnectivityServiceThread(); - final IBinder iCb = cb.asBinder(); - - final ConnectivityDiagnosticsCallbackInfo cbInfo = - mConnectivityDiagnosticsCallbacks.remove(iCb); - if (cbInfo == null) { - if (VDBG) log("Removing diagnostics callback that is not currently registered"); - return; - } - - final NetworkRequestInfo nri = cbInfo.mRequestInfo; - - // Caller's UID must either be the registrants (if they are unregistering) or the System's - // (if the Binder died) - if (uid != nri.mUid && uid != Process.SYSTEM_UID) { - if (DBG) loge("Uid(" + uid + ") not registrant's (" + nri.mUid + ") or System's"); - return; - } - - // Decrement the reference count for this NetworkRequestInfo. The reference count is - // incremented when the NetworkRequestInfo is created as part of - // enforceRequestCountLimit(). - nri.decrementRequestCount(); - - iCb.unlinkToDeath(cbInfo, 0); - } - - private void handleNetworkTestedWithExtras( - @NonNull ConnectivityReportEvent reportEvent, @NonNull PersistableBundle extras) { - final NetworkAgentInfo nai = reportEvent.mNai; - final NetworkCapabilities networkCapabilities = - getNetworkCapabilitiesWithoutUids(nai.networkCapabilities); - final ConnectivityReport report = - new ConnectivityReport( - reportEvent.mNai.network, - reportEvent.mTimestampMillis, - nai.linkProperties, - networkCapabilities, - extras); - nai.setConnectivityReport(report); - final List results = - getMatchingPermissionedCallbacks(nai); - for (final IConnectivityDiagnosticsCallback cb : results) { - try { - cb.onConnectivityReportAvailable(report); - } catch (RemoteException ex) { - loge("Error invoking onConnectivityReport", ex); - } - } - } - - private void handleDataStallSuspected( - @NonNull NetworkAgentInfo nai, long timestampMillis, int detectionMethod, - @NonNull PersistableBundle extras) { - final NetworkCapabilities networkCapabilities = - getNetworkCapabilitiesWithoutUids(nai.networkCapabilities); - final DataStallReport report = - new DataStallReport( - nai.network, - timestampMillis, - detectionMethod, - nai.linkProperties, - networkCapabilities, - extras); - final List results = - getMatchingPermissionedCallbacks(nai); - for (final IConnectivityDiagnosticsCallback cb : results) { - try { - cb.onDataStallSuspected(report); - } catch (RemoteException ex) { - loge("Error invoking onDataStallSuspected", ex); - } - } - } - - private void handleNetworkConnectivityReported( - @NonNull NetworkAgentInfo nai, boolean connectivity) { - final List results = - getMatchingPermissionedCallbacks(nai); - for (final IConnectivityDiagnosticsCallback cb : results) { - try { - cb.onNetworkConnectivityReported(nai.network, connectivity); - } catch (RemoteException ex) { - loge("Error invoking onNetworkConnectivityReported", ex); - } - } - } - - private NetworkCapabilities getNetworkCapabilitiesWithoutUids(@NonNull NetworkCapabilities nc) { - final NetworkCapabilities sanitized = new NetworkCapabilities(nc, - NetworkCapabilities.REDACT_ALL); - sanitized.setUids(null); - sanitized.setAdministratorUids(new int[0]); - sanitized.setOwnerUid(Process.INVALID_UID); - return sanitized; - } - - private List getMatchingPermissionedCallbacks( - @NonNull NetworkAgentInfo nai) { - final List results = new ArrayList<>(); - for (Entry entry : - mConnectivityDiagnosticsCallbacks.entrySet()) { - final ConnectivityDiagnosticsCallbackInfo cbInfo = entry.getValue(); - final NetworkRequestInfo nri = cbInfo.mRequestInfo; - // Connectivity Diagnostics rejects multilayer requests at registration hence get(0). - if (nai.satisfies(nri.mRequests.get(0))) { - if (checkConnectivityDiagnosticsPermissions( - nri.mPid, nri.mUid, nai, cbInfo.mCallingPackageName)) { - results.add(entry.getValue().mCb); - } - } - } - return results; - } - - private boolean hasLocationPermission(String packageName, int uid) { - // LocationPermissionChecker#checkLocationPermission can throw SecurityException if the uid - // and package name don't match. Throwing on the CS thread is not acceptable, so wrap the - // call in a try-catch. - try { - if (!mLocationPermissionChecker.checkLocationPermission( - packageName, null /* featureId */, uid, null /* message */)) { - return false; - } - } catch (SecurityException e) { - return false; - } - - return true; - } - - private boolean ownsVpnRunningOverNetwork(int uid, Network network) { - for (NetworkAgentInfo virtual : mNetworkAgentInfos) { - if (virtual.supportsUnderlyingNetworks() - && virtual.networkCapabilities.getOwnerUid() == uid - && CollectionUtils.contains(virtual.declaredUnderlyingNetworks, network)) { - return true; - } - } - - return false; - } - - @VisibleForTesting - boolean checkConnectivityDiagnosticsPermissions( - int callbackPid, int callbackUid, NetworkAgentInfo nai, String callbackPackageName) { - if (checkNetworkStackPermission(callbackPid, callbackUid)) { - return true; - } - - // Administrator UIDs also contains the Owner UID - final int[] administratorUids = nai.networkCapabilities.getAdministratorUids(); - if (!CollectionUtils.contains(administratorUids, callbackUid) - && !ownsVpnRunningOverNetwork(callbackUid, nai.network)) { - return false; - } - - return hasLocationPermission(callbackPackageName, callbackUid); - } - - @Override - public void registerConnectivityDiagnosticsCallback( - @NonNull IConnectivityDiagnosticsCallback callback, - @NonNull NetworkRequest request, - @NonNull String callingPackageName) { - if (request.legacyType != TYPE_NONE) { - throw new IllegalArgumentException("ConnectivityManager.TYPE_* are deprecated." - + " Please use NetworkCapabilities instead."); - } - final int callingUid = mDeps.getCallingUid(); - mAppOpsManager.checkPackage(callingUid, callingPackageName); - - // This NetworkCapabilities is only used for matching to Networks. Clear out its owner uid - // and administrator uids to be safe. - final NetworkCapabilities nc = new NetworkCapabilities(request.networkCapabilities); - restrictRequestUidsForCallerAndSetRequestorInfo(nc, callingUid, callingPackageName); - - final NetworkRequest requestWithId = - new NetworkRequest( - nc, TYPE_NONE, nextNetworkRequestId(), NetworkRequest.Type.LISTEN); - - // NetworkRequestInfos created here count towards MAX_NETWORK_REQUESTS_PER_UID limit. - // - // nri is not bound to the death of callback. Instead, callback.bindToDeath() is set in - // handleRegisterConnectivityDiagnosticsCallback(). nri will be cleaned up as part of the - // callback's binder death. - final NetworkRequestInfo nri = new NetworkRequestInfo(callingUid, requestWithId); - final ConnectivityDiagnosticsCallbackInfo cbInfo = - new ConnectivityDiagnosticsCallbackInfo(callback, nri, callingPackageName); - - mConnectivityDiagnosticsHandler.sendMessage( - mConnectivityDiagnosticsHandler.obtainMessage( - ConnectivityDiagnosticsHandler - .EVENT_REGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK, - cbInfo)); - } - - @Override - public void unregisterConnectivityDiagnosticsCallback( - @NonNull IConnectivityDiagnosticsCallback callback) { - Objects.requireNonNull(callback, "callback must be non-null"); - mConnectivityDiagnosticsHandler.sendMessage( - mConnectivityDiagnosticsHandler.obtainMessage( - ConnectivityDiagnosticsHandler - .EVENT_UNREGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK, - mDeps.getCallingUid(), - 0, - callback)); - } - - @Override - public void simulateDataStall(int detectionMethod, long timestampMillis, - @NonNull Network network, @NonNull PersistableBundle extras) { - enforceAnyPermissionOf(android.Manifest.permission.MANAGE_TEST_NETWORKS, - android.Manifest.permission.NETWORK_STACK); - final NetworkCapabilities nc = getNetworkCapabilitiesInternal(network); - if (!nc.hasTransport(TRANSPORT_TEST)) { - throw new SecurityException("Data Stall simluation is only possible for test networks"); - } - - final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network); - if (nai == null || nai.creatorUid != mDeps.getCallingUid()) { - throw new SecurityException("Data Stall simulation is only possible for network " - + "creators"); - } - - // Instead of passing the data stall directly to the ConnectivityDiagnostics handler, treat - // this as a Data Stall received directly from NetworkMonitor. This requires wrapping the - // Data Stall information as a DataStallReportParcelable and passing to - // #notifyDataStallSuspected. This ensures that unknown Data Stall detection methods are - // still passed to ConnectivityDiagnostics (with new detection methods masked). - final DataStallReportParcelable p = new DataStallReportParcelable(); - p.timestampMillis = timestampMillis; - p.detectionMethod = detectionMethod; - - if (hasDataStallDetectionMethod(p, DETECTION_METHOD_DNS_EVENTS)) { - p.dnsConsecutiveTimeouts = extras.getInt(KEY_DNS_CONSECUTIVE_TIMEOUTS); - } - if (hasDataStallDetectionMethod(p, DETECTION_METHOD_TCP_METRICS)) { - p.tcpPacketFailRate = extras.getInt(KEY_TCP_PACKET_FAIL_RATE); - p.tcpMetricsCollectionPeriodMillis = extras.getInt( - KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS); - } - - notifyDataStallSuspected(p, network.getNetId()); - } - - private class NetdCallback extends BaseNetdUnsolicitedEventListener { - @Override - public void onInterfaceClassActivityChanged(boolean isActive, int transportType, - long timestampNs, int uid) { - mNetworkActivityTracker.setAndReportNetworkActive(isActive, transportType, timestampNs); - } - - @Override - public void onInterfaceLinkStateChanged(String iface, boolean up) { - for (NetworkAgentInfo nai : mNetworkAgentInfos) { - nai.clatd.interfaceLinkStateChanged(iface, up); - } - } - - @Override - public void onInterfaceRemoved(String iface) { - for (NetworkAgentInfo nai : mNetworkAgentInfos) { - nai.clatd.interfaceRemoved(iface); - } - } - } - - private final LegacyNetworkActivityTracker mNetworkActivityTracker; - - /** - * Class used for updating network activity tracking with netd and notify network activity - * changes. - */ - private static final class LegacyNetworkActivityTracker { - private static final int NO_UID = -1; - private final Context mContext; - private final INetd mNetd; - private final RemoteCallbackList mNetworkActivityListeners = - new RemoteCallbackList<>(); - // Indicate the current system default network activity is active or not. - @GuardedBy("mActiveIdleTimers") - private boolean mNetworkActive; - @GuardedBy("mActiveIdleTimers") - private final ArrayMap mActiveIdleTimers = new ArrayMap(); - private final Handler mHandler; - - private class IdleTimerParams { - public final int timeout; - public final int transportType; - - IdleTimerParams(int timeout, int transport) { - this.timeout = timeout; - this.transportType = transport; - } - } - - LegacyNetworkActivityTracker(@NonNull Context context, @NonNull Handler handler, - @NonNull INetd netd) { - mContext = context; - mNetd = netd; - mHandler = handler; - } - - public void setAndReportNetworkActive(boolean active, int transportType, long tsNanos) { - sendDataActivityBroadcast(transportTypeToLegacyType(transportType), active, tsNanos); - synchronized (mActiveIdleTimers) { - mNetworkActive = active; - // If there are no idle timers, it means that system is not monitoring - // activity, so the system default network for those default network - // unspecified apps is always considered active. - // - // TODO: If the mActiveIdleTimers is empty, netd will actually not send - // any network activity change event. Whenever this event is received, - // the mActiveIdleTimers should be always not empty. The legacy behavior - // is no-op. Remove to refer to mNetworkActive only. - if (mNetworkActive || mActiveIdleTimers.isEmpty()) { - mHandler.sendMessage(mHandler.obtainMessage(EVENT_REPORT_NETWORK_ACTIVITY)); - } - } - } - - // The network activity should only be updated from ConnectivityService handler thread - // when mActiveIdleTimers lock is held. - @GuardedBy("mActiveIdleTimers") - private void reportNetworkActive() { - final int length = mNetworkActivityListeners.beginBroadcast(); - if (DDBG) log("reportNetworkActive, notify " + length + " listeners"); - try { - for (int i = 0; i < length; i++) { - try { - mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive(); - } catch (RemoteException | RuntimeException e) { - loge("Fail to send network activie to listener " + e); - } - } - } finally { - mNetworkActivityListeners.finishBroadcast(); - } - } - - @GuardedBy("mActiveIdleTimers") - public void handleReportNetworkActivity() { - synchronized (mActiveIdleTimers) { - reportNetworkActive(); - } - } - - // This is deprecated and only to support legacy use cases. - private int transportTypeToLegacyType(int type) { - switch (type) { - case NetworkCapabilities.TRANSPORT_CELLULAR: - return TYPE_MOBILE; - case NetworkCapabilities.TRANSPORT_WIFI: - return TYPE_WIFI; - case NetworkCapabilities.TRANSPORT_BLUETOOTH: - return TYPE_BLUETOOTH; - case NetworkCapabilities.TRANSPORT_ETHERNET: - return TYPE_ETHERNET; - default: - loge("Unexpected transport in transportTypeToLegacyType: " + type); - } - return ConnectivityManager.TYPE_NONE; - } - - public void sendDataActivityBroadcast(int deviceType, boolean active, long tsNanos) { - final Intent intent = new Intent(ConnectivityManager.ACTION_DATA_ACTIVITY_CHANGE); - intent.putExtra(ConnectivityManager.EXTRA_DEVICE_TYPE, deviceType); - intent.putExtra(ConnectivityManager.EXTRA_IS_ACTIVE, active); - intent.putExtra(ConnectivityManager.EXTRA_REALTIME_NS, tsNanos); - final long ident = Binder.clearCallingIdentity(); - try { - mContext.sendOrderedBroadcastAsUser(intent, UserHandle.ALL, - RECEIVE_DATA_ACTIVITY_CHANGE, - null /* resultReceiver */, - null /* scheduler */, - 0 /* initialCode */, - null /* initialData */, - null /* initialExtra */); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - /** - * Setup data activity tracking for the given network. - * - * Every {@code setupDataActivityTracking} should be paired with a - * {@link #removeDataActivityTracking} for cleanup. - */ - private void setupDataActivityTracking(NetworkAgentInfo networkAgent) { - final String iface = networkAgent.linkProperties.getInterfaceName(); - - final int timeout; - final int type; - - if (networkAgent.networkCapabilities.hasTransport( - NetworkCapabilities.TRANSPORT_CELLULAR)) { - timeout = Settings.Global.getInt(mContext.getContentResolver(), - ConnectivitySettingsManager.DATA_ACTIVITY_TIMEOUT_MOBILE, - 10); - type = NetworkCapabilities.TRANSPORT_CELLULAR; - } else if (networkAgent.networkCapabilities.hasTransport( - NetworkCapabilities.TRANSPORT_WIFI)) { - timeout = Settings.Global.getInt(mContext.getContentResolver(), - ConnectivitySettingsManager.DATA_ACTIVITY_TIMEOUT_WIFI, - 15); - type = NetworkCapabilities.TRANSPORT_WIFI; - } else { - return; // do not track any other networks - } - - updateRadioPowerState(true /* isActive */, type); - - if (timeout > 0 && iface != null) { - try { - synchronized (mActiveIdleTimers) { - // Networks start up. - mNetworkActive = true; - mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, type)); - mNetd.idletimerAddInterface(iface, timeout, Integer.toString(type)); - reportNetworkActive(); - } - } catch (Exception e) { - // You shall not crash! - loge("Exception in setupDataActivityTracking " + e); - } - } - } - - /** - * Remove data activity tracking when network disconnects. - */ - private void removeDataActivityTracking(NetworkAgentInfo networkAgent) { - final String iface = networkAgent.linkProperties.getInterfaceName(); - final NetworkCapabilities caps = networkAgent.networkCapabilities; - - if (iface == null) return; - - final int type; - if (caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { - type = NetworkCapabilities.TRANSPORT_CELLULAR; - } else if (caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { - type = NetworkCapabilities.TRANSPORT_WIFI; - } else { - return; // do not track any other networks - } - - try { - updateRadioPowerState(false /* isActive */, type); - synchronized (mActiveIdleTimers) { - final IdleTimerParams params = mActiveIdleTimers.remove(iface); - // The call fails silently if no idle timer setup for this interface - mNetd.idletimerRemoveInterface(iface, params.timeout, - Integer.toString(params.transportType)); - } - } catch (Exception e) { - // You shall not crash! - loge("Exception in removeDataActivityTracking " + e); - } - } - - /** - * Update data activity tracking when network state is updated. - */ - public void updateDataActivityTracking(NetworkAgentInfo newNetwork, - NetworkAgentInfo oldNetwork) { - if (newNetwork != null) { - setupDataActivityTracking(newNetwork); - } - if (oldNetwork != null) { - removeDataActivityTracking(oldNetwork); - } - } - - private void updateRadioPowerState(boolean isActive, int transportType) { - final BatteryStatsManager bs = mContext.getSystemService(BatteryStatsManager.class); - switch (transportType) { - case NetworkCapabilities.TRANSPORT_CELLULAR: - bs.reportMobileRadioPowerState(isActive, NO_UID); - break; - case NetworkCapabilities.TRANSPORT_WIFI: - bs.reportWifiRadioPowerState(isActive, NO_UID); - break; - default: - logw("Untracked transport type:" + transportType); - } - } - - public boolean isDefaultNetworkActive() { - synchronized (mActiveIdleTimers) { - // If there are no idle timers, it means that system is not monitoring activity, - // so the default network is always considered active. - // - // TODO : Distinguish between the cases where mActiveIdleTimers is empty because - // tracking is disabled (negative idle timer value configured), or no active default - // network. In the latter case, this reports active but it should report inactive. - return mNetworkActive || mActiveIdleTimers.isEmpty(); - } - } - - public void registerNetworkActivityListener(@NonNull INetworkActivityListener l) { - mNetworkActivityListeners.register(l); - } - - public void unregisterNetworkActivityListener(@NonNull INetworkActivityListener l) { - mNetworkActivityListeners.unregister(l); - } - - public void dump(IndentingPrintWriter pw) { - synchronized (mActiveIdleTimers) { - pw.print("mNetworkActive="); pw.println(mNetworkActive); - pw.println("Idle timers:"); - for (HashMap.Entry ent : mActiveIdleTimers.entrySet()) { - pw.print(" "); pw.print(ent.getKey()); pw.println(":"); - final IdleTimerParams params = ent.getValue(); - pw.print(" timeout="); pw.print(params.timeout); - pw.print(" type="); pw.println(params.transportType); - } - } - } - } - - /** - * Registers {@link QosSocketFilter} with {@link IQosCallback}. - * - * @param socketInfo the socket information - * @param callback the callback to register - */ - @Override - public void registerQosSocketCallback(@NonNull final QosSocketInfo socketInfo, - @NonNull final IQosCallback callback) { - final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(socketInfo.getNetwork()); - if (nai == null || nai.networkCapabilities == null) { - try { - callback.onError(QosCallbackException.EX_TYPE_FILTER_NETWORK_RELEASED); - } catch (final RemoteException ex) { - loge("registerQosCallbackInternal: RemoteException", ex); - } - return; - } - registerQosCallbackInternal(new QosSocketFilter(socketInfo), callback, nai); - } - - /** - * Register a {@link IQosCallback} with base {@link QosFilter}. - * - * @param filter the filter to register - * @param callback the callback to register - * @param nai the agent information related to the filter's network - */ - @VisibleForTesting - public void registerQosCallbackInternal(@NonNull final QosFilter filter, - @NonNull final IQosCallback callback, @NonNull final NetworkAgentInfo nai) { - if (filter == null) throw new IllegalArgumentException("filter must be non-null"); - if (callback == null) throw new IllegalArgumentException("callback must be non-null"); - - if (!nai.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) { - enforceConnectivityRestrictedNetworksPermission(); - } - mQosCallbackTracker.registerCallback(callback, filter, nai); - } - - /** - * Unregisters the given callback. - * - * @param callback the callback to unregister - */ - @Override - public void unregisterQosCallback(@NonNull final IQosCallback callback) { - Objects.requireNonNull(callback, "callback must be non-null"); - mQosCallbackTracker.unregisterCallback(callback); - } - - // Network preference per-profile and OEM network preferences can't be set at the same - // time, because it is unclear what should happen if both preferences are active for - // one given UID. To make it possible, the stack would have to clarify what would happen - // in case both are active at the same time. The implementation may have to be adjusted - // to implement the resulting rules. For example, a priority could be defined between them, - // where the OEM preference would be considered less or more important than the enterprise - // preference ; this would entail implementing the priorities somehow, e.g. by doing - // UID arithmetic with UID ranges or passing a priority to netd so that the routing rules - // are set at the right level. Other solutions are possible, e.g. merging of the - // preferences for the relevant UIDs. - private static void throwConcurrentPreferenceException() { - throw new IllegalStateException("Can't set NetworkPreferenceForUser and " - + "set OemNetworkPreference at the same time"); - } - - /** - * Request that a user profile is put by default on a network matching a given preference. - * - * See the documentation for the individual preferences for a description of the supported - * behaviors. - * - * @param profile the profile concerned. - * @param preference the preference for this profile, as one of the PROFILE_NETWORK_PREFERENCE_* - * constants. - * @param listener an optional listener to listen for completion of the operation. - */ - @Override - public void setProfileNetworkPreference(@NonNull final UserHandle profile, - @ConnectivityManager.ProfileNetworkPreference final int preference, - @Nullable final IOnCompleteListener listener) { - Objects.requireNonNull(profile); - PermissionUtils.enforceNetworkStackPermission(mContext); - if (DBG) { - log("setProfileNetworkPreference " + profile + " to " + preference); - } - if (profile.getIdentifier() < 0) { - throw new IllegalArgumentException("Must explicitly specify a user handle (" - + "UserHandle.CURRENT not supported)"); - } - final UserManager um = mContext.getSystemService(UserManager.class); - if (!um.isManagedProfile(profile.getIdentifier())) { - throw new IllegalArgumentException("Profile must be a managed profile"); - } - // Strictly speaking, mOemNetworkPreferences should only be touched on the - // handler thread. However it is an immutable object, so reading the reference is - // safe - it's just possible the value is slightly outdated. For the final check, - // see #handleSetProfileNetworkPreference. But if this can be caught here it is a - // lot easier to understand, so opportunistically check it. - if (!mOemNetworkPreferences.isEmpty()) { - throwConcurrentPreferenceException(); - } - final NetworkCapabilities nc; - switch (preference) { - case ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT: - nc = null; - break; - case ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE: - final UidRange uids = UidRange.createForUser(profile); - nc = createDefaultNetworkCapabilitiesForUidRange(uids); - nc.addCapability(NET_CAPABILITY_ENTERPRISE); - nc.removeCapability(NET_CAPABILITY_NOT_RESTRICTED); - break; - default: - throw new IllegalArgumentException( - "Invalid preference in setProfileNetworkPreference"); - } - mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_PROFILE_NETWORK_PREFERENCE, - new Pair<>(new ProfileNetworkPreferences.Preference(profile, nc), listener))); - } - - private void validateNetworkCapabilitiesOfProfileNetworkPreference( - @Nullable final NetworkCapabilities nc) { - if (null == nc) return; // Null caps are always allowed. It means to remove the setting. - ensureRequestableCapabilities(nc); - } - - private ArraySet createNrisFromProfileNetworkPreferences( - @NonNull final ProfileNetworkPreferences prefs) { - final ArraySet result = new ArraySet<>(); - for (final ProfileNetworkPreferences.Preference pref : prefs.preferences) { - // The NRI for a user should be comprised of two layers: - // - The request for the capabilities - // - The request for the default network, for fallback. Create an image of it to - // have the correct UIDs in it (also a request can only be part of one NRI, because - // of lookups in 1:1 associations like mNetworkRequests). - // Note that denying a fallback can be implemented simply by not adding the second - // request. - final ArrayList nrs = new ArrayList<>(); - nrs.add(createNetworkRequest(NetworkRequest.Type.REQUEST, pref.capabilities)); - nrs.add(createDefaultInternetRequestForTransport( - TYPE_NONE, NetworkRequest.Type.TRACK_DEFAULT)); - setNetworkRequestUids(nrs, UidRange.fromIntRanges(pref.capabilities.getUids())); - final NetworkRequestInfo nri = new NetworkRequestInfo(Process.myUid(), nrs); - result.add(nri); - } - return result; - } - - private void handleSetProfileNetworkPreference( - @NonNull final ProfileNetworkPreferences.Preference preference, - @Nullable final IOnCompleteListener listener) { - // setProfileNetworkPreference and setOemNetworkPreference are mutually exclusive, in - // particular because it's not clear what preference should win in case both apply - // to the same app. - // The binder call has already checked this, but as mOemNetworkPreferences is only - // touched on the handler thread, it's theoretically not impossible that it has changed - // since. - if (!mOemNetworkPreferences.isEmpty()) { - // This may happen on a device with an OEM preference set when a user is removed. - // In this case, it's safe to ignore. In particular this happens in the tests. - loge("handleSetProfileNetworkPreference, but OEM network preferences not empty"); - return; - } - - validateNetworkCapabilitiesOfProfileNetworkPreference(preference.capabilities); - - mProfileNetworkPreferences = mProfileNetworkPreferences.plus(preference); - mSystemNetworkRequestCounter.transact( - mDeps.getCallingUid(), mProfileNetworkPreferences.preferences.size(), - () -> { - final ArraySet nris = - createNrisFromProfileNetworkPreferences(mProfileNetworkPreferences); - replaceDefaultNetworkRequestsForPreference(nris); - }); - // Finally, rematch. - rematchAllNetworksAndRequests(); - - if (null != listener) { - try { - listener.onComplete(); - } catch (RemoteException e) { - loge("Listener for setProfileNetworkPreference has died"); - } - } - } - - private void enforceAutomotiveDevice() { - final boolean isAutomotiveDevice = - mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE); - if (!isAutomotiveDevice) { - throw new UnsupportedOperationException( - "setOemNetworkPreference() is only available on automotive devices."); - } - } - - /** - * Used by automotive devices to set the network preferences used to direct traffic at an - * application level as per the given OemNetworkPreferences. An example use-case would be an - * automotive OEM wanting to provide connectivity for applications critical to the usage of a - * vehicle via a particular network. - * - * Calling this will overwrite the existing preference. - * - * @param preference {@link OemNetworkPreferences} The application network preference to be set. - * @param listener {@link ConnectivityManager.OnCompleteListener} Listener used - * to communicate completion of setOemNetworkPreference(); - */ - @Override - public void setOemNetworkPreference( - @NonNull final OemNetworkPreferences preference, - @Nullable final IOnCompleteListener listener) { - - enforceAutomotiveDevice(); - enforceOemNetworkPreferencesPermission(); - - if (!mProfileNetworkPreferences.isEmpty()) { - // Strictly speaking, mProfileNetworkPreferences should only be touched on the - // handler thread. However it is an immutable object, so reading the reference is - // safe - it's just possible the value is slightly outdated. For the final check, - // see #handleSetOemPreference. But if this can be caught here it is a - // lot easier to understand, so opportunistically check it. - throwConcurrentPreferenceException(); - } - - Objects.requireNonNull(preference, "OemNetworkPreferences must be non-null"); - validateOemNetworkPreferences(preference); - mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_OEM_NETWORK_PREFERENCE, - new Pair<>(preference, listener))); - } - - private void validateOemNetworkPreferences(@NonNull OemNetworkPreferences preference) { - for (@OemNetworkPreferences.OemNetworkPreference final int pref - : preference.getNetworkPreferences().values()) { - if (OemNetworkPreferences.OEM_NETWORK_PREFERENCE_UNINITIALIZED == pref) { - final String msg = "OEM_NETWORK_PREFERENCE_UNINITIALIZED is an invalid value."; - throw new IllegalArgumentException(msg); - } - } - } - - private void handleSetOemNetworkPreference( - @NonNull final OemNetworkPreferences preference, - @Nullable final IOnCompleteListener listener) { - Objects.requireNonNull(preference, "OemNetworkPreferences must be non-null"); - if (DBG) { - log("set OEM network preferences :" + preference.toString()); - } - // setProfileNetworkPreference and setOemNetworkPreference are mutually exclusive, in - // particular because it's not clear what preference should win in case both apply - // to the same app. - // The binder call has already checked this, but as mOemNetworkPreferences is only - // touched on the handler thread, it's theoretically not impossible that it has changed - // since. - if (!mProfileNetworkPreferences.isEmpty()) { - logwtf("handleSetOemPreference, but per-profile network preferences not empty"); - return; - } - - mOemNetworkPreferencesLogs.log("UPDATE INITIATED: " + preference); - final int uniquePreferenceCount = new ArraySet<>( - preference.getNetworkPreferences().values()).size(); - mSystemNetworkRequestCounter.transact( - mDeps.getCallingUid(), uniquePreferenceCount, - () -> { - final ArraySet nris = - new OemNetworkRequestFactory() - .createNrisFromOemNetworkPreferences(preference); - replaceDefaultNetworkRequestsForPreference(nris); - }); - mOemNetworkPreferences = preference; - - if (null != listener) { - try { - listener.onComplete(); - } catch (RemoteException e) { - loge("Can't send onComplete in handleSetOemNetworkPreference", e); - } - } - } - - private void replaceDefaultNetworkRequestsForPreference( - @NonNull final Set nris) { - // Pass in a defensive copy as this collection will be updated on remove. - handleRemoveNetworkRequests(new ArraySet<>(mDefaultNetworkRequests)); - addPerAppDefaultNetworkRequests(nris); - } - - private void addPerAppDefaultNetworkRequests(@NonNull final Set nris) { - ensureRunningOnConnectivityServiceThread(); - mDefaultNetworkRequests.addAll(nris); - final ArraySet perAppCallbackRequestsToUpdate = - getPerAppCallbackRequestsToUpdate(); - final ArraySet nrisToRegister = new ArraySet<>(nris); - mSystemNetworkRequestCounter.transact( - mDeps.getCallingUid(), perAppCallbackRequestsToUpdate.size(), - () -> { - nrisToRegister.addAll( - createPerAppCallbackRequestsToRegister(perAppCallbackRequestsToUpdate)); - handleRemoveNetworkRequests(perAppCallbackRequestsToUpdate); - handleRegisterNetworkRequests(nrisToRegister); - }); - } - - /** - * All current requests that are tracking the default network need to be assessed as to whether - * or not the current set of per-application default requests will be changing their default - * network. If so, those requests will need to be updated so that they will send callbacks for - * default network changes at the appropriate time. Additionally, those requests tracking the - * default that were previously updated by this flow will need to be reassessed. - * @return the nris which will need to be updated. - */ - private ArraySet getPerAppCallbackRequestsToUpdate() { - final ArraySet defaultCallbackRequests = new ArraySet<>(); - // Get the distinct nris to check since for multilayer requests, it is possible to have the - // same nri in the map's values for each of its NetworkRequest objects. - final ArraySet nris = new ArraySet<>(mNetworkRequests.values()); - for (final NetworkRequestInfo nri : nris) { - // Include this nri if it is currently being tracked. - if (isPerAppTrackedNri(nri)) { - defaultCallbackRequests.add(nri); - continue; - } - // We only track callbacks for requests tracking the default. - if (NetworkRequest.Type.TRACK_DEFAULT != nri.mRequests.get(0).type) { - continue; - } - // Include this nri if it will be tracked by the new per-app default requests. - final boolean isNriGoingToBeTracked = - getDefaultRequestTrackingUid(nri.mAsUid) != mDefaultRequest; - if (isNriGoingToBeTracked) { - defaultCallbackRequests.add(nri); - } - } - return defaultCallbackRequests; - } - - /** - * Create nris for those network requests that are currently tracking the default network that - * are being controlled by a per-application default. - * @param perAppCallbackRequestsForUpdate the baseline network requests to be used as the - * foundation when creating the nri. Important items include the calling uid's original - * NetworkRequest to be used when mapping callbacks as well as the caller's uid and name. These - * requests are assumed to have already been validated as needing to be updated. - * @return the Set of nris to use when registering network requests. - */ - private ArraySet createPerAppCallbackRequestsToRegister( - @NonNull final ArraySet perAppCallbackRequestsForUpdate) { - final ArraySet callbackRequestsToRegister = new ArraySet<>(); - for (final NetworkRequestInfo callbackRequest : perAppCallbackRequestsForUpdate) { - final NetworkRequestInfo trackingNri = - getDefaultRequestTrackingUid(callbackRequest.mAsUid); - - // If this nri is not being tracked, the change it back to an untracked nri. - if (trackingNri == mDefaultRequest) { - callbackRequestsToRegister.add(new NetworkRequestInfo( - callbackRequest, - Collections.singletonList(callbackRequest.getNetworkRequestForCallback()))); - continue; - } - - final NetworkRequest request = callbackRequest.mRequests.get(0); - callbackRequestsToRegister.add(new NetworkRequestInfo( - callbackRequest, - copyNetworkRequestsForUid( - trackingNri.mRequests, callbackRequest.mAsUid, - callbackRequest.mUid, request.getRequestorPackageName()))); - } - return callbackRequestsToRegister; - } - - private static void setNetworkRequestUids(@NonNull final List requests, - @NonNull final Set uids) { - for (final NetworkRequest req : requests) { - req.networkCapabilities.setUids(UidRange.toIntRanges(uids)); - } - } - - /** - * Class used to generate {@link NetworkRequestInfo} based off of {@link OemNetworkPreferences}. - */ - @VisibleForTesting - final class OemNetworkRequestFactory { - ArraySet createNrisFromOemNetworkPreferences( - @NonNull final OemNetworkPreferences preference) { - final ArraySet nris = new ArraySet<>(); - final SparseArray> uids = - createUidsFromOemNetworkPreferences(preference); - for (int i = 0; i < uids.size(); i++) { - final int key = uids.keyAt(i); - final Set value = uids.valueAt(i); - final NetworkRequestInfo nri = createNriFromOemNetworkPreferences(key, value); - // No need to add an nri without any requests. - if (0 == nri.mRequests.size()) { - continue; - } - nris.add(nri); - } - - return nris; - } - - private SparseArray> createUidsFromOemNetworkPreferences( - @NonNull final OemNetworkPreferences preference) { - final SparseArray> uids = new SparseArray<>(); - final PackageManager pm = mContext.getPackageManager(); - final List users = - mContext.getSystemService(UserManager.class).getUserHandles(true); - if (null == users || users.size() == 0) { - if (VDBG || DDBG) { - log("No users currently available for setting the OEM network preference."); - } - return uids; - } - for (final Map.Entry entry : - preference.getNetworkPreferences().entrySet()) { - @OemNetworkPreferences.OemNetworkPreference final int pref = entry.getValue(); - try { - final int uid = pm.getApplicationInfo(entry.getKey(), 0).uid; - if (!uids.contains(pref)) { - uids.put(pref, new ArraySet<>()); - } - for (final UserHandle ui : users) { - // Add the rules for all users as this policy is device wide. - uids.get(pref).add(ui.getUid(uid)); - } - } catch (PackageManager.NameNotFoundException e) { - // Although this may seem like an error scenario, it is ok that uninstalled - // packages are sent on a network preference as the system will watch for - // package installations associated with this network preference and update - // accordingly. This is done so as to minimize race conditions on app install. - continue; - } - } - return uids; - } - - private NetworkRequestInfo createNriFromOemNetworkPreferences( - @OemNetworkPreferences.OemNetworkPreference final int preference, - @NonNull final Set uids) { - final List requests = new ArrayList<>(); - // Requests will ultimately be evaluated by order of insertion therefore it matters. - switch (preference) { - case OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID: - requests.add(createUnmeteredNetworkRequest()); - requests.add(createOemPaidNetworkRequest()); - requests.add(createDefaultInternetRequestForTransport( - TYPE_NONE, NetworkRequest.Type.TRACK_DEFAULT)); - break; - case OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK: - requests.add(createUnmeteredNetworkRequest()); - requests.add(createOemPaidNetworkRequest()); - break; - case OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY: - requests.add(createOemPaidNetworkRequest()); - break; - case OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY: - requests.add(createOemPrivateNetworkRequest()); - break; - default: - // This should never happen. - throw new IllegalArgumentException("createNriFromOemNetworkPreferences()" - + " called with invalid preference of " + preference); - } - - final ArraySet ranges = new ArraySet(); - for (final int uid : uids) { - ranges.add(new UidRange(uid, uid)); - } - setNetworkRequestUids(requests, ranges); - return new NetworkRequestInfo(Process.myUid(), requests); - } - - private NetworkRequest createUnmeteredNetworkRequest() { - final NetworkCapabilities netcap = createDefaultPerAppNetCap() - .addCapability(NET_CAPABILITY_NOT_METERED) - .addCapability(NET_CAPABILITY_VALIDATED); - return createNetworkRequest(NetworkRequest.Type.LISTEN, netcap); - } - - private NetworkRequest createOemPaidNetworkRequest() { - // NET_CAPABILITY_OEM_PAID is a restricted capability. - final NetworkCapabilities netcap = createDefaultPerAppNetCap() - .addCapability(NET_CAPABILITY_OEM_PAID) - .removeCapability(NET_CAPABILITY_NOT_RESTRICTED); - return createNetworkRequest(NetworkRequest.Type.REQUEST, netcap); - } - - private NetworkRequest createOemPrivateNetworkRequest() { - // NET_CAPABILITY_OEM_PRIVATE is a restricted capability. - final NetworkCapabilities netcap = createDefaultPerAppNetCap() - .addCapability(NET_CAPABILITY_OEM_PRIVATE) - .removeCapability(NET_CAPABILITY_NOT_RESTRICTED); - return createNetworkRequest(NetworkRequest.Type.REQUEST, netcap); - } - - private NetworkCapabilities createDefaultPerAppNetCap() { - final NetworkCapabilities netCap = new NetworkCapabilities(); - netCap.addCapability(NET_CAPABILITY_INTERNET); - netCap.setRequestorUidAndPackageName(Process.myUid(), mContext.getPackageName()); - return netCap; - } - } -} diff --git a/packages/Connectivity/service/src/com/android/server/ConnectivityServiceInitializer.java b/packages/Connectivity/service/src/com/android/server/ConnectivityServiceInitializer.java deleted file mode 100644 index 2465479aadd85..0000000000000 --- a/packages/Connectivity/service/src/com/android/server/ConnectivityServiceInitializer.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server; - -import android.content.Context; -import android.util.Log; - -/** - * Connectivity service initializer for core networking. This is called by system server to create - * a new instance of ConnectivityService. - */ -public final class ConnectivityServiceInitializer extends SystemService { - private static final String TAG = ConnectivityServiceInitializer.class.getSimpleName(); - private final ConnectivityService mConnectivity; - - public ConnectivityServiceInitializer(Context context) { - super(context); - // Load JNI libraries used by ConnectivityService and its dependencies - System.loadLibrary("service-connectivity"); - // TODO: Define formal APIs to get the needed services. - mConnectivity = new ConnectivityService(context); - } - - @Override - public void onStart() { - Log.i(TAG, "Registering " + Context.CONNECTIVITY_SERVICE); - publishBinderService(Context.CONNECTIVITY_SERVICE, mConnectivity, - /* allowIsolated= */ false); - } -} diff --git a/packages/Connectivity/service/src/com/android/server/NetIdManager.java b/packages/Connectivity/service/src/com/android/server/NetIdManager.java deleted file mode 100644 index 61925c80a22bb..0000000000000 --- a/packages/Connectivity/service/src/com/android/server/NetIdManager.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server; - -import android.annotation.NonNull; -import android.net.ConnectivityManager; -import android.util.SparseBooleanArray; - -import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; - -/** - * Class used to reserve and release net IDs. - * - *

      Instances of this class are thread-safe. - */ -public class NetIdManager { - // Sequence number for Networks; keep in sync with system/netd/NetworkController.cpp - public static final int MIN_NET_ID = 100; // some reserved marks - // Top IDs reserved by IpSecService - public static final int MAX_NET_ID = ConnectivityManager.getIpSecNetIdRange().getLower() - 1; - - @GuardedBy("mNetIdInUse") - private final SparseBooleanArray mNetIdInUse = new SparseBooleanArray(); - - @GuardedBy("mNetIdInUse") - private int mLastNetId = MIN_NET_ID - 1; - - private final int mMaxNetId; - - public NetIdManager() { - this(MAX_NET_ID); - } - - @VisibleForTesting - NetIdManager(int maxNetId) { - mMaxNetId = maxNetId; - } - - /** - * Get the first netId that follows the provided lastId and is available. - */ - private int getNextAvailableNetIdLocked( - int lastId, @NonNull SparseBooleanArray netIdInUse) { - int netId = lastId; - for (int i = MIN_NET_ID; i <= mMaxNetId; i++) { - netId = netId < mMaxNetId ? netId + 1 : MIN_NET_ID; - if (!netIdInUse.get(netId)) { - return netId; - } - } - throw new IllegalStateException("No free netIds"); - } - - /** - * Reserve a new ID for a network. - */ - public int reserveNetId() { - synchronized (mNetIdInUse) { - mLastNetId = getNextAvailableNetIdLocked(mLastNetId, mNetIdInUse); - // Make sure NetID unused. http://b/16815182 - mNetIdInUse.put(mLastNetId, true); - return mLastNetId; - } - } - - /** - * Clear a previously reserved ID for a network. - */ - public void releaseNetId(int id) { - synchronized (mNetIdInUse) { - mNetIdInUse.delete(id); - } - } -} diff --git a/packages/Connectivity/service/src/com/android/server/TestNetworkService.java b/packages/Connectivity/service/src/com/android/server/TestNetworkService.java deleted file mode 100644 index 09873f4db045d..0000000000000 --- a/packages/Connectivity/service/src/com/android/server/TestNetworkService.java +++ /dev/null @@ -1,387 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server; - -import static android.net.TestNetworkManager.TEST_TAP_PREFIX; -import static android.net.TestNetworkManager.TEST_TUN_PREFIX; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.INetd; -import android.net.ITestNetworkManager; -import android.net.IpPrefix; -import android.net.LinkAddress; -import android.net.LinkProperties; -import android.net.NetworkAgent; -import android.net.NetworkAgentConfig; -import android.net.NetworkCapabilities; -import android.net.NetworkProvider; -import android.net.RouteInfo; -import android.net.TestNetworkInterface; -import android.net.TestNetworkSpecifier; -import android.os.Binder; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.Looper; -import android.os.ParcelFileDescriptor; -import android.os.RemoteException; -import android.util.SparseArray; - -import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; -import com.android.net.module.util.NetdUtils; -import com.android.net.module.util.NetworkStackConstants; -import com.android.net.module.util.PermissionUtils; - -import java.io.UncheckedIOException; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InterfaceAddress; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.util.ArrayList; -import java.util.Objects; -import java.util.concurrent.atomic.AtomicInteger; - -/** @hide */ -class TestNetworkService extends ITestNetworkManager.Stub { - @NonNull private static final String TEST_NETWORK_LOGTAG = "TestNetworkAgent"; - @NonNull private static final String TEST_NETWORK_PROVIDER_NAME = "TestNetworkProvider"; - @NonNull private static final AtomicInteger sTestTunIndex = new AtomicInteger(); - - @NonNull private final Context mContext; - @NonNull private final INetd mNetd; - - @NonNull private final HandlerThread mHandlerThread; - @NonNull private final Handler mHandler; - - @NonNull private final ConnectivityManager mCm; - @NonNull private final NetworkProvider mNetworkProvider; - - // Native method stubs - private static native int jniCreateTunTap(boolean isTun, @NonNull String iface); - - @VisibleForTesting - protected TestNetworkService(@NonNull Context context) { - mHandlerThread = new HandlerThread("TestNetworkServiceThread"); - mHandlerThread.start(); - mHandler = new Handler(mHandlerThread.getLooper()); - - mContext = Objects.requireNonNull(context, "missing Context"); - mNetd = Objects.requireNonNull( - INetd.Stub.asInterface((IBinder) context.getSystemService(Context.NETD_SERVICE)), - "could not get netd instance"); - mCm = mContext.getSystemService(ConnectivityManager.class); - mNetworkProvider = new NetworkProvider(mContext, mHandler.getLooper(), - TEST_NETWORK_PROVIDER_NAME); - final long token = Binder.clearCallingIdentity(); - try { - mCm.registerNetworkProvider(mNetworkProvider); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - /** - * Create a TUN or TAP interface with the given interface name and link addresses - * - *

      This method will return the FileDescriptor to the interface. Close it to tear down the - * interface. - */ - private TestNetworkInterface createInterface(boolean isTun, LinkAddress[] linkAddrs) { - enforceTestNetworkPermissions(mContext); - - Objects.requireNonNull(linkAddrs, "missing linkAddrs"); - - String ifacePrefix = isTun ? TEST_TUN_PREFIX : TEST_TAP_PREFIX; - String iface = ifacePrefix + sTestTunIndex.getAndIncrement(); - final long token = Binder.clearCallingIdentity(); - try { - ParcelFileDescriptor tunIntf = - ParcelFileDescriptor.adoptFd(jniCreateTunTap(isTun, iface)); - for (LinkAddress addr : linkAddrs) { - mNetd.interfaceAddAddress( - iface, - addr.getAddress().getHostAddress(), - addr.getPrefixLength()); - } - - return new TestNetworkInterface(tunIntf, iface); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - /** - * Create a TUN interface with the given interface name and link addresses - * - *

      This method will return the FileDescriptor to the TUN interface. Close it to tear down the - * TUN interface. - */ - @Override - public TestNetworkInterface createTunInterface(@NonNull LinkAddress[] linkAddrs) { - return createInterface(true, linkAddrs); - } - - /** - * Create a TAP interface with the given interface name - * - *

      This method will return the FileDescriptor to the TAP interface. Close it to tear down the - * TAP interface. - */ - @Override - public TestNetworkInterface createTapInterface() { - return createInterface(false, new LinkAddress[0]); - } - - // Tracker for TestNetworkAgents - @GuardedBy("mTestNetworkTracker") - @NonNull - private final SparseArray mTestNetworkTracker = new SparseArray<>(); - - public class TestNetworkAgent extends NetworkAgent implements IBinder.DeathRecipient { - private static final int NETWORK_SCORE = 1; // Use a low, non-zero score. - - private final int mUid; - - @GuardedBy("mBinderLock") - @NonNull - private IBinder mBinder; - - @NonNull private final Object mBinderLock = new Object(); - - private TestNetworkAgent( - @NonNull Context context, - @NonNull Looper looper, - @NonNull NetworkCapabilities nc, - @NonNull LinkProperties lp, - @NonNull NetworkAgentConfig config, - int uid, - @NonNull IBinder binder, - @NonNull NetworkProvider np) - throws RemoteException { - super(context, looper, TEST_NETWORK_LOGTAG, nc, lp, NETWORK_SCORE, config, np); - mUid = uid; - synchronized (mBinderLock) { - mBinder = binder; // Binder null-checks in create() - - try { - mBinder.linkToDeath(this, 0); - } catch (RemoteException e) { - binderDied(); - throw e; // Abort, signal failure up the stack. - } - } - } - - /** - * If the Binder object dies, this function is called to free the resources of this - * TestNetworkAgent - */ - @Override - public void binderDied() { - teardown(); - } - - @Override - protected void unwanted() { - teardown(); - } - - private void teardown() { - unregister(); - - // Synchronize on mBinderLock to ensure that unlinkToDeath is never called more than - // once (otherwise it could throw an exception) - synchronized (mBinderLock) { - // If mBinder is null, this Test Network has already been cleaned up. - if (mBinder == null) return; - mBinder.unlinkToDeath(this, 0); - mBinder = null; - } - - // Has to be in TestNetworkAgent to ensure all teardown codepaths properly clean up - // resources, even for binder death or unwanted calls. - synchronized (mTestNetworkTracker) { - mTestNetworkTracker.remove(getNetwork().getNetId()); - } - } - } - - private TestNetworkAgent registerTestNetworkAgent( - @NonNull Looper looper, - @NonNull Context context, - @NonNull String iface, - @Nullable LinkProperties lp, - boolean isMetered, - int callingUid, - @NonNull int[] administratorUids, - @NonNull IBinder binder) - throws RemoteException, SocketException { - Objects.requireNonNull(looper, "missing Looper"); - Objects.requireNonNull(context, "missing Context"); - // iface and binder validity checked by caller - - // Build narrow set of NetworkCapabilities, useful only for testing - NetworkCapabilities nc = new NetworkCapabilities(); - nc.clearAll(); // Remove default capabilities. - nc.addTransportType(NetworkCapabilities.TRANSPORT_TEST); - nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED); - nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); - nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); - nc.setNetworkSpecifier(new TestNetworkSpecifier(iface)); - nc.setAdministratorUids(administratorUids); - if (!isMetered) { - nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); - } - - // Build LinkProperties - if (lp == null) { - lp = new LinkProperties(); - } else { - lp = new LinkProperties(lp); - // Use LinkAddress(es) from the interface itself to minimize how much the caller - // is trusted. - lp.setLinkAddresses(new ArrayList<>()); - } - lp.setInterfaceName(iface); - - // Find the currently assigned addresses, and add them to LinkProperties - boolean allowIPv4 = false, allowIPv6 = false; - NetworkInterface netIntf = NetworkInterface.getByName(iface); - Objects.requireNonNull(netIntf, "No such network interface found: " + netIntf); - - for (InterfaceAddress intfAddr : netIntf.getInterfaceAddresses()) { - lp.addLinkAddress( - new LinkAddress(intfAddr.getAddress(), intfAddr.getNetworkPrefixLength())); - - if (intfAddr.getAddress() instanceof Inet6Address) { - allowIPv6 |= !intfAddr.getAddress().isLinkLocalAddress(); - } else if (intfAddr.getAddress() instanceof Inet4Address) { - allowIPv4 = true; - } - } - - // Add global routes (but as non-default, non-internet providing network) - if (allowIPv4) { - lp.addRoute(new RouteInfo(new IpPrefix( - NetworkStackConstants.IPV4_ADDR_ANY, 0), null, iface)); - } - if (allowIPv6) { - lp.addRoute(new RouteInfo(new IpPrefix( - NetworkStackConstants.IPV6_ADDR_ANY, 0), null, iface)); - } - - final TestNetworkAgent agent = new TestNetworkAgent(context, looper, nc, lp, - new NetworkAgentConfig.Builder().build(), callingUid, binder, - mNetworkProvider); - agent.register(); - agent.markConnected(); - return agent; - } - - /** - * Sets up a Network with extremely limited privileges, guarded by the MANAGE_TEST_NETWORKS - * permission. - * - *

      This method provides a Network that is useful only for testing. - */ - @Override - public void setupTestNetwork( - @NonNull String iface, - @Nullable LinkProperties lp, - boolean isMetered, - @NonNull int[] administratorUids, - @NonNull IBinder binder) { - enforceTestNetworkPermissions(mContext); - - Objects.requireNonNull(iface, "missing Iface"); - Objects.requireNonNull(binder, "missing IBinder"); - - if (!(iface.startsWith(INetd.IPSEC_INTERFACE_PREFIX) - || iface.startsWith(TEST_TUN_PREFIX))) { - throw new IllegalArgumentException( - "Cannot create network for non ipsec, non-testtun interface"); - } - - try { - final long token = Binder.clearCallingIdentity(); - try { - PermissionUtils.enforceNetworkStackPermission(mContext); - NetdUtils.setInterfaceUp(mNetd, iface); - } finally { - Binder.restoreCallingIdentity(token); - } - - // Synchronize all accesses to mTestNetworkTracker to prevent the case where: - // 1. TestNetworkAgent successfully binds to death of binder - // 2. Before it is added to the mTestNetworkTracker, binder dies, binderDied() is called - // (on a different thread) - // 3. This thread is pre-empted, put() is called after remove() - synchronized (mTestNetworkTracker) { - TestNetworkAgent agent = - registerTestNetworkAgent( - mHandler.getLooper(), - mContext, - iface, - lp, - isMetered, - Binder.getCallingUid(), - administratorUids, - binder); - - mTestNetworkTracker.put(agent.getNetwork().getNetId(), agent); - } - } catch (SocketException e) { - throw new UncheckedIOException(e); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** Teardown a test network */ - @Override - public void teardownTestNetwork(int netId) { - enforceTestNetworkPermissions(mContext); - - final TestNetworkAgent agent; - synchronized (mTestNetworkTracker) { - agent = mTestNetworkTracker.get(netId); - } - - if (agent == null) { - return; // Already torn down - } else if (agent.mUid != Binder.getCallingUid()) { - throw new SecurityException("Attempted to modify other user's test networks"); - } - - // Safe to be called multiple times. - agent.teardown(); - } - - private static final String PERMISSION_NAME = - android.Manifest.permission.MANAGE_TEST_NETWORKS; - - public static void enforceTestNetworkPermissions(@NonNull Context context) { - context.enforceCallingOrSelfPermission(PERMISSION_NAME, "TestNetworkService"); - } -} diff --git a/packages/Connectivity/service/src/com/android/server/connectivity/AutodestructReference.java b/packages/Connectivity/service/src/com/android/server/connectivity/AutodestructReference.java deleted file mode 100644 index 009a43e582850..0000000000000 --- a/packages/Connectivity/service/src/com/android/server/connectivity/AutodestructReference.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import android.annotation.NonNull; - -import java.util.concurrent.atomic.AtomicReference; - -/** - * A ref that autodestructs at the first usage of it. - * @param The type of the held object - * @hide - */ -public class AutodestructReference { - private final AtomicReference mHeld; - public AutodestructReference(@NonNull T obj) { - if (null == obj) throw new NullPointerException("Autodestruct reference to null"); - mHeld = new AtomicReference<>(obj); - } - - /** Get the ref and destruct it. NPE if already destructed. */ - @NonNull - public T getAndDestroy() { - final T obj = mHeld.getAndSet(null); - if (null == obj) throw new NullPointerException("Already autodestructed"); - return obj; - } -} diff --git a/packages/Connectivity/service/src/com/android/server/connectivity/DnsManager.java b/packages/Connectivity/service/src/com/android/server/connectivity/DnsManager.java deleted file mode 100644 index 05b12bad55891..0000000000000 --- a/packages/Connectivity/service/src/com/android/server/connectivity/DnsManager.java +++ /dev/null @@ -1,494 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import static android.net.ConnectivitySettingsManager.DNS_RESOLVER_MAX_SAMPLES; -import static android.net.ConnectivitySettingsManager.DNS_RESOLVER_MIN_SAMPLES; -import static android.net.ConnectivitySettingsManager.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS; -import static android.net.ConnectivitySettingsManager.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT; -import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_DEFAULT_MODE; -import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE; -import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OFF; -import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME; -import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_SPECIFIER; -import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_FAILURE; -import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_SUCCESS; - -import android.annotation.NonNull; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.net.ConnectivityManager; -import android.net.ConnectivitySettingsManager; -import android.net.IDnsResolver; -import android.net.InetAddresses; -import android.net.LinkProperties; -import android.net.Network; -import android.net.ResolverOptionsParcel; -import android.net.ResolverParamsParcel; -import android.net.Uri; -import android.net.shared.PrivateDnsConfig; -import android.os.Binder; -import android.os.RemoteException; -import android.os.ServiceSpecificException; -import android.os.UserHandle; -import android.provider.Settings; -import android.text.TextUtils; -import android.util.Log; -import android.util.Pair; - -import java.net.InetAddress; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; - -/** - * Encapsulate the management of DNS settings for networks. - * - * This class it NOT designed for concurrent access. Furthermore, all non-static - * methods MUST be called from ConnectivityService's thread. However, an exceptional - * case is getPrivateDnsConfig(Network) which is exclusively for - * ConnectivityService#dumpNetworkDiagnostics() on a random binder thread. - * - * [ Private DNS ] - * The code handling Private DNS is spread across several components, but this - * seems like the least bad place to collect all the observations. - * - * Private DNS handling and updating occurs in response to several different - * events. Each is described here with its corresponding intended handling. - * - * [A] Event: A new network comes up. - * Mechanics: - * [1] ConnectivityService gets notifications from NetworkAgents. - * [2] in updateNetworkInfo(), the first time the NetworkAgent goes into - * into CONNECTED state, the Private DNS configuration is retrieved, - * programmed, and strict mode hostname resolution (if applicable) is - * enqueued in NetworkAgent's NetworkMonitor, via a call to - * handlePerNetworkPrivateDnsConfig(). - * [3] Re-resolution of strict mode hostnames that fail to return any - * IP addresses happens inside NetworkMonitor; it sends itself a - * delayed CMD_EVALUATE_PRIVATE_DNS message in a simple backoff - * schedule. - * [4] Successfully resolved hostnames are sent to ConnectivityService - * inside an EVENT_PRIVATE_DNS_CONFIG_RESOLVED message. The resolved - * IP addresses are programmed into netd via: - * - * updatePrivateDns() -> updateDnses() - * - * both of which make calls into DnsManager. - * [5] Upon a successful hostname resolution NetworkMonitor initiates a - * validation attempt in the form of a lookup for a one-time hostname - * that uses Private DNS. - * - * [B] Event: Private DNS settings are changed. - * Mechanics: - * [1] ConnectivityService gets notifications from its SettingsObserver. - * [2] handlePrivateDnsSettingsChanged() is called, which calls - * handlePerNetworkPrivateDnsConfig() and the process proceeds - * as if from A.3 above. - * - * [C] Event: An application calls ConnectivityManager#reportBadNetwork(). - * Mechanics: - * [1] NetworkMonitor is notified and initiates a reevaluation, which - * always bypasses Private DNS. - * [2] Once completed, NetworkMonitor checks if strict mode is in operation - * and if so enqueues another evaluation of Private DNS, as if from - * step A.5 above. - * - * @hide - */ -public class DnsManager { - private static final String TAG = DnsManager.class.getSimpleName(); - private static final PrivateDnsConfig PRIVATE_DNS_OFF = new PrivateDnsConfig(); - - /* Defaults for resolver parameters. */ - private static final int DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS = 1800; - private static final int DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT = 25; - private static final int DNS_RESOLVER_DEFAULT_MIN_SAMPLES = 8; - private static final int DNS_RESOLVER_DEFAULT_MAX_SAMPLES = 64; - - /** - * Get PrivateDnsConfig. - */ - public static PrivateDnsConfig getPrivateDnsConfig(Context context) { - final int mode = ConnectivitySettingsManager.getPrivateDnsMode(context); - - final boolean useTls = mode != PRIVATE_DNS_MODE_OFF; - - if (PRIVATE_DNS_MODE_PROVIDER_HOSTNAME == mode) { - final String specifier = getStringSetting(context.getContentResolver(), - PRIVATE_DNS_SPECIFIER); - return new PrivateDnsConfig(specifier, null); - } - - return new PrivateDnsConfig(useTls); - } - - public static Uri[] getPrivateDnsSettingsUris() { - return new Uri[]{ - Settings.Global.getUriFor(PRIVATE_DNS_DEFAULT_MODE), - Settings.Global.getUriFor(PRIVATE_DNS_MODE), - Settings.Global.getUriFor(PRIVATE_DNS_SPECIFIER), - }; - } - - public static class PrivateDnsValidationUpdate { - public final int netId; - public final InetAddress ipAddress; - public final String hostname; - // Refer to IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_*. - public final int validationResult; - - public PrivateDnsValidationUpdate(int netId, InetAddress ipAddress, - String hostname, int validationResult) { - this.netId = netId; - this.ipAddress = ipAddress; - this.hostname = hostname; - this.validationResult = validationResult; - } - } - - private static class PrivateDnsValidationStatuses { - enum ValidationStatus { - IN_PROGRESS, - FAILED, - SUCCEEDED - } - - // Validation statuses of pairs for a single netId - // Caution : not thread-safe. As mentioned in the top file comment, all - // methods of this class must only be called on ConnectivityService's thread. - private Map, ValidationStatus> mValidationMap; - - private PrivateDnsValidationStatuses() { - mValidationMap = new HashMap<>(); - } - - private boolean hasValidatedServer() { - for (ValidationStatus status : mValidationMap.values()) { - if (status == ValidationStatus.SUCCEEDED) { - return true; - } - } - return false; - } - - private void updateTrackedDnses(String[] ipAddresses, String hostname) { - Set> latestDnses = new HashSet<>(); - for (String ipAddress : ipAddresses) { - try { - latestDnses.add(new Pair(hostname, - InetAddresses.parseNumericAddress(ipAddress))); - } catch (IllegalArgumentException e) {} - } - // Remove pairs that should not be tracked. - for (Iterator, ValidationStatus>> it = - mValidationMap.entrySet().iterator(); it.hasNext(); ) { - Map.Entry, ValidationStatus> entry = it.next(); - if (!latestDnses.contains(entry.getKey())) { - it.remove(); - } - } - // Add new pairs that should be tracked. - for (Pair p : latestDnses) { - if (!mValidationMap.containsKey(p)) { - mValidationMap.put(p, ValidationStatus.IN_PROGRESS); - } - } - } - - private void updateStatus(PrivateDnsValidationUpdate update) { - Pair p = new Pair(update.hostname, - update.ipAddress); - if (!mValidationMap.containsKey(p)) { - return; - } - if (update.validationResult == VALIDATION_RESULT_SUCCESS) { - mValidationMap.put(p, ValidationStatus.SUCCEEDED); - } else if (update.validationResult == VALIDATION_RESULT_FAILURE) { - mValidationMap.put(p, ValidationStatus.FAILED); - } else { - Log.e(TAG, "Unknown private dns validation operation=" - + update.validationResult); - } - } - - private LinkProperties fillInValidatedPrivateDns(LinkProperties lp) { - lp.setValidatedPrivateDnsServers(Collections.EMPTY_LIST); - mValidationMap.forEach((key, value) -> { - if (value == ValidationStatus.SUCCEEDED) { - lp.addValidatedPrivateDnsServer(key.second); - } - }); - return lp; - } - } - - private final Context mContext; - private final ContentResolver mContentResolver; - private final IDnsResolver mDnsResolver; - private final ConcurrentHashMap mPrivateDnsMap; - // TODO: Replace the Map with SparseArrays. - private final Map mPrivateDnsValidationMap; - private final Map mLinkPropertiesMap; - private final Map mTransportsMap; - - private int mSampleValidity; - private int mSuccessThreshold; - private int mMinSamples; - private int mMaxSamples; - - public DnsManager(Context ctx, IDnsResolver dnsResolver) { - mContext = ctx; - mContentResolver = mContext.getContentResolver(); - mDnsResolver = dnsResolver; - mPrivateDnsMap = new ConcurrentHashMap<>(); - mPrivateDnsValidationMap = new HashMap<>(); - mLinkPropertiesMap = new HashMap<>(); - mTransportsMap = new HashMap<>(); - - // TODO: Create and register ContentObservers to track every setting - // used herein, posting messages to respond to changes. - } - - public PrivateDnsConfig getPrivateDnsConfig() { - return getPrivateDnsConfig(mContext); - } - - public void removeNetwork(Network network) { - mPrivateDnsMap.remove(network.getNetId()); - mPrivateDnsValidationMap.remove(network.getNetId()); - mTransportsMap.remove(network.getNetId()); - mLinkPropertiesMap.remove(network.getNetId()); - } - - // This is exclusively called by ConnectivityService#dumpNetworkDiagnostics() which - // is not on the ConnectivityService handler thread. - public PrivateDnsConfig getPrivateDnsConfig(@NonNull Network network) { - return mPrivateDnsMap.getOrDefault(network.getNetId(), PRIVATE_DNS_OFF); - } - - public PrivateDnsConfig updatePrivateDns(Network network, PrivateDnsConfig cfg) { - Log.w(TAG, "updatePrivateDns(" + network + ", " + cfg + ")"); - return (cfg != null) - ? mPrivateDnsMap.put(network.getNetId(), cfg) - : mPrivateDnsMap.remove(network.getNetId()); - } - - public void updatePrivateDnsStatus(int netId, LinkProperties lp) { - // Use the PrivateDnsConfig data pushed to this class instance - // from ConnectivityService. - final PrivateDnsConfig privateDnsCfg = mPrivateDnsMap.getOrDefault(netId, - PRIVATE_DNS_OFF); - - final boolean useTls = privateDnsCfg.useTls; - final PrivateDnsValidationStatuses statuses = - useTls ? mPrivateDnsValidationMap.get(netId) : null; - final boolean validated = (null != statuses) && statuses.hasValidatedServer(); - final boolean strictMode = privateDnsCfg.inStrictMode(); - final String tlsHostname = strictMode ? privateDnsCfg.hostname : null; - final boolean usingPrivateDns = strictMode || validated; - - lp.setUsePrivateDns(usingPrivateDns); - lp.setPrivateDnsServerName(tlsHostname); - if (usingPrivateDns && null != statuses) { - statuses.fillInValidatedPrivateDns(lp); - } else { - lp.setValidatedPrivateDnsServers(Collections.EMPTY_LIST); - } - } - - public void updatePrivateDnsValidation(PrivateDnsValidationUpdate update) { - final PrivateDnsValidationStatuses statuses = mPrivateDnsValidationMap.get(update.netId); - if (statuses == null) return; - statuses.updateStatus(update); - } - - /** - * When creating a new network or transport types are changed in a specific network, - * transport types are always saved to a hashMap before update dns config. - * When destroying network, the specific network will be removed from the hashMap. - * The hashMap is always accessed on the same thread. - */ - public void updateTransportsForNetwork(int netId, @NonNull int[] transportTypes) { - mTransportsMap.put(netId, transportTypes); - sendDnsConfigurationForNetwork(netId); - } - - /** - * When {@link LinkProperties} are changed in a specific network, they are - * always saved to a hashMap before update dns config. - * When destroying network, the specific network will be removed from the hashMap. - * The hashMap is always accessed on the same thread. - */ - public void noteDnsServersForNetwork(int netId, @NonNull LinkProperties lp) { - mLinkPropertiesMap.put(netId, lp); - sendDnsConfigurationForNetwork(netId); - } - - /** - * Send dns configuration parameters to resolver for a given network. - */ - public void sendDnsConfigurationForNetwork(int netId) { - final LinkProperties lp = mLinkPropertiesMap.get(netId); - final int[] transportTypes = mTransportsMap.get(netId); - if (lp == null || transportTypes == null) return; - updateParametersSettings(); - final ResolverParamsParcel paramsParcel = new ResolverParamsParcel(); - - // We only use the PrivateDnsConfig data pushed to this class instance - // from ConnectivityService because it works in coordination with - // NetworkMonitor to decide which networks need validation and runs the - // blocking calls to resolve Private DNS strict mode hostnames. - // - // At this time we do not attempt to enable Private DNS on non-Internet - // networks like IMS. - final PrivateDnsConfig privateDnsCfg = mPrivateDnsMap.getOrDefault(netId, - PRIVATE_DNS_OFF); - final boolean useTls = privateDnsCfg.useTls; - final boolean strictMode = privateDnsCfg.inStrictMode(); - - paramsParcel.netId = netId; - paramsParcel.sampleValiditySeconds = mSampleValidity; - paramsParcel.successThreshold = mSuccessThreshold; - paramsParcel.minSamples = mMinSamples; - paramsParcel.maxSamples = mMaxSamples; - paramsParcel.servers = makeStrings(lp.getDnsServers()); - paramsParcel.domains = getDomainStrings(lp.getDomains()); - paramsParcel.tlsName = strictMode ? privateDnsCfg.hostname : ""; - paramsParcel.tlsServers = - strictMode ? makeStrings( - Arrays.stream(privateDnsCfg.ips) - .filter((ip) -> lp.isReachable(ip)) - .collect(Collectors.toList())) - : useTls ? paramsParcel.servers // Opportunistic - : new String[0]; // Off - paramsParcel.resolverOptions = new ResolverOptionsParcel(); - paramsParcel.transportTypes = transportTypes; - // Prepare to track the validation status of the DNS servers in the - // resolver config when private DNS is in opportunistic or strict mode. - if (useTls) { - if (!mPrivateDnsValidationMap.containsKey(netId)) { - mPrivateDnsValidationMap.put(netId, new PrivateDnsValidationStatuses()); - } - mPrivateDnsValidationMap.get(netId).updateTrackedDnses(paramsParcel.tlsServers, - paramsParcel.tlsName); - } else { - mPrivateDnsValidationMap.remove(netId); - } - - Log.d(TAG, String.format("sendDnsConfigurationForNetwork(%d, %s, %s, %d, %d, %d, %d, " - + "%d, %d, %s, %s)", paramsParcel.netId, Arrays.toString(paramsParcel.servers), - Arrays.toString(paramsParcel.domains), paramsParcel.sampleValiditySeconds, - paramsParcel.successThreshold, paramsParcel.minSamples, - paramsParcel.maxSamples, paramsParcel.baseTimeoutMsec, - paramsParcel.retryCount, paramsParcel.tlsName, - Arrays.toString(paramsParcel.tlsServers))); - - try { - mDnsResolver.setResolverConfiguration(paramsParcel); - } catch (RemoteException | ServiceSpecificException e) { - Log.e(TAG, "Error setting DNS configuration: " + e); - return; - } - } - - /** - * Flush DNS caches and events work before boot has completed. - */ - public void flushVmDnsCache() { - /* - * Tell the VMs to toss their DNS caches - */ - final Intent intent = new Intent(ConnectivityManager.ACTION_CLEAR_DNS_CACHE); - intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); - /* - * Connectivity events can happen before boot has completed ... - */ - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - final long ident = Binder.clearCallingIdentity(); - try { - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - private void updateParametersSettings() { - mSampleValidity = getIntSetting( - DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS, - DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS); - if (mSampleValidity < 0 || mSampleValidity > 65535) { - Log.w(TAG, "Invalid sampleValidity=" + mSampleValidity + ", using default=" - + DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS); - mSampleValidity = DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS; - } - - mSuccessThreshold = getIntSetting( - DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT, - DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT); - if (mSuccessThreshold < 0 || mSuccessThreshold > 100) { - Log.w(TAG, "Invalid successThreshold=" + mSuccessThreshold + ", using default=" - + DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT); - mSuccessThreshold = DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT; - } - - mMinSamples = getIntSetting(DNS_RESOLVER_MIN_SAMPLES, DNS_RESOLVER_DEFAULT_MIN_SAMPLES); - mMaxSamples = getIntSetting(DNS_RESOLVER_MAX_SAMPLES, DNS_RESOLVER_DEFAULT_MAX_SAMPLES); - if (mMinSamples < 0 || mMinSamples > mMaxSamples || mMaxSamples > 64) { - Log.w(TAG, "Invalid sample count (min, max)=(" + mMinSamples + ", " + mMaxSamples - + "), using default=(" + DNS_RESOLVER_DEFAULT_MIN_SAMPLES + ", " - + DNS_RESOLVER_DEFAULT_MAX_SAMPLES + ")"); - mMinSamples = DNS_RESOLVER_DEFAULT_MIN_SAMPLES; - mMaxSamples = DNS_RESOLVER_DEFAULT_MAX_SAMPLES; - } - } - - private int getIntSetting(String which, int dflt) { - return Settings.Global.getInt(mContentResolver, which, dflt); - } - - /** - * Create a string array of host addresses from a collection of InetAddresses - * - * @param addrs a Collection of InetAddresses - * @return an array of Strings containing their host addresses - */ - private String[] makeStrings(Collection addrs) { - String[] result = new String[addrs.size()]; - int i = 0; - for (InetAddress addr : addrs) { - result[i++] = addr.getHostAddress(); - } - return result; - } - - private static String getStringSetting(ContentResolver cr, String which) { - return Settings.Global.getString(cr, which); - } - - private static String[] getDomainStrings(String domains) { - return (TextUtils.isEmpty(domains)) ? new String[0] : domains.split(" "); - } -} diff --git a/packages/Connectivity/service/src/com/android/server/connectivity/FullScore.java b/packages/Connectivity/service/src/com/android/server/connectivity/FullScore.java deleted file mode 100644 index fbfa7a18c9d85..0000000000000 --- a/packages/Connectivity/service/src/com/android/server/connectivity/FullScore.java +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; -import static android.net.NetworkCapabilities.TRANSPORT_VPN; -import static android.net.NetworkScore.KEEP_CONNECTED_NONE; -import static android.net.NetworkScore.POLICY_EXITING; -import static android.net.NetworkScore.POLICY_TRANSPORT_PRIMARY; -import static android.net.NetworkScore.POLICY_YIELD_TO_BAD_WIFI; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.net.NetworkAgentConfig; -import android.net.NetworkCapabilities; -import android.net.NetworkScore; -import android.net.NetworkScore.KeepConnectedReason; - -import com.android.internal.annotations.VisibleForTesting; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.StringJoiner; - -/** - * This class represents how desirable a network is. - * - * FullScore is very similar to NetworkScore, but it contains the bits that are managed - * by ConnectivityService. This provides static guarantee that all users must know whether - * they are handling a score that had the CS-managed bits set. - */ -public class FullScore { - // This will be removed soon. Do *NOT* depend on it for any new code that is not part of - // a migration. - private final int mLegacyInt; - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = {"POLICY_"}, value = { - POLICY_IS_VALIDATED, - POLICY_IS_VPN, - POLICY_EVER_USER_SELECTED, - POLICY_ACCEPT_UNVALIDATED, - POLICY_IS_UNMETERED - }) - public @interface Policy { - } - - // Agent-managed policies are in NetworkScore. They start from 1. - // CS-managed policies, counting from 63 downward - // This network is validated. CS-managed because the source of truth is in NetworkCapabilities. - /** @hide */ - public static final int POLICY_IS_VALIDATED = 63; - - // This is a VPN and behaves as one for scoring purposes. - /** @hide */ - public static final int POLICY_IS_VPN = 62; - - // This network has been selected by the user manually from settings or a 3rd party app - // at least once. {@see NetworkAgentConfig#explicitlySelected}. - /** @hide */ - public static final int POLICY_EVER_USER_SELECTED = 61; - - // The user has indicated in UI that this network should be used even if it doesn't - // validate. {@see NetworkAgentConfig#acceptUnvalidated}. - /** @hide */ - public static final int POLICY_ACCEPT_UNVALIDATED = 60; - - // This network is unmetered. {@see NetworkCapabilities.NET_CAPABILITY_NOT_METERED}. - /** @hide */ - public static final int POLICY_IS_UNMETERED = 59; - - // This network is invincible. This is useful for offers until there is an API to listen - // to requests. - /** @hide */ - public static final int POLICY_IS_INVINCIBLE = 58; - - // This network has been validated at least once since it was connected, but not explicitly - // avoided in UI. - // TODO : remove setAvoidUnvalidated and instead disconnect the network when the user - // chooses to move away from this network, and remove this flag. - /** @hide */ - public static final int POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD = 57; - - // To help iterate when printing - @VisibleForTesting - static final int MIN_CS_MANAGED_POLICY = POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD; - @VisibleForTesting - static final int MAX_CS_MANAGED_POLICY = POLICY_IS_VALIDATED; - - // Mask for policies in NetworkScore. This should have all bits managed by NetworkScore set - // and all bits managed by FullScore unset. As bits are handled from 0 up in NetworkScore and - // from 63 down in FullScore, cut at the 32nd bit for simplicity, but change this if some day - // there are more than 32 bits handled on either side. - // YIELD_TO_BAD_WIFI is temporarily handled by ConnectivityService, but the factory is still - // allowed to set it, so that it's possible to transition from handling it in CS to handling - // it in the factory. - private static final long EXTERNAL_POLICIES_MASK = 0x00000000FFFFFFFFL; - - @VisibleForTesting - static @NonNull String policyNameOf(final int policy) { - switch (policy) { - case POLICY_IS_VALIDATED: return "IS_VALIDATED"; - case POLICY_IS_VPN: return "IS_VPN"; - case POLICY_EVER_USER_SELECTED: return "EVER_USER_SELECTED"; - case POLICY_ACCEPT_UNVALIDATED: return "ACCEPT_UNVALIDATED"; - case POLICY_IS_UNMETERED: return "IS_UNMETERED"; - case POLICY_YIELD_TO_BAD_WIFI: return "YIELD_TO_BAD_WIFI"; - case POLICY_TRANSPORT_PRIMARY: return "TRANSPORT_PRIMARY"; - case POLICY_EXITING: return "EXITING"; - case POLICY_IS_INVINCIBLE: return "INVINCIBLE"; - case POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD: return "EVER_VALIDATED"; - } - throw new IllegalArgumentException("Unknown policy : " + policy); - } - - // Bitmask of all the policies applied to this score. - private final long mPolicies; - - private final int mKeepConnectedReason; - - FullScore(final int legacyInt, final long policies, - @KeepConnectedReason final int keepConnectedReason) { - mLegacyInt = legacyInt; - mPolicies = policies; - mKeepConnectedReason = keepConnectedReason; - } - - /** - * Given a score supplied by the NetworkAgent and CS-managed objects, produce a full score. - * - * @param score the score supplied by the agent - * @param caps the NetworkCapabilities of the network - * @param config the NetworkAgentConfig of the network - * @param everValidated whether this network has ever validated - * @param yieldToBadWiFi whether this network yields to a previously validated wifi gone bad - * @return a FullScore that is appropriate to use for ranking. - */ - // TODO : this shouldn't manage bad wifi avoidance – instead this should be done by the - // telephony factory, so that it depends on the carrier. For now this is handled by - // connectivity for backward compatibility. - public static FullScore fromNetworkScore(@NonNull final NetworkScore score, - @NonNull final NetworkCapabilities caps, @NonNull final NetworkAgentConfig config, - final boolean everValidated, final boolean yieldToBadWiFi) { - return withPolicies(score.getLegacyInt(), score.getPolicies(), - score.getKeepConnectedReason(), - caps.hasCapability(NET_CAPABILITY_VALIDATED), - caps.hasTransport(TRANSPORT_VPN), - caps.hasCapability(NET_CAPABILITY_NOT_METERED), - everValidated, - config.explicitlySelected, - config.acceptUnvalidated, - yieldToBadWiFi, - false /* invincible */); // only prospective scores can be invincible - } - - /** - * Given a score supplied by a NetworkProvider, produce a prospective score for an offer. - * - * NetworkOffers have score filters that are compared to the scores of actual networks - * to see if they could possibly beat the current satisfier. Some things the agent can't - * know in advance ; a good example is the validation bit – some networks will validate, - * others won't. For comparison purposes, assume the best, so all possibly beneficial - * networks will be brought up. - * - * @param score the score supplied by the agent for this offer - * @param caps the capabilities supplied by the agent for this offer - * @return a FullScore appropriate for comparing to actual network's scores. - */ - public static FullScore makeProspectiveScore(@NonNull final NetworkScore score, - @NonNull final NetworkCapabilities caps) { - // If the network offers Internet access, it may validate. - final boolean mayValidate = caps.hasCapability(NET_CAPABILITY_INTERNET); - // VPN transports are known in advance. - final boolean vpn = caps.hasTransport(TRANSPORT_VPN); - // Prospective scores are always unmetered, because unmetered networks are stronger - // than metered networks, and it's not known in advance whether the network is metered. - final boolean unmetered = true; - // If the offer may validate, then it should be considered to have validated at some point - final boolean everValidated = mayValidate; - // The network hasn't been chosen by the user (yet, at least). - final boolean everUserSelected = false; - // Don't assume the user will accept unvalidated connectivity. - final boolean acceptUnvalidated = false; - // Don't assume clinging to bad wifi - final boolean yieldToBadWiFi = false; - // A prospective score is invincible if the legacy int in the filter is over the maximum - // score. - final boolean invincible = score.getLegacyInt() > NetworkRanker.LEGACY_INT_MAX; - return withPolicies(score.getLegacyInt(), score.getPolicies(), KEEP_CONNECTED_NONE, - mayValidate, vpn, unmetered, everValidated, everUserSelected, acceptUnvalidated, - yieldToBadWiFi, invincible); - } - - /** - * Return a new score given updated caps and config. - * - * @param caps the NetworkCapabilities of the network - * @param config the NetworkAgentConfig of the network - * @return a score with the policies from the arguments reset - */ - // TODO : this shouldn't manage bad wifi avoidance – instead this should be done by the - // telephony factory, so that it depends on the carrier. For now this is handled by - // connectivity for backward compatibility. - public FullScore mixInScore(@NonNull final NetworkCapabilities caps, - @NonNull final NetworkAgentConfig config, - final boolean everValidated, - final boolean yieldToBadWifi) { - return withPolicies(mLegacyInt, mPolicies, mKeepConnectedReason, - caps.hasCapability(NET_CAPABILITY_VALIDATED), - caps.hasTransport(TRANSPORT_VPN), - caps.hasCapability(NET_CAPABILITY_NOT_METERED), - everValidated, - config.explicitlySelected, - config.acceptUnvalidated, - yieldToBadWifi, - false /* invincible */); // only prospective scores can be invincible - } - - // TODO : this shouldn't manage bad wifi avoidance – instead this should be done by the - // telephony factory, so that it depends on the carrier. For now this is handled by - // connectivity for backward compatibility. - private static FullScore withPolicies(@NonNull final int legacyInt, - final long externalPolicies, - @KeepConnectedReason final int keepConnectedReason, - final boolean isValidated, - final boolean isVpn, - final boolean isUnmetered, - final boolean everValidated, - final boolean everUserSelected, - final boolean acceptUnvalidated, - final boolean yieldToBadWiFi, - final boolean invincible) { - return new FullScore(legacyInt, (externalPolicies & EXTERNAL_POLICIES_MASK) - | (isValidated ? 1L << POLICY_IS_VALIDATED : 0) - | (isVpn ? 1L << POLICY_IS_VPN : 0) - | (isUnmetered ? 1L << POLICY_IS_UNMETERED : 0) - | (everValidated ? 1L << POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD : 0) - | (everUserSelected ? 1L << POLICY_EVER_USER_SELECTED : 0) - | (acceptUnvalidated ? 1L << POLICY_ACCEPT_UNVALIDATED : 0) - | (yieldToBadWiFi ? 1L << POLICY_YIELD_TO_BAD_WIFI : 0) - | (invincible ? 1L << POLICY_IS_INVINCIBLE : 0), - keepConnectedReason); - } - - /** - * Returns this score but validated. - */ - public FullScore asValidated() { - return new FullScore(mLegacyInt, mPolicies | (1L << POLICY_IS_VALIDATED), - mKeepConnectedReason); - } - - /** - * For backward compatibility, get the legacy int. - * This will be removed before S is published. - */ - public int getLegacyInt() { - return getLegacyInt(false /* pretendValidated */); - } - - public int getLegacyIntAsValidated() { - return getLegacyInt(true /* pretendValidated */); - } - - // TODO : remove these two constants - // Penalty applied to scores of Networks that have not been validated. - private static final int UNVALIDATED_SCORE_PENALTY = 40; - - // Score for a network that can be used unvalidated - private static final int ACCEPT_UNVALIDATED_NETWORK_SCORE = 100; - - private int getLegacyInt(boolean pretendValidated) { - // If the user has chosen this network at least once, give it the maximum score when - // checking to pretend it's validated, or if it doesn't need to validate because the - // user said to use it even if it doesn't validate. - // This ensures that networks that have been selected in UI are not torn down before the - // user gets a chance to prefer it when a higher-scoring network (e.g., Ethernet) is - // available. - if (hasPolicy(POLICY_EVER_USER_SELECTED) - && (hasPolicy(POLICY_ACCEPT_UNVALIDATED) || pretendValidated)) { - return ACCEPT_UNVALIDATED_NETWORK_SCORE; - } - - int score = mLegacyInt; - // Except for VPNs, networks are subject to a penalty for not being validated. - // Apply the penalty unless the network is a VPN, or it's validated or pretending to be. - if (!hasPolicy(POLICY_IS_VALIDATED) && !pretendValidated && !hasPolicy(POLICY_IS_VPN)) { - score -= UNVALIDATED_SCORE_PENALTY; - } - if (score < 0) score = 0; - return score; - } - - /** - * @return whether this score has a particular policy. - */ - @VisibleForTesting - public boolean hasPolicy(final int policy) { - return 0 != (mPolicies & (1L << policy)); - } - - /** - * Returns the keep-connected reason, or KEEP_CONNECTED_NONE. - */ - public int getKeepConnectedReason() { - return mKeepConnectedReason; - } - - // Example output : - // Score(50 ; Policies : EVER_USER_SELECTED&IS_VALIDATED) - @Override - public String toString() { - final StringJoiner sj = new StringJoiner( - "&", // delimiter - "Score(" + mLegacyInt + " ; KeepConnected : " + mKeepConnectedReason - + " ; Policies : ", // prefix - ")"); // suffix - for (int i = NetworkScore.MIN_AGENT_MANAGED_POLICY; - i <= NetworkScore.MAX_AGENT_MANAGED_POLICY; ++i) { - if (hasPolicy(i)) sj.add(policyNameOf(i)); - } - for (int i = MIN_CS_MANAGED_POLICY; i <= MAX_CS_MANAGED_POLICY; ++i) { - if (hasPolicy(i)) sj.add(policyNameOf(i)); - } - return sj.toString(); - } -} diff --git a/packages/Connectivity/service/src/com/android/server/connectivity/KeepaliveTracker.java b/packages/Connectivity/service/src/com/android/server/connectivity/KeepaliveTracker.java deleted file mode 100644 index 7d922a4de9a1c..0000000000000 --- a/packages/Connectivity/service/src/com/android/server/connectivity/KeepaliveTracker.java +++ /dev/null @@ -1,761 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static android.net.NattSocketKeepalive.NATT_PORT; -import static android.net.NetworkAgent.CMD_START_SOCKET_KEEPALIVE; -import static android.net.SocketKeepalive.BINDER_DIED; -import static android.net.SocketKeepalive.DATA_RECEIVED; -import static android.net.SocketKeepalive.ERROR_INSUFFICIENT_RESOURCES; -import static android.net.SocketKeepalive.ERROR_INVALID_INTERVAL; -import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS; -import static android.net.SocketKeepalive.ERROR_INVALID_NETWORK; -import static android.net.SocketKeepalive.ERROR_INVALID_SOCKET; -import static android.net.SocketKeepalive.ERROR_NO_SUCH_SLOT; -import static android.net.SocketKeepalive.ERROR_STOP_REASON_UNINITIALIZED; -import static android.net.SocketKeepalive.ERROR_UNSUPPORTED; -import static android.net.SocketKeepalive.MAX_INTERVAL_SEC; -import static android.net.SocketKeepalive.MIN_INTERVAL_SEC; -import static android.net.SocketKeepalive.NO_KEEPALIVE; -import static android.net.SocketKeepalive.SUCCESS; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.net.ConnectivityResources; -import android.net.ISocketKeepaliveCallback; -import android.net.InetAddresses; -import android.net.InvalidPacketException; -import android.net.KeepalivePacketData; -import android.net.NattKeepalivePacketData; -import android.net.NetworkAgent; -import android.net.SocketKeepalive.InvalidSocketException; -import android.net.TcpKeepalivePacketData; -import android.net.util.KeepaliveUtils; -import android.os.Binder; -import android.os.Handler; -import android.os.IBinder; -import android.os.Message; -import android.os.Process; -import android.os.RemoteException; -import android.system.ErrnoException; -import android.system.Os; -import android.util.Log; -import android.util.Pair; - -import com.android.connectivity.resources.R; -import com.android.internal.util.IndentingPrintWriter; -import com.android.net.module.util.HexDump; -import com.android.net.module.util.IpUtils; - -import java.io.FileDescriptor; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; - -/** - * Manages socket keepalive requests. - * - * Provides methods to stop and start keepalive requests, and keeps track of keepalives across all - * networks. This class is tightly coupled to ConnectivityService. It is not thread-safe and its - * handle* methods must be called only from the ConnectivityService handler thread. - */ -public class KeepaliveTracker { - - private static final String TAG = "KeepaliveTracker"; - private static final boolean DBG = false; - - public static final String PERMISSION = android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD; - - /** Keeps track of keepalive requests. */ - private final HashMap > mKeepalives = - new HashMap<> (); - private final Handler mConnectivityServiceHandler; - @NonNull - private final TcpKeepaliveController mTcpController; - @NonNull - private final Context mContext; - - // Supported keepalive count for each transport type, can be configured through - // config_networkSupportedKeepaliveCount. For better error handling, use - // {@link getSupportedKeepalivesForNetworkCapabilities} instead of direct access. - @NonNull - private final int[] mSupportedKeepalives; - - // Reserved privileged keepalive slots per transport. Caller's permission will be enforced if - // the number of remaining keepalive slots is less than or equal to the threshold. - private final int mReservedPrivilegedSlots; - - // Allowed unprivileged keepalive slots per uid. Caller's permission will be enforced if - // the number of remaining keepalive slots is less than or equal to the threshold. - private final int mAllowedUnprivilegedSlotsForUid; - - public KeepaliveTracker(Context context, Handler handler) { - mConnectivityServiceHandler = handler; - mTcpController = new TcpKeepaliveController(handler); - mContext = context; - mSupportedKeepalives = KeepaliveUtils.getSupportedKeepalives(mContext); - - final ConnectivityResources res = new ConnectivityResources(mContext); - mReservedPrivilegedSlots = res.get().getInteger( - R.integer.config_reservedPrivilegedKeepaliveSlots); - mAllowedUnprivilegedSlotsForUid = res.get().getInteger( - R.integer.config_allowedUnprivilegedKeepalivePerUid); - } - - /** - * Tracks information about a socket keepalive. - * - * All information about this keepalive is known at construction time except the slot number, - * which is only returned when the hardware has successfully started the keepalive. - */ - class KeepaliveInfo implements IBinder.DeathRecipient { - // Bookkeeping data. - private final ISocketKeepaliveCallback mCallback; - private final int mUid; - private final int mPid; - private final boolean mPrivileged; - private final NetworkAgentInfo mNai; - private final int mType; - private final FileDescriptor mFd; - - public static final int TYPE_NATT = 1; - public static final int TYPE_TCP = 2; - - // Keepalive slot. A small integer that identifies this keepalive among the ones handled - // by this network. - private int mSlot = NO_KEEPALIVE; - - // Packet data. - private final KeepalivePacketData mPacket; - private final int mInterval; - - // Whether the keepalive is started or not. The initial state is NOT_STARTED. - private static final int NOT_STARTED = 1; - private static final int STARTING = 2; - private static final int STARTED = 3; - private static final int STOPPING = 4; - private int mStartedState = NOT_STARTED; - private int mStopReason = ERROR_STOP_REASON_UNINITIALIZED; - - KeepaliveInfo(@NonNull ISocketKeepaliveCallback callback, - @NonNull NetworkAgentInfo nai, - @NonNull KeepalivePacketData packet, - int interval, - int type, - @Nullable FileDescriptor fd) throws InvalidSocketException { - mCallback = callback; - mPid = Binder.getCallingPid(); - mUid = Binder.getCallingUid(); - mPrivileged = (PERMISSION_GRANTED == mContext.checkPermission(PERMISSION, mPid, mUid)); - - mNai = nai; - mPacket = packet; - mInterval = interval; - mType = type; - - // For SocketKeepalive, a dup of fd is kept in mFd so the source port from which the - // keepalives are sent cannot be reused by another app even if the fd gets closed by - // the user. A null is acceptable here for backward compatibility of PacketKeepalive - // API. - try { - if (fd != null) { - mFd = Os.dup(fd); - } else { - Log.d(TAG, toString() + " calls with null fd"); - if (!mPrivileged) { - throw new SecurityException( - "null fd is not allowed for unprivileged access."); - } - if (mType == TYPE_TCP) { - throw new IllegalArgumentException( - "null fd is not allowed for tcp socket keepalives."); - } - mFd = null; - } - } catch (ErrnoException e) { - Log.e(TAG, "Cannot dup fd: ", e); - throw new InvalidSocketException(ERROR_INVALID_SOCKET, e); - } - - try { - mCallback.asBinder().linkToDeath(this, 0); - } catch (RemoteException e) { - binderDied(); - } - } - - public NetworkAgentInfo getNai() { - return mNai; - } - - private String startedStateString(final int state) { - switch (state) { - case NOT_STARTED : return "NOT_STARTED"; - case STARTING : return "STARTING"; - case STARTED : return "STARTED"; - case STOPPING : return "STOPPING"; - } - throw new IllegalArgumentException("Unknown state"); - } - - public String toString() { - return "KeepaliveInfo [" - + " type=" + mType - + " network=" + mNai.network - + " startedState=" + startedStateString(mStartedState) - + " " - + IpUtils.addressAndPortToString(mPacket.getSrcAddress(), mPacket.getSrcPort()) - + "->" - + IpUtils.addressAndPortToString(mPacket.getDstAddress(), mPacket.getDstPort()) - + " interval=" + mInterval - + " uid=" + mUid + " pid=" + mPid + " privileged=" + mPrivileged - + " packetData=" + HexDump.toHexString(mPacket.getPacket()) - + " ]"; - } - - /** Called when the application process is killed. */ - public void binderDied() { - stop(BINDER_DIED); - } - - void unlinkDeathRecipient() { - if (mCallback != null) { - mCallback.asBinder().unlinkToDeath(this, 0); - } - } - - private int checkNetworkConnected() { - if (!mNai.networkInfo.isConnectedOrConnecting()) { - return ERROR_INVALID_NETWORK; - } - return SUCCESS; - } - - private int checkSourceAddress() { - // Check that we have the source address. - for (InetAddress address : mNai.linkProperties.getAddresses()) { - if (address.equals(mPacket.getSrcAddress())) { - return SUCCESS; - } - } - return ERROR_INVALID_IP_ADDRESS; - } - - private int checkInterval() { - if (mInterval < MIN_INTERVAL_SEC || mInterval > MAX_INTERVAL_SEC) { - return ERROR_INVALID_INTERVAL; - } - return SUCCESS; - } - - private int checkPermission() { - final HashMap networkKeepalives = mKeepalives.get(mNai); - if (networkKeepalives == null) { - return ERROR_INVALID_NETWORK; - } - - if (mPrivileged) return SUCCESS; - - final int supported = KeepaliveUtils.getSupportedKeepalivesForNetworkCapabilities( - mSupportedKeepalives, mNai.networkCapabilities); - - int takenUnprivilegedSlots = 0; - for (final KeepaliveInfo ki : networkKeepalives.values()) { - if (!ki.mPrivileged) ++takenUnprivilegedSlots; - } - if (takenUnprivilegedSlots > supported - mReservedPrivilegedSlots) { - return ERROR_INSUFFICIENT_RESOURCES; - } - - // Count unprivileged keepalives for the same uid across networks. - int unprivilegedCountSameUid = 0; - for (final HashMap kaForNetwork : mKeepalives.values()) { - for (final KeepaliveInfo ki : kaForNetwork.values()) { - if (ki.mUid == mUid) { - unprivilegedCountSameUid++; - } - } - } - if (unprivilegedCountSameUid > mAllowedUnprivilegedSlotsForUid) { - return ERROR_INSUFFICIENT_RESOURCES; - } - return SUCCESS; - } - - private int checkLimit() { - final HashMap networkKeepalives = mKeepalives.get(mNai); - if (networkKeepalives == null) { - return ERROR_INVALID_NETWORK; - } - final int supported = KeepaliveUtils.getSupportedKeepalivesForNetworkCapabilities( - mSupportedKeepalives, mNai.networkCapabilities); - if (supported == 0) return ERROR_UNSUPPORTED; - if (networkKeepalives.size() > supported) return ERROR_INSUFFICIENT_RESOURCES; - return SUCCESS; - } - - private int isValid() { - synchronized (mNai) { - int error = checkInterval(); - if (error == SUCCESS) error = checkLimit(); - if (error == SUCCESS) error = checkPermission(); - if (error == SUCCESS) error = checkNetworkConnected(); - if (error == SUCCESS) error = checkSourceAddress(); - return error; - } - } - - void start(int slot) { - mSlot = slot; - int error = isValid(); - if (error == SUCCESS) { - Log.d(TAG, "Starting keepalive " + mSlot + " on " + mNai.toShortString()); - switch (mType) { - case TYPE_NATT: - final NattKeepalivePacketData nattData = (NattKeepalivePacketData) mPacket; - mNai.onAddNattKeepalivePacketFilter(slot, nattData); - mNai.onStartNattSocketKeepalive(slot, mInterval, nattData); - break; - case TYPE_TCP: - try { - mTcpController.startSocketMonitor(mFd, this, mSlot); - } catch (InvalidSocketException e) { - handleStopKeepalive(mNai, mSlot, ERROR_INVALID_SOCKET); - return; - } - final TcpKeepalivePacketData tcpData = (TcpKeepalivePacketData) mPacket; - mNai.onAddTcpKeepalivePacketFilter(slot, tcpData); - // TODO: check result from apf and notify of failure as needed. - mNai.onStartTcpSocketKeepalive(slot, mInterval, tcpData); - break; - default: - Log.wtf(TAG, "Starting keepalive with unknown type: " + mType); - handleStopKeepalive(mNai, mSlot, error); - return; - } - mStartedState = STARTING; - } else { - handleStopKeepalive(mNai, mSlot, error); - return; - } - } - - void stop(int reason) { - int uid = Binder.getCallingUid(); - if (uid != mUid && uid != Process.SYSTEM_UID) { - if (DBG) { - Log.e(TAG, "Cannot stop unowned keepalive " + mSlot + " on " + mNai.network); - } - } - // Ignore the case when the network disconnects immediately after stop() has been - // called and the keepalive code is waiting for the response from the modem. This - // might happen when the caller listens for a lower-layer network disconnect - // callback and stop the keepalive at that time. But the stop() races with the - // stop() generated in ConnectivityService network disconnection code path. - if (mStartedState == STOPPING && reason == ERROR_INVALID_NETWORK) return; - - // Store the reason of stopping, and report it after the keepalive is fully stopped. - if (mStopReason != ERROR_STOP_REASON_UNINITIALIZED) { - throw new IllegalStateException("Unexpected stop reason: " + mStopReason); - } - mStopReason = reason; - Log.d(TAG, "Stopping keepalive " + mSlot + " on " + mNai.toShortString() - + ": " + reason); - switch (mStartedState) { - case NOT_STARTED: - // Remove the reference of the keepalive that meet error before starting, - // e.g. invalid parameter. - cleanupStoppedKeepalive(mNai, mSlot); - break; - default: - mStartedState = STOPPING; - switch (mType) { - case TYPE_TCP: - mTcpController.stopSocketMonitor(mSlot); - // fall through - case TYPE_NATT: - mNai.onStopSocketKeepalive(mSlot); - mNai.onRemoveKeepalivePacketFilter(mSlot); - break; - default: - Log.wtf(TAG, "Stopping keepalive with unknown type: " + mType); - } - } - - // Close the duplicated fd that maintains the lifecycle of socket whenever - // keepalive is running. - if (mFd != null) { - try { - Os.close(mFd); - } catch (ErrnoException e) { - // This should not happen since system server controls the lifecycle of fd when - // keepalive offload is running. - Log.wtf(TAG, "Error closing fd for keepalive " + mSlot + ": " + e); - } - } - } - - void onFileDescriptorInitiatedStop(final int socketKeepaliveReason) { - handleStopKeepalive(mNai, mSlot, socketKeepaliveReason); - } - } - - void notifyErrorCallback(ISocketKeepaliveCallback cb, int error) { - if (DBG) Log.w(TAG, "Sending onError(" + error + ") callback"); - try { - cb.onError(error); - } catch (RemoteException e) { - Log.w(TAG, "Discarded onError(" + error + ") callback"); - } - } - - private int findFirstFreeSlot(NetworkAgentInfo nai) { - HashMap networkKeepalives = mKeepalives.get(nai); - if (networkKeepalives == null) { - networkKeepalives = new HashMap(); - mKeepalives.put(nai, networkKeepalives); - } - - // Find the lowest-numbered free slot. Slot numbers start from 1, because that's what two - // separate chipset implementations independently came up with. - int slot; - for (slot = 1; slot <= networkKeepalives.size(); slot++) { - if (networkKeepalives.get(slot) == null) { - return slot; - } - } - return slot; - } - - public void handleStartKeepalive(Message message) { - KeepaliveInfo ki = (KeepaliveInfo) message.obj; - NetworkAgentInfo nai = ki.getNai(); - int slot = findFirstFreeSlot(nai); - mKeepalives.get(nai).put(slot, ki); - ki.start(slot); - } - - public void handleStopAllKeepalives(NetworkAgentInfo nai, int reason) { - final HashMap networkKeepalives = mKeepalives.get(nai); - if (networkKeepalives != null) { - final ArrayList kalist = new ArrayList(networkKeepalives.values()); - for (KeepaliveInfo ki : kalist) { - ki.stop(reason); - // Clean up keepalives since the network agent is disconnected and unable to pass - // back asynchronous result of stop(). - cleanupStoppedKeepalive(nai, ki.mSlot); - } - } - } - - public void handleStopKeepalive(NetworkAgentInfo nai, int slot, int reason) { - final String networkName = NetworkAgentInfo.toShortString(nai); - HashMap networkKeepalives = mKeepalives.get(nai); - if (networkKeepalives == null) { - Log.e(TAG, "Attempt to stop keepalive on nonexistent network " + networkName); - return; - } - KeepaliveInfo ki = networkKeepalives.get(slot); - if (ki == null) { - Log.e(TAG, "Attempt to stop nonexistent keepalive " + slot + " on " + networkName); - return; - } - ki.stop(reason); - // Clean up keepalives will be done as a result of calling ki.stop() after the slots are - // freed. - } - - private void cleanupStoppedKeepalive(NetworkAgentInfo nai, int slot) { - final String networkName = NetworkAgentInfo.toShortString(nai); - HashMap networkKeepalives = mKeepalives.get(nai); - if (networkKeepalives == null) { - Log.e(TAG, "Attempt to remove keepalive on nonexistent network " + networkName); - return; - } - KeepaliveInfo ki = networkKeepalives.get(slot); - if (ki == null) { - Log.e(TAG, "Attempt to remove nonexistent keepalive " + slot + " on " + networkName); - return; - } - - // Remove the keepalive from hash table so the slot can be considered available when reusing - // it. - networkKeepalives.remove(slot); - Log.d(TAG, "Remove keepalive " + slot + " on " + networkName + ", " - + networkKeepalives.size() + " remains."); - if (networkKeepalives.isEmpty()) { - mKeepalives.remove(nai); - } - - // Notify app that the keepalive is stopped. - final int reason = ki.mStopReason; - if (reason == SUCCESS) { - try { - ki.mCallback.onStopped(); - } catch (RemoteException e) { - Log.w(TAG, "Discarded onStop callback: " + reason); - } - } else if (reason == DATA_RECEIVED) { - try { - ki.mCallback.onDataReceived(); - } catch (RemoteException e) { - Log.w(TAG, "Discarded onDataReceived callback: " + reason); - } - } else if (reason == ERROR_STOP_REASON_UNINITIALIZED) { - throw new IllegalStateException("Unexpected stop reason: " + reason); - } else if (reason == ERROR_NO_SUCH_SLOT) { - throw new IllegalStateException("No such slot: " + reason); - } else { - notifyErrorCallback(ki.mCallback, reason); - } - - ki.unlinkDeathRecipient(); - } - - public void handleCheckKeepalivesStillValid(NetworkAgentInfo nai) { - HashMap networkKeepalives = mKeepalives.get(nai); - if (networkKeepalives != null) { - ArrayList> invalidKeepalives = new ArrayList<>(); - for (int slot : networkKeepalives.keySet()) { - int error = networkKeepalives.get(slot).isValid(); - if (error != SUCCESS) { - invalidKeepalives.add(Pair.create(slot, error)); - } - } - for (Pair slotAndError: invalidKeepalives) { - handleStopKeepalive(nai, slotAndError.first, slotAndError.second); - } - } - } - - /** Handle keepalive events from lower layer. */ - public void handleEventSocketKeepalive(@NonNull NetworkAgentInfo nai, int slot, int reason) { - KeepaliveInfo ki = null; - try { - ki = mKeepalives.get(nai).get(slot); - } catch(NullPointerException e) {} - if (ki == null) { - Log.e(TAG, "Event " + NetworkAgent.EVENT_SOCKET_KEEPALIVE + "," + slot + "," + reason - + " for unknown keepalive " + slot + " on " + nai.toShortString()); - return; - } - - // This can be called in a number of situations : - // - startedState is STARTING. - // - reason is SUCCESS => go to STARTED. - // - reason isn't SUCCESS => it's an error starting. Go to NOT_STARTED and stop keepalive. - // - startedState is STARTED. - // - reason is SUCCESS => it's a success stopping. Go to NOT_STARTED and stop keepalive. - // - reason isn't SUCCESS => it's an error in exec. Go to NOT_STARTED and stop keepalive. - // The control is not supposed to ever come here if the state is NOT_STARTED. This is - // because in NOT_STARTED state, the code will switch to STARTING before sending messages - // to start, and the only way to NOT_STARTED is this function, through the edges outlined - // above : in all cases, keepalive gets stopped and can't restart without going into - // STARTING as messages are ordered. This also depends on the hardware processing the - // messages in order. - // TODO : clarify this code and get rid of mStartedState. Using a StateMachine is an - // option. - if (KeepaliveInfo.STARTING == ki.mStartedState) { - if (SUCCESS == reason) { - // Keepalive successfully started. - Log.d(TAG, "Started keepalive " + slot + " on " + nai.toShortString()); - ki.mStartedState = KeepaliveInfo.STARTED; - try { - ki.mCallback.onStarted(slot); - } catch (RemoteException e) { - Log.w(TAG, "Discarded onStarted(" + slot + ") callback"); - } - } else { - Log.d(TAG, "Failed to start keepalive " + slot + " on " + nai.toShortString() - + ": " + reason); - // The message indicated some error trying to start: do call handleStopKeepalive. - handleStopKeepalive(nai, slot, reason); - } - } else if (KeepaliveInfo.STOPPING == ki.mStartedState) { - // The message indicated result of stopping : clean up keepalive slots. - Log.d(TAG, "Stopped keepalive " + slot + " on " + nai.toShortString() - + " stopped: " + reason); - ki.mStartedState = KeepaliveInfo.NOT_STARTED; - cleanupStoppedKeepalive(nai, slot); - } else { - Log.wtf(TAG, "Event " + NetworkAgent.EVENT_SOCKET_KEEPALIVE + "," + slot + "," + reason - + " for keepalive in wrong state: " + ki.toString()); - } - } - - /** - * Called when requesting that keepalives be started on a IPsec NAT-T socket. See - * {@link android.net.SocketKeepalive}. - **/ - public void startNattKeepalive(@Nullable NetworkAgentInfo nai, - @Nullable FileDescriptor fd, - int intervalSeconds, - @NonNull ISocketKeepaliveCallback cb, - @NonNull String srcAddrString, - int srcPort, - @NonNull String dstAddrString, - int dstPort) { - if (nai == null) { - notifyErrorCallback(cb, ERROR_INVALID_NETWORK); - return; - } - - InetAddress srcAddress, dstAddress; - try { - srcAddress = InetAddresses.parseNumericAddress(srcAddrString); - dstAddress = InetAddresses.parseNumericAddress(dstAddrString); - } catch (IllegalArgumentException e) { - notifyErrorCallback(cb, ERROR_INVALID_IP_ADDRESS); - return; - } - - KeepalivePacketData packet; - try { - packet = NattKeepalivePacketData.nattKeepalivePacket( - srcAddress, srcPort, dstAddress, NATT_PORT); - } catch (InvalidPacketException e) { - notifyErrorCallback(cb, e.getError()); - return; - } - KeepaliveInfo ki = null; - try { - ki = new KeepaliveInfo(cb, nai, packet, intervalSeconds, - KeepaliveInfo.TYPE_NATT, fd); - } catch (InvalidSocketException | IllegalArgumentException | SecurityException e) { - Log.e(TAG, "Fail to construct keepalive", e); - notifyErrorCallback(cb, ERROR_INVALID_SOCKET); - return; - } - Log.d(TAG, "Created keepalive: " + ki.toString()); - mConnectivityServiceHandler.obtainMessage( - NetworkAgent.CMD_START_SOCKET_KEEPALIVE, ki).sendToTarget(); - } - - /** - * Called by ConnectivityService to start TCP keepalive on a file descriptor. - * - * In order to offload keepalive for application correctly, sequence number, ack number and - * other fields are needed to form the keepalive packet. Thus, this function synchronously - * puts the socket into repair mode to get the necessary information. After the socket has been - * put into repair mode, the application cannot access the socket until reverted to normal. - * - * See {@link android.net.SocketKeepalive}. - **/ - public void startTcpKeepalive(@Nullable NetworkAgentInfo nai, - @NonNull FileDescriptor fd, - int intervalSeconds, - @NonNull ISocketKeepaliveCallback cb) { - if (nai == null) { - notifyErrorCallback(cb, ERROR_INVALID_NETWORK); - return; - } - - final TcpKeepalivePacketData packet; - try { - packet = TcpKeepaliveController.getTcpKeepalivePacket(fd); - } catch (InvalidSocketException e) { - notifyErrorCallback(cb, e.error); - return; - } catch (InvalidPacketException e) { - notifyErrorCallback(cb, e.getError()); - return; - } - KeepaliveInfo ki = null; - try { - ki = new KeepaliveInfo(cb, nai, packet, intervalSeconds, - KeepaliveInfo.TYPE_TCP, fd); - } catch (InvalidSocketException | IllegalArgumentException | SecurityException e) { - Log.e(TAG, "Fail to construct keepalive e=" + e); - notifyErrorCallback(cb, ERROR_INVALID_SOCKET); - return; - } - Log.d(TAG, "Created keepalive: " + ki.toString()); - mConnectivityServiceHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, ki).sendToTarget(); - } - - /** - * Called when requesting that keepalives be started on a IPsec NAT-T socket. This function is - * identical to {@link #startNattKeepalive}, but also takes a {@code resourceId}, which is the - * resource index bound to the {@link UdpEncapsulationSocket} when creating by - * {@link com.android.server.IpSecService} to verify whether the given - * {@link UdpEncapsulationSocket} is legitimate. - **/ - public void startNattKeepalive(@Nullable NetworkAgentInfo nai, - @Nullable FileDescriptor fd, - int resourceId, - int intervalSeconds, - @NonNull ISocketKeepaliveCallback cb, - @NonNull String srcAddrString, - @NonNull String dstAddrString, - int dstPort) { - // Ensure that the socket is created by IpSecService. - if (!isNattKeepaliveSocketValid(fd, resourceId)) { - notifyErrorCallback(cb, ERROR_INVALID_SOCKET); - } - - // Get src port to adopt old API. - int srcPort = 0; - try { - final SocketAddress srcSockAddr = Os.getsockname(fd); - srcPort = ((InetSocketAddress) srcSockAddr).getPort(); - } catch (ErrnoException e) { - notifyErrorCallback(cb, ERROR_INVALID_SOCKET); - } - - // Forward request to old API. - startNattKeepalive(nai, fd, intervalSeconds, cb, srcAddrString, srcPort, - dstAddrString, dstPort); - } - - /** - * Verify if the IPsec NAT-T file descriptor and resource Id hold for IPsec keepalive is valid. - **/ - public static boolean isNattKeepaliveSocketValid(@Nullable FileDescriptor fd, int resourceId) { - // TODO: 1. confirm whether the fd is called from system api or created by IpSecService. - // 2. If the fd is created from the system api, check that it's bounded. And - // call dup to keep the fd open. - // 3. If the fd is created from IpSecService, check if the resource ID is valid. And - // hold the resource needed in IpSecService. - if (null == fd) { - return false; - } - return true; - } - - public void dump(IndentingPrintWriter pw) { - pw.println("Supported Socket keepalives: " + Arrays.toString(mSupportedKeepalives)); - pw.println("Reserved Privileged keepalives: " + mReservedPrivilegedSlots); - pw.println("Allowed Unprivileged keepalives per uid: " + mAllowedUnprivilegedSlotsForUid); - pw.println("Socket keepalives:"); - pw.increaseIndent(); - for (NetworkAgentInfo nai : mKeepalives.keySet()) { - pw.println(nai.toShortString()); - pw.increaseIndent(); - for (int slot : mKeepalives.get(nai).keySet()) { - KeepaliveInfo ki = mKeepalives.get(nai).get(slot); - pw.println(slot + ": " + ki.toString()); - } - pw.decreaseIndent(); - } - pw.decreaseIndent(); - } -} diff --git a/packages/Connectivity/service/src/com/android/server/connectivity/LingerMonitor.java b/packages/Connectivity/service/src/com/android/server/connectivity/LingerMonitor.java deleted file mode 100644 index 032612c6f093a..0000000000000 --- a/packages/Connectivity/service/src/com/android/server/connectivity/LingerMonitor.java +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import static android.net.ConnectivityManager.NETID_UNSET; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.app.PendingIntent; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; -import android.net.ConnectivityResources; -import android.net.NetworkCapabilities; -import android.os.SystemClock; -import android.os.UserHandle; -import android.text.TextUtils; -import android.text.format.DateUtils; -import android.util.Log; -import android.util.SparseArray; -import android.util.SparseBooleanArray; -import android.util.SparseIntArray; - -import com.android.connectivity.resources.R; -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.MessageUtils; -import com.android.server.connectivity.NetworkNotificationManager.NotificationType; - -import java.util.Arrays; -import java.util.HashMap; - -/** - * Class that monitors default network linger events and possibly notifies the user of network - * switches. - * - * This class is not thread-safe and all its methods must be called on the ConnectivityService - * handler thread. - */ -public class LingerMonitor { - - private static final boolean DBG = true; - private static final boolean VDBG = false; - private static final String TAG = LingerMonitor.class.getSimpleName(); - - public static final int DEFAULT_NOTIFICATION_DAILY_LIMIT = 3; - public static final long DEFAULT_NOTIFICATION_RATE_LIMIT_MILLIS = DateUtils.MINUTE_IN_MILLIS; - - private static final HashMap TRANSPORT_NAMES = makeTransportToNameMap(); - @VisibleForTesting - public static final Intent CELLULAR_SETTINGS = new Intent().setComponent(new ComponentName( - "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity")); - - @VisibleForTesting - public static final int NOTIFY_TYPE_NONE = 0; - public static final int NOTIFY_TYPE_NOTIFICATION = 1; - public static final int NOTIFY_TYPE_TOAST = 2; - - private static SparseArray sNotifyTypeNames = MessageUtils.findMessageNames( - new Class[] { LingerMonitor.class }, new String[]{ "NOTIFY_TYPE_" }); - - private final Context mContext; - final Resources mResources; - private final NetworkNotificationManager mNotifier; - private final int mDailyLimit; - private final long mRateLimitMillis; - - private long mFirstNotificationMillis; - private long mLastNotificationMillis; - private int mNotificationCounter; - - /** Current notifications. Maps the netId we switched away from to the netId we switched to. */ - private final SparseIntArray mNotifications = new SparseIntArray(); - - /** Whether we ever notified that we switched away from a particular network. */ - private final SparseBooleanArray mEverNotified = new SparseBooleanArray(); - - public LingerMonitor(Context context, NetworkNotificationManager notifier, - int dailyLimit, long rateLimitMillis) { - mContext = context; - mResources = new ConnectivityResources(mContext).get(); - mNotifier = notifier; - mDailyLimit = dailyLimit; - mRateLimitMillis = rateLimitMillis; - // Ensure that (now - mLastNotificationMillis) >= rateLimitMillis at first - mLastNotificationMillis = -rateLimitMillis; - } - - private static HashMap makeTransportToNameMap() { - SparseArray numberToName = MessageUtils.findMessageNames( - new Class[] { NetworkCapabilities.class }, new String[]{ "TRANSPORT_" }); - HashMap nameToNumber = new HashMap<>(); - for (int i = 0; i < numberToName.size(); i++) { - // MessageUtils will fail to initialize if there are duplicate constant values, so there - // are no duplicates here. - nameToNumber.put(numberToName.valueAt(i), numberToName.keyAt(i)); - } - return nameToNumber; - } - - private static boolean hasTransport(NetworkAgentInfo nai, int transport) { - return nai.networkCapabilities.hasTransport(transport); - } - - private int getNotificationSource(NetworkAgentInfo toNai) { - for (int i = 0; i < mNotifications.size(); i++) { - if (mNotifications.valueAt(i) == toNai.network.getNetId()) { - return mNotifications.keyAt(i); - } - } - return NETID_UNSET; - } - - private boolean everNotified(NetworkAgentInfo nai) { - return mEverNotified.get(nai.network.getNetId(), false); - } - - @VisibleForTesting - public boolean isNotificationEnabled(NetworkAgentInfo fromNai, NetworkAgentInfo toNai) { - // TODO: Evaluate moving to CarrierConfigManager. - String[] notifySwitches = mResources.getStringArray(R.array.config_networkNotifySwitches); - - if (VDBG) { - Log.d(TAG, "Notify on network switches: " + Arrays.toString(notifySwitches)); - } - - for (String notifySwitch : notifySwitches) { - if (TextUtils.isEmpty(notifySwitch)) continue; - String[] transports = notifySwitch.split("-", 2); - if (transports.length != 2) { - Log.e(TAG, "Invalid network switch notification configuration: " + notifySwitch); - continue; - } - int fromTransport = TRANSPORT_NAMES.get("TRANSPORT_" + transports[0]); - int toTransport = TRANSPORT_NAMES.get("TRANSPORT_" + transports[1]); - if (hasTransport(fromNai, fromTransport) && hasTransport(toNai, toTransport)) { - return true; - } - } - - return false; - } - - private void showNotification(NetworkAgentInfo fromNai, NetworkAgentInfo toNai) { - mNotifier.showNotification(fromNai.network.getNetId(), NotificationType.NETWORK_SWITCH, - fromNai, toNai, createNotificationIntent(), true); - } - - @VisibleForTesting - protected PendingIntent createNotificationIntent() { - return PendingIntent.getActivity( - mContext.createContextAsUser(UserHandle.CURRENT, 0 /* flags */), - 0 /* requestCode */, - CELLULAR_SETTINGS, - PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE); - } - - // Removes any notification that was put up as a result of switching to nai. - private void maybeStopNotifying(NetworkAgentInfo nai) { - int fromNetId = getNotificationSource(nai); - if (fromNetId != NETID_UNSET) { - mNotifications.delete(fromNetId); - mNotifier.clearNotification(fromNetId); - // Toasts can't be deleted. - } - } - - // Notify the user of a network switch using a notification or a toast. - private void notify(NetworkAgentInfo fromNai, NetworkAgentInfo toNai, boolean forceToast) { - int notifyType = mResources.getInteger(R.integer.config_networkNotifySwitchType); - if (notifyType == NOTIFY_TYPE_NOTIFICATION && forceToast) { - notifyType = NOTIFY_TYPE_TOAST; - } - - if (VDBG) { - Log.d(TAG, "Notify type: " + sNotifyTypeNames.get(notifyType, "" + notifyType)); - } - - switch (notifyType) { - case NOTIFY_TYPE_NONE: - return; - case NOTIFY_TYPE_NOTIFICATION: - showNotification(fromNai, toNai); - break; - case NOTIFY_TYPE_TOAST: - mNotifier.showToast(fromNai, toNai); - break; - default: - Log.e(TAG, "Unknown notify type " + notifyType); - return; - } - - if (DBG) { - Log.d(TAG, "Notifying switch from=" + fromNai.toShortString() - + " to=" + toNai.toShortString() - + " type=" + sNotifyTypeNames.get(notifyType, "unknown(" + notifyType + ")")); - } - - mNotifications.put(fromNai.network.getNetId(), toNai.network.getNetId()); - mEverNotified.put(fromNai.network.getNetId(), true); - } - - /** - * Put up or dismiss a notification or toast for of a change in the default network if needed. - * - * Putting up a notification when switching from no network to some network is not supported - * and as such this method can't be called with a null |fromNai|. It can be called with a - * null |toNai| if there isn't a default network any more. - * - * @param fromNai switching from this NAI - * @param toNai switching to this NAI - */ - // The default network changed from fromNai to toNai due to a change in score. - public void noteLingerDefaultNetwork(@NonNull final NetworkAgentInfo fromNai, - @Nullable final NetworkAgentInfo toNai) { - if (VDBG) { - Log.d(TAG, "noteLingerDefaultNetwork from=" + fromNai.toShortString() - + " everValidated=" + fromNai.everValidated - + " lastValidated=" + fromNai.lastValidated - + " to=" + toNai.toShortString()); - } - - // If we are currently notifying the user because the device switched to fromNai, now that - // we are switching away from it we should remove the notification. This includes the case - // where we switch back to toNai because its score improved again (e.g., because it regained - // Internet access). - maybeStopNotifying(fromNai); - - // If the network was simply lost (either because it disconnected or because it stopped - // being the default with no replacement), then don't show a notification. - if (null == toNai) return; - - // If this network never validated, don't notify. Otherwise, we could do things like: - // - // 1. Unvalidated wifi connects. - // 2. Unvalidated mobile data connects. - // 3. Cell validates, and we show a notification. - // or: - // 1. User connects to wireless printer. - // 2. User turns on cellular data. - // 3. We show a notification. - if (!fromNai.everValidated) return; - - // If this network is a captive portal, don't notify. This cannot happen on initial connect - // to a captive portal, because the everValidated check above will fail. However, it can - // happen if the captive portal reasserts itself (e.g., because its timeout fires). In that - // case, as soon as the captive portal reasserts itself, we'll show a sign-in notification. - // We don't want to overwrite that notification with this one; the user has already been - // notified, and of the two, the captive portal notification is the more useful one because - // it allows the user to sign in to the captive portal. In this case, display a toast - // in addition to the captive portal notification. - // - // Note that if the network we switch to is already up when the captive portal reappears, - // this won't work because NetworkMonitor tells ConnectivityService that the network is - // unvalidated (causing a switch) before asking it to show the sign in notification. In this - // case, the toast won't show and we'll only display the sign in notification. This is the - // best we can do at this time. - boolean forceToast = fromNai.networkCapabilities.hasCapability( - NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL); - - // Only show the notification once, in order to avoid irritating the user every time. - // TODO: should we do this? - if (everNotified(fromNai)) { - if (VDBG) { - Log.d(TAG, "Not notifying handover from " + fromNai.toShortString() - + ", already notified"); - } - return; - } - - // Only show the notification if we switched away because a network became unvalidated, not - // because its score changed. - // TODO: instead of just skipping notification, keep a note of it, and show it if it becomes - // unvalidated. - if (fromNai.lastValidated) return; - - if (!isNotificationEnabled(fromNai, toNai)) return; - - final long now = SystemClock.elapsedRealtime(); - if (isRateLimited(now) || isAboveDailyLimit(now)) return; - - notify(fromNai, toNai, forceToast); - } - - public void noteDisconnect(NetworkAgentInfo nai) { - mNotifications.delete(nai.network.getNetId()); - mEverNotified.delete(nai.network.getNetId()); - maybeStopNotifying(nai); - // No need to cancel notifications on nai: NetworkMonitor does that on disconnect. - } - - private boolean isRateLimited(long now) { - final long millisSinceLast = now - mLastNotificationMillis; - if (millisSinceLast < mRateLimitMillis) { - return true; - } - mLastNotificationMillis = now; - return false; - } - - private boolean isAboveDailyLimit(long now) { - if (mFirstNotificationMillis == 0) { - mFirstNotificationMillis = now; - } - final long millisSinceFirst = now - mFirstNotificationMillis; - if (millisSinceFirst > DateUtils.DAY_IN_MILLIS) { - mNotificationCounter = 0; - mFirstNotificationMillis = 0; - } - if (mNotificationCounter >= mDailyLimit) { - return true; - } - mNotificationCounter++; - return false; - } -} diff --git a/packages/Connectivity/service/src/com/android/server/connectivity/MockableSystemProperties.java b/packages/Connectivity/service/src/com/android/server/connectivity/MockableSystemProperties.java deleted file mode 100644 index a25b89ac039ab..0000000000000 --- a/packages/Connectivity/service/src/com/android/server/connectivity/MockableSystemProperties.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import android.os.SystemProperties; - -public class MockableSystemProperties { - - public String get(String key) { - return SystemProperties.get(key); - } - - public int getInt(String key, int def) { - return SystemProperties.getInt(key, def); - } - - public boolean getBoolean(String key, boolean def) { - return SystemProperties.getBoolean(key, def); - } -} diff --git a/packages/Connectivity/service/src/com/android/server/connectivity/Nat464Xlat.java b/packages/Connectivity/service/src/com/android/server/connectivity/Nat464Xlat.java deleted file mode 100644 index c66a280f2b028..0000000000000 --- a/packages/Connectivity/service/src/com/android/server/connectivity/Nat464Xlat.java +++ /dev/null @@ -1,523 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; - -import static com.android.net.module.util.CollectionUtils.contains; - -import android.annotation.NonNull; -import android.net.ConnectivityManager; -import android.net.IDnsResolver; -import android.net.INetd; -import android.net.InetAddresses; -import android.net.InterfaceConfigurationParcel; -import android.net.IpPrefix; -import android.net.LinkAddress; -import android.net.LinkProperties; -import android.net.NetworkInfo; -import android.net.RouteInfo; -import android.os.RemoteException; -import android.os.ServiceSpecificException; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.net.module.util.NetworkStackConstants; -import com.android.server.ConnectivityService; - -import java.net.Inet6Address; -import java.util.Objects; - -/** - * Class to manage a 464xlat CLAT daemon. Nat464Xlat is not thread safe and should be manipulated - * from a consistent and unique thread context. It is the responsibility of ConnectivityService to - * call into this class from its own Handler thread. - * - * @hide - */ -public class Nat464Xlat { - private static final String TAG = Nat464Xlat.class.getSimpleName(); - - // This must match the interface prefix in clatd.c. - private static final String CLAT_PREFIX = "v4-"; - - // The network types on which we will start clatd, - // allowing clat only on networks for which we can support IPv6-only. - private static final int[] NETWORK_TYPES = { - ConnectivityManager.TYPE_MOBILE, - ConnectivityManager.TYPE_WIFI, - ConnectivityManager.TYPE_ETHERNET, - }; - - // The network states in which running clatd is supported. - private static final NetworkInfo.State[] NETWORK_STATES = { - NetworkInfo.State.CONNECTED, - NetworkInfo.State.SUSPENDED, - }; - - private final IDnsResolver mDnsResolver; - private final INetd mNetd; - - // The network we're running on, and its type. - private final NetworkAgentInfo mNetwork; - - private enum State { - IDLE, // start() not called. Base iface and stacked iface names are null. - DISCOVERING, // same as IDLE, except prefix discovery in progress. - STARTING, // start() called. Base iface and stacked iface names are known. - RUNNING, // start() called, and the stacked iface is known to be up. - } - - /** - * NAT64 prefix currently in use. Only valid in STARTING or RUNNING states. - * Used, among other things, to avoid updates when switching from a prefix learned from one - * source (e.g., RA) to the same prefix learned from another source (e.g., RA). - */ - private IpPrefix mNat64PrefixInUse; - /** NAT64 prefix (if any) discovered from DNS via RFC 7050. */ - private IpPrefix mNat64PrefixFromDns; - /** NAT64 prefix (if any) learned from the network via RA. */ - private IpPrefix mNat64PrefixFromRa; - private String mBaseIface; - private String mIface; - private Inet6Address mIPv6Address; - private State mState = State.IDLE; - - private boolean mEnableClatOnCellular; - private boolean mPrefixDiscoveryRunning; - - public Nat464Xlat(NetworkAgentInfo nai, INetd netd, IDnsResolver dnsResolver, - ConnectivityService.Dependencies deps) { - mDnsResolver = dnsResolver; - mNetd = netd; - mNetwork = nai; - mEnableClatOnCellular = deps.getCellular464XlatEnabled(); - } - - /** - * Whether to attempt 464xlat on this network. This is true for an IPv6-only network that is - * currently connected and where the NetworkAgent has not disabled 464xlat. It is the signal to - * enable NAT64 prefix discovery. - * - * @param nai the NetworkAgentInfo corresponding to the network. - * @return true if the network requires clat, false otherwise. - */ - @VisibleForTesting - protected boolean requiresClat(NetworkAgentInfo nai) { - // TODO: migrate to NetworkCapabilities.TRANSPORT_*. - final boolean supported = contains(NETWORK_TYPES, nai.networkInfo.getType()); - final boolean connected = contains(NETWORK_STATES, nai.networkInfo.getState()); - - // Only run clat on networks that have a global IPv6 address and don't have a native IPv4 - // address. - LinkProperties lp = nai.linkProperties; - final boolean isIpv6OnlyNetwork = (lp != null) && lp.hasGlobalIpv6Address() - && !lp.hasIpv4Address(); - - // If the network tells us it doesn't use clat, respect that. - final boolean skip464xlat = (nai.netAgentConfig() != null) - && nai.netAgentConfig().skip464xlat; - - return supported && connected && isIpv6OnlyNetwork && !skip464xlat - && (nai.networkCapabilities.hasTransport(TRANSPORT_CELLULAR) - ? isCellular464XlatEnabled() : true); - } - - /** - * Whether the clat demon should be started on this network now. This is true if requiresClat is - * true and a NAT64 prefix has been discovered. - * - * @param nai the NetworkAgentInfo corresponding to the network. - * @return true if the network should start clat, false otherwise. - */ - @VisibleForTesting - protected boolean shouldStartClat(NetworkAgentInfo nai) { - LinkProperties lp = nai.linkProperties; - return requiresClat(nai) && lp != null && lp.getNat64Prefix() != null; - } - - /** - * @return true if clatd has been started and has not yet stopped. - * A true result corresponds to internal states STARTING and RUNNING. - */ - public boolean isStarted() { - return (mState == State.STARTING || mState == State.RUNNING); - } - - /** - * @return true if clatd has been started but the stacked interface is not yet up. - */ - public boolean isStarting() { - return mState == State.STARTING; - } - - /** - * @return true if clatd has been started and the stacked interface is up. - */ - public boolean isRunning() { - return mState == State.RUNNING; - } - - /** - * Start clatd, register this Nat464Xlat as a network observer for the stacked interface, - * and set internal state. - */ - private void enterStartingState(String baseIface) { - mNat64PrefixInUse = selectNat64Prefix(); - String addrStr = null; - try { - addrStr = mNetd.clatdStart(baseIface, mNat64PrefixInUse.toString()); - } catch (RemoteException | ServiceSpecificException e) { - Log.e(TAG, "Error starting clatd on " + baseIface + ": " + e); - } - mIface = CLAT_PREFIX + baseIface; - mBaseIface = baseIface; - mState = State.STARTING; - try { - mIPv6Address = (Inet6Address) InetAddresses.parseNumericAddress(addrStr); - } catch (ClassCastException | IllegalArgumentException | NullPointerException e) { - Log.e(TAG, "Invalid IPv6 address " + addrStr); - } - if (mPrefixDiscoveryRunning && !isPrefixDiscoveryNeeded()) { - stopPrefixDiscovery(); - } - if (!mPrefixDiscoveryRunning) { - setPrefix64(mNat64PrefixInUse); - } - } - - /** - * Enter running state just after getting confirmation that the stacked interface is up, and - * turn ND offload off if on WiFi. - */ - private void enterRunningState() { - mState = State.RUNNING; - } - - /** - * Unregister as a base observer for the stacked interface, and clear internal state. - */ - private void leaveStartedState() { - mNat64PrefixInUse = null; - mIface = null; - mBaseIface = null; - - if (!mPrefixDiscoveryRunning) { - setPrefix64(null); - } - - if (isPrefixDiscoveryNeeded()) { - if (!mPrefixDiscoveryRunning) { - startPrefixDiscovery(); - } - mState = State.DISCOVERING; - } else { - stopPrefixDiscovery(); - mState = State.IDLE; - } - } - - @VisibleForTesting - protected void start() { - if (isStarted()) { - Log.e(TAG, "startClat: already started"); - return; - } - - String baseIface = mNetwork.linkProperties.getInterfaceName(); - if (baseIface == null) { - Log.e(TAG, "startClat: Can't start clat on null interface"); - return; - } - // TODO: should we only do this if mNetd.clatdStart() succeeds? - Log.i(TAG, "Starting clatd on " + baseIface); - enterStartingState(baseIface); - } - - @VisibleForTesting - protected void stop() { - if (!isStarted()) { - Log.e(TAG, "stopClat: already stopped"); - return; - } - - Log.i(TAG, "Stopping clatd on " + mBaseIface); - try { - mNetd.clatdStop(mBaseIface); - } catch (RemoteException | ServiceSpecificException e) { - Log.e(TAG, "Error stopping clatd on " + mBaseIface + ": " + e); - } - - String iface = mIface; - boolean wasRunning = isRunning(); - - // Change state before updating LinkProperties. handleUpdateLinkProperties ends up calling - // fixupLinkProperties, and if at that time the state is still RUNNING, fixupLinkProperties - // would wrongly inform ConnectivityService that there is still a stacked interface. - leaveStartedState(); - - if (wasRunning) { - LinkProperties lp = new LinkProperties(mNetwork.linkProperties); - lp.removeStackedLink(iface); - mNetwork.connService().handleUpdateLinkProperties(mNetwork, lp); - } - } - - private void startPrefixDiscovery() { - try { - mDnsResolver.startPrefix64Discovery(getNetId()); - } catch (RemoteException | ServiceSpecificException e) { - Log.e(TAG, "Error starting prefix discovery on netId " + getNetId() + ": " + e); - } - mPrefixDiscoveryRunning = true; - } - - private void stopPrefixDiscovery() { - try { - mDnsResolver.stopPrefix64Discovery(getNetId()); - } catch (RemoteException | ServiceSpecificException e) { - Log.e(TAG, "Error stopping prefix discovery on netId " + getNetId() + ": " + e); - } - mPrefixDiscoveryRunning = false; - } - - private boolean isPrefixDiscoveryNeeded() { - // If there is no NAT64 prefix in the RA, prefix discovery is always needed. It cannot be - // stopped after it succeeds, because stopping it will cause netd to report that the prefix - // has been removed, and that will cause us to stop clatd. - return requiresClat(mNetwork) && mNat64PrefixFromRa == null; - } - - private void setPrefix64(IpPrefix prefix) { - final String prefixString = (prefix != null) ? prefix.toString() : ""; - try { - mDnsResolver.setPrefix64(getNetId(), prefixString); - } catch (RemoteException | ServiceSpecificException e) { - Log.e(TAG, "Error setting NAT64 prefix on netId " + getNetId() + " to " - + prefix + ": " + e); - } - } - - private void maybeHandleNat64PrefixChange() { - final IpPrefix newPrefix = selectNat64Prefix(); - if (!Objects.equals(mNat64PrefixInUse, newPrefix)) { - Log.d(TAG, "NAT64 prefix changed from " + mNat64PrefixInUse + " to " - + newPrefix); - stop(); - // It's safe to call update here, even though this method is called from update, because - // stop() is guaranteed to have moved out of STARTING and RUNNING, which are the only - // states in which this method can be called. - update(); - } - } - - /** - * Starts/stops NAT64 prefix discovery and clatd as necessary. - */ - public void update() { - // TODO: turn this class into a proper StateMachine. http://b/126113090 - switch (mState) { - case IDLE: - if (isPrefixDiscoveryNeeded()) { - startPrefixDiscovery(); // Enters DISCOVERING state. - mState = State.DISCOVERING; - } else if (requiresClat(mNetwork)) { - start(); // Enters STARTING state. - } - break; - - case DISCOVERING: - if (shouldStartClat(mNetwork)) { - // NAT64 prefix detected. Start clatd. - start(); // Enters STARTING state. - return; - } - if (!requiresClat(mNetwork)) { - // IPv4 address added. Go back to IDLE state. - stopPrefixDiscovery(); - mState = State.IDLE; - return; - } - break; - - case STARTING: - case RUNNING: - // NAT64 prefix removed, or IPv4 address added. - // Stop clatd and go back into DISCOVERING or idle. - if (!shouldStartClat(mNetwork)) { - stop(); - break; - } - // Only necessary while clat is actually started. - maybeHandleNat64PrefixChange(); - break; - } - } - - /** - * Picks a NAT64 prefix to use. Always prefers the prefix from the RA if one is received from - * both RA and DNS, because the prefix in the RA has better security and updatability, and will - * almost always be received first anyway. - * - * Any network that supports legacy hosts will support discovering the DNS64 prefix via DNS as - * well. If the prefix from the RA is withdrawn, fall back to that for reliability purposes. - */ - private IpPrefix selectNat64Prefix() { - return mNat64PrefixFromRa != null ? mNat64PrefixFromRa : mNat64PrefixFromDns; - } - - public void setNat64PrefixFromRa(IpPrefix prefix) { - mNat64PrefixFromRa = prefix; - } - - public void setNat64PrefixFromDns(IpPrefix prefix) { - mNat64PrefixFromDns = prefix; - } - - /** - * Copies the stacked clat link in oldLp, if any, to the passed LinkProperties. - * This is necessary because the LinkProperties in mNetwork come from the transport layer, which - * has no idea that 464xlat is running on top of it. - */ - public void fixupLinkProperties(@NonNull LinkProperties oldLp, @NonNull LinkProperties lp) { - // This must be done even if clatd is not running, because otherwise shouldStartClat would - // never return true. - lp.setNat64Prefix(selectNat64Prefix()); - - if (!isRunning()) { - return; - } - if (lp.getAllInterfaceNames().contains(mIface)) { - return; - } - - Log.d(TAG, "clatd running, updating NAI for " + mIface); - for (LinkProperties stacked: oldLp.getStackedLinks()) { - if (Objects.equals(mIface, stacked.getInterfaceName())) { - lp.addStackedLink(stacked); - return; - } - } - } - - private LinkProperties makeLinkProperties(LinkAddress clatAddress) { - LinkProperties stacked = new LinkProperties(); - stacked.setInterfaceName(mIface); - - // Although the clat interface is a point-to-point tunnel, we don't - // point the route directly at the interface because some apps don't - // understand routes without gateways (see, e.g., http://b/9597256 - // http://b/9597516). Instead, set the next hop of the route to the - // clat IPv4 address itself (for those apps, it doesn't matter what - // the IP of the gateway is, only that there is one). - RouteInfo ipv4Default = new RouteInfo( - new LinkAddress(NetworkStackConstants.IPV4_ADDR_ANY, 0), - clatAddress.getAddress(), mIface); - stacked.addRoute(ipv4Default); - stacked.addLinkAddress(clatAddress); - return stacked; - } - - private LinkAddress getLinkAddress(String iface) { - try { - final InterfaceConfigurationParcel config = mNetd.interfaceGetCfg(iface); - return new LinkAddress( - InetAddresses.parseNumericAddress(config.ipv4Addr), config.prefixLength); - } catch (IllegalArgumentException | RemoteException | ServiceSpecificException e) { - Log.e(TAG, "Error getting link properties: " + e); - return null; - } - } - - /** - * Adds stacked link on base link and transitions to RUNNING state. - */ - private void handleInterfaceLinkStateChanged(String iface, boolean up) { - // TODO: if we call start(), then stop(), then start() again, and the - // interfaceLinkStateChanged notification for the first start is delayed past the first - // stop, then the code becomes out of sync with system state and will behave incorrectly. - // - // This is not trivial to fix because: - // 1. It is not guaranteed that start() will eventually result in the interface coming up, - // because there could be an error starting clat (e.g., if the interface goes down before - // the packet socket can be bound). - // 2. If start is called multiple times, there is nothing in the interfaceLinkStateChanged - // notification that says which start() call the interface was created by. - // - // Once this code is converted to StateMachine, it will be possible to use deferMessage to - // ensure it stays in STARTING state until the interfaceLinkStateChanged notification fires, - // and possibly use a timeout (or provide some guarantees at the lower layer) to address #1. - if (!isStarting() || !up || !Objects.equals(mIface, iface)) { - return; - } - - LinkAddress clatAddress = getLinkAddress(iface); - if (clatAddress == null) { - Log.e(TAG, "clatAddress was null for stacked iface " + iface); - return; - } - - Log.i(TAG, String.format("interface %s is up, adding stacked link %s on top of %s", - mIface, mIface, mBaseIface)); - enterRunningState(); - LinkProperties lp = new LinkProperties(mNetwork.linkProperties); - lp.addStackedLink(makeLinkProperties(clatAddress)); - mNetwork.connService().handleUpdateLinkProperties(mNetwork, lp); - } - - /** - * Removes stacked link on base link and transitions to IDLE state. - */ - private void handleInterfaceRemoved(String iface) { - if (!Objects.equals(mIface, iface)) { - return; - } - if (!isRunning()) { - return; - } - - Log.i(TAG, "interface " + iface + " removed"); - // If we're running, and the interface was removed, then we didn't call stop(), and it's - // likely that clatd crashed. Ensure we call stop() so we can start clatd again. Calling - // stop() will also update LinkProperties, and if clatd crashed, the LinkProperties update - // will cause ConnectivityService to call start() again. - stop(); - } - - public void interfaceLinkStateChanged(String iface, boolean up) { - mNetwork.handler().post(() -> { handleInterfaceLinkStateChanged(iface, up); }); - } - - public void interfaceRemoved(String iface) { - mNetwork.handler().post(() -> handleInterfaceRemoved(iface)); - } - - @Override - public String toString() { - return "mBaseIface: " + mBaseIface + ", mIface: " + mIface + ", mState: " + mState; - } - - @VisibleForTesting - protected int getNetId() { - return mNetwork.network.getNetId(); - } - - @VisibleForTesting - protected boolean isCellular464XlatEnabled() { - return mEnableClatOnCellular; - } -} diff --git a/packages/Connectivity/service/src/com/android/server/connectivity/NetworkAgentInfo.java b/packages/Connectivity/service/src/com/android/server/connectivity/NetworkAgentInfo.java deleted file mode 100644 index 18becd45f6d8b..0000000000000 --- a/packages/Connectivity/service/src/com/android/server/connectivity/NetworkAgentInfo.java +++ /dev/null @@ -1,1215 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport; -import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; -import static android.net.NetworkCapabilities.transportNamesOf; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.net.CaptivePortalData; -import android.net.IDnsResolver; -import android.net.INetd; -import android.net.INetworkAgent; -import android.net.INetworkAgentRegistry; -import android.net.INetworkMonitor; -import android.net.LinkProperties; -import android.net.NattKeepalivePacketData; -import android.net.Network; -import android.net.NetworkAgent; -import android.net.NetworkAgentConfig; -import android.net.NetworkCapabilities; -import android.net.NetworkInfo; -import android.net.NetworkMonitorManager; -import android.net.NetworkRequest; -import android.net.NetworkScore; -import android.net.NetworkStateSnapshot; -import android.net.QosCallbackException; -import android.net.QosFilter; -import android.net.QosFilterParcelable; -import android.net.QosSession; -import android.net.TcpKeepalivePacketData; -import android.os.Handler; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.SystemClock; -import android.telephony.data.EpsBearerQosSessionAttributes; -import android.telephony.data.NrQosSessionAttributes; -import android.util.Log; -import android.util.Pair; -import android.util.SparseArray; - -import com.android.internal.util.WakeupMessage; -import com.android.server.ConnectivityService; - -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Objects; -import java.util.SortedSet; -import java.util.TreeSet; - -/** - * A bag class used by ConnectivityService for holding a collection of most recent - * information published by a particular NetworkAgent as well as the - * AsyncChannel/messenger for reaching that NetworkAgent and lists of NetworkRequests - * interested in using it. Default sort order is descending by score. - */ -// States of a network: -// -------------------- -// 1. registered, uncreated, disconnected, unvalidated -// This state is entered when a NetworkFactory registers a NetworkAgent in any state except -// the CONNECTED state. -// 2. registered, uncreated, connecting, unvalidated -// This state is entered when a registered NetworkAgent for a VPN network transitions to the -// CONNECTING state (TODO: go through this state for every network, not just VPNs). -// ConnectivityService will tell netd to create the network early in order to add extra UID -// routing rules referencing the netID. These rules need to be in place before the network is -// connected to avoid racing against client apps trying to connect to a half-setup network. -// 3. registered, uncreated, connected, unvalidated -// This state is entered when a registered NetworkAgent transitions to the CONNECTED state. -// ConnectivityService will tell netd to create the network if it was not already created, and -// immediately transition to state #4. -// 4. registered, created, connected, unvalidated -// If this network can satisfy the default NetworkRequest, then NetworkMonitor will -// probe for Internet connectivity. -// If this network cannot satisfy the default NetworkRequest, it will immediately be -// transitioned to state #5. -// A network may remain in this state if NetworkMonitor fails to find Internet connectivity, -// for example: -// a. a captive portal is present, or -// b. a WiFi router whose Internet backhaul is down, or -// c. a wireless connection stops transfering packets temporarily (e.g. device is in elevator -// or tunnel) but does not disconnect from the AP/cell tower, or -// d. a stand-alone device offering a WiFi AP without an uplink for configuration purposes. -// 5. registered, created, connected, validated -// -// The device's default network connection: -// ---------------------------------------- -// Networks in states #4 and #5 may be used as a device's default network connection if they -// satisfy the default NetworkRequest. -// A network, that satisfies the default NetworkRequest, in state #5 should always be chosen -// in favor of a network, that satisfies the default NetworkRequest, in state #4. -// When deciding between two networks, that both satisfy the default NetworkRequest, to select -// for the default network connection, the one with the higher score should be chosen. -// -// When a network disconnects: -// --------------------------- -// If a network's transport disappears, for example: -// a. WiFi turned off, or -// b. cellular data turned off, or -// c. airplane mode is turned on, or -// d. a wireless connection disconnects from AP/cell tower entirely (e.g. device is out of range -// of AP for an extended period of time, or switches to another AP without roaming) -// then that network can transition from any state (#1-#5) to unregistered. This happens by -// the transport disconnecting their NetworkAgent's AsyncChannel with ConnectivityManager. -// ConnectivityService also tells netd to destroy the network. -// -// When ConnectivityService disconnects a network: -// ----------------------------------------------- -// If a network is just connected, ConnectivityService will think it will be used soon, but might -// not be used. Thus, a 5s timer will be held to prevent the network being torn down immediately. -// This "nascent" state is implemented by the "lingering" logic below without relating to any -// request, and is used in some cases where network requests race with network establishment. The -// nascent state ends when the 5-second timer fires, or as soon as the network satisfies a -// request, whichever is earlier. In this state, the network is considered in the background. -// -// If a network has no chance of satisfying any requests (even if it were to become validated -// and enter state #5), ConnectivityService will disconnect the NetworkAgent's AsyncChannel. -// -// If the network was satisfying a foreground NetworkRequest (i.e. had been the highest scoring that -// satisfied the NetworkRequest's constraints), but is no longer the highest scoring network for any -// foreground NetworkRequest, then there will be a 30s pause to allow network communication to be -// wrapped up rather than abruptly terminated. During this pause the network is said to be -// "lingering". During this pause if the network begins satisfying a foreground NetworkRequest, -// ConnectivityService will cancel the future disconnection of the NetworkAgent's AsyncChannel, and -// the network is no longer considered "lingering". After the linger timer expires, if the network -// is satisfying one or more background NetworkRequests it is kept up in the background. If it is -// not, ConnectivityService disconnects the NetworkAgent's AsyncChannel. -public class NetworkAgentInfo implements Comparable, NetworkRanker.Scoreable { - - @NonNull public NetworkInfo networkInfo; - // This Network object should always be used if possible, so as to encourage reuse of the - // enclosed socket factory and connection pool. Avoid creating other Network objects. - // This Network object is always valid. - @NonNull public final Network network; - @NonNull public LinkProperties linkProperties; - // This should only be modified by ConnectivityService, via setNetworkCapabilities(). - // TODO: make this private with a getter. - @NonNull public NetworkCapabilities networkCapabilities; - @NonNull public final NetworkAgentConfig networkAgentConfig; - - // Underlying networks declared by the agent. Only set if supportsUnderlyingNetworks is true. - // The networks in this list might be declared by a VPN app using setUnderlyingNetworks and are - // not guaranteed to be current or correct, or even to exist. - // - // This array is read and iterated on multiple threads with no locking so its contents must - // never be modified. When the list of networks changes, replace with a new array, on the - // handler thread. - public @Nullable volatile Network[] declaredUnderlyingNetworks; - - // The capabilities originally announced by the NetworkAgent, regardless of any capabilities - // that were added or removed due to this network's underlying networks. - // Only set if #supportsUnderlyingNetworks is true. - public @Nullable NetworkCapabilities declaredCapabilities; - - // Indicates if netd has been told to create this Network. From this point on the appropriate - // routing rules are setup and routes are added so packets can begin flowing over the Network. - // This is a sticky bit; once set it is never cleared. - public boolean created; - // Set to true after the first time this network is marked as CONNECTED. Once set, the network - // shows up in API calls, is able to satisfy NetworkRequests and can become the default network. - // This is a sticky bit; once set it is never cleared. - public boolean everConnected; - // Set to true if this Network successfully passed validation or if it did not satisfy the - // default NetworkRequest in which case validation will not be attempted. - // This is a sticky bit; once set it is never cleared even if future validation attempts fail. - public boolean everValidated; - - // The result of the last validation attempt on this network (true if validated, false if not). - public boolean lastValidated; - - // If true, becoming unvalidated will lower the network's score. This is only meaningful if the - // system is configured not to do this for certain networks, e.g., if the - // config_networkAvoidBadWifi option is set to 0 and the user has not overridden that via - // Settings.Global.NETWORK_AVOID_BAD_WIFI. - public boolean avoidUnvalidated; - - // Whether a captive portal was ever detected on this network. - // This is a sticky bit; once set it is never cleared. - public boolean everCaptivePortalDetected; - - // Whether a captive portal was found during the last network validation attempt. - public boolean lastCaptivePortalDetected; - - // Set to true when partial connectivity was detected. - public boolean partialConnectivity; - - // Delay between when the network is disconnected and when the native network is destroyed. - public int teardownDelayMs; - - // Captive portal info of the network from RFC8908, if any. - // Obtained by ConnectivityService and merged into NetworkAgent-provided information. - public CaptivePortalData capportApiData; - - // The UID of the remote entity that created this Network. - public final int creatorUid; - - // Network agent portal info of the network, if any. This information is provided from - // non-RFC8908 sources, such as Wi-Fi Passpoint, which can provide information such as Venue - // URL, Terms & Conditions URL, and network friendly name. - public CaptivePortalData networkAgentPortalData; - - // Networks are lingered when they become unneeded as a result of their NetworkRequests being - // satisfied by a higher-scoring network. so as to allow communication to wrap up before the - // network is taken down. This usually only happens to the default network. Lingering ends with - // either the linger timeout expiring and the network being taken down, or the network - // satisfying a request again. - public static class InactivityTimer implements Comparable { - public final int requestId; - public final long expiryMs; - - public InactivityTimer(int requestId, long expiryMs) { - this.requestId = requestId; - this.expiryMs = expiryMs; - } - public boolean equals(Object o) { - if (!(o instanceof InactivityTimer)) return false; - InactivityTimer other = (InactivityTimer) o; - return (requestId == other.requestId) && (expiryMs == other.expiryMs); - } - public int hashCode() { - return Objects.hash(requestId, expiryMs); - } - public int compareTo(InactivityTimer other) { - return (expiryMs != other.expiryMs) ? - Long.compare(expiryMs, other.expiryMs) : - Integer.compare(requestId, other.requestId); - } - public String toString() { - return String.format("%s, expires %dms", requestId, - expiryMs - SystemClock.elapsedRealtime()); - } - } - - /** - * Inform ConnectivityService that the network LINGER period has - * expired. - * obj = this NetworkAgentInfo - */ - public static final int EVENT_NETWORK_LINGER_COMPLETE = 1001; - - /** - * Inform ConnectivityService that the agent is half-connected. - * arg1 = ARG_AGENT_SUCCESS or ARG_AGENT_FAILURE - * obj = NetworkAgentInfo - * @hide - */ - public static final int EVENT_AGENT_REGISTERED = 1002; - - /** - * Inform ConnectivityService that the agent was disconnected. - * obj = NetworkAgentInfo - * @hide - */ - public static final int EVENT_AGENT_DISCONNECTED = 1003; - - /** - * Argument for EVENT_AGENT_HALF_CONNECTED indicating failure. - */ - public static final int ARG_AGENT_FAILURE = 0; - - /** - * Argument for EVENT_AGENT_HALF_CONNECTED indicating success. - */ - public static final int ARG_AGENT_SUCCESS = 1; - - // How long this network should linger for. - private int mLingerDurationMs; - - // All inactivity timers for this network, sorted by expiry time. A timer is added whenever - // a request is moved to a network with a better score, regardless of whether the network is or - // was lingering or not. An inactivity timer is also added when a network connects - // without immediately satisfying any requests. - // TODO: determine if we can replace this with a smaller or unsorted data structure. (e.g., - // SparseLongArray) combined with the timestamp of when the last timer is scheduled to fire. - private final SortedSet mInactivityTimers = new TreeSet<>(); - - // For fast lookups. Indexes into mInactivityTimers by request ID. - private final SparseArray mInactivityTimerForRequest = new SparseArray<>(); - - // Inactivity expiry timer. Armed whenever mInactivityTimers is non-empty, regardless of - // whether the network is inactive or not. Always set to the expiry of the mInactivityTimers - // that expires last. When the timer fires, all inactivity state is cleared, and if the network - // has no requests, it is torn down. - private WakeupMessage mInactivityMessage; - - // Inactivity expiry. Holds the expiry time of the inactivity timer, or 0 if the timer is not - // armed. - private long mInactivityExpiryMs; - - // Whether the network is inactive or not. Must be maintained separately from the above because - // it depends on the state of other networks and requests, which only ConnectivityService knows. - // (Example: we don't linger a network if it would become the best for a NetworkRequest if it - // validated). - private boolean mInactive; - - // This represents the quality of the network. As opposed to NetworkScore, FullScore includes - // the ConnectivityService-managed bits. - private FullScore mScore; - - // The list of NetworkRequests being satisfied by this Network. - private final SparseArray mNetworkRequests = new SparseArray<>(); - - // How many of the satisfied requests are actual requests and not listens. - private int mNumRequestNetworkRequests = 0; - - // How many of the satisfied requests are of type BACKGROUND_REQUEST. - private int mNumBackgroundNetworkRequests = 0; - - // The last ConnectivityReport made available for this network. This value is only null before a - // report is generated. Once non-null, it will never be null again. - @Nullable private ConnectivityReport mConnectivityReport; - - public final INetworkAgent networkAgent; - // Only accessed from ConnectivityService handler thread - private final AgentDeathMonitor mDeathMonitor = new AgentDeathMonitor(); - - public final int factorySerialNumber; - - // Used by ConnectivityService to keep track of 464xlat. - public final Nat464Xlat clatd; - - // Set after asynchronous creation of the NetworkMonitor. - private volatile NetworkMonitorManager mNetworkMonitor; - - private static final String TAG = ConnectivityService.class.getSimpleName(); - private static final boolean VDBG = false; - private final ConnectivityService mConnService; - private final Context mContext; - private final Handler mHandler; - private final QosCallbackTracker mQosCallbackTracker; - - public NetworkAgentInfo(INetworkAgent na, Network net, NetworkInfo info, - @NonNull LinkProperties lp, @NonNull NetworkCapabilities nc, - @NonNull NetworkScore score, Context context, - Handler handler, NetworkAgentConfig config, ConnectivityService connService, INetd netd, - IDnsResolver dnsResolver, int factorySerialNumber, int creatorUid, - int lingerDurationMs, QosCallbackTracker qosCallbackTracker, - ConnectivityService.Dependencies deps) { - Objects.requireNonNull(net); - Objects.requireNonNull(info); - Objects.requireNonNull(lp); - Objects.requireNonNull(nc); - Objects.requireNonNull(context); - Objects.requireNonNull(config); - Objects.requireNonNull(qosCallbackTracker); - networkAgent = na; - network = net; - networkInfo = info; - linkProperties = lp; - networkCapabilities = nc; - networkAgentConfig = config; - mConnService = connService; - setScore(score); // uses members connService, networkCapabilities and networkAgentConfig - clatd = new Nat464Xlat(this, netd, dnsResolver, deps); - mContext = context; - mHandler = handler; - this.factorySerialNumber = factorySerialNumber; - this.creatorUid = creatorUid; - mLingerDurationMs = lingerDurationMs; - mQosCallbackTracker = qosCallbackTracker; - } - - private class AgentDeathMonitor implements IBinder.DeathRecipient { - @Override - public void binderDied() { - notifyDisconnected(); - } - } - - /** - * Notify the NetworkAgent that it was registered, and should be unregistered if it dies. - * - * Must be called from the ConnectivityService handler thread. A NetworkAgent can only be - * registered once. - */ - public void notifyRegistered() { - try { - networkAgent.asBinder().linkToDeath(mDeathMonitor, 0); - networkAgent.onRegistered(new NetworkAgentMessageHandler(mHandler)); - } catch (RemoteException e) { - Log.e(TAG, "Error registering NetworkAgent", e); - maybeUnlinkDeathMonitor(); - mHandler.obtainMessage(EVENT_AGENT_REGISTERED, ARG_AGENT_FAILURE, 0, this) - .sendToTarget(); - return; - } - - mHandler.obtainMessage(EVENT_AGENT_REGISTERED, ARG_AGENT_SUCCESS, 0, this).sendToTarget(); - } - - /** - * Disconnect the NetworkAgent. Must be called from the ConnectivityService handler thread. - */ - public void disconnect() { - try { - networkAgent.onDisconnected(); - } catch (RemoteException e) { - Log.i(TAG, "Error disconnecting NetworkAgent", e); - // Fall through: it's fine if the remote has died - } - - notifyDisconnected(); - maybeUnlinkDeathMonitor(); - } - - private void maybeUnlinkDeathMonitor() { - try { - networkAgent.asBinder().unlinkToDeath(mDeathMonitor, 0); - } catch (NoSuchElementException e) { - // Was not linked: ignore - } - } - - private void notifyDisconnected() { - // Note this may be called multiple times if ConnectivityService disconnects while the - // NetworkAgent also dies. ConnectivityService ignores disconnects of already disconnected - // agents. - mHandler.obtainMessage(EVENT_AGENT_DISCONNECTED, this).sendToTarget(); - } - - /** - * Notify the NetworkAgent that bandwidth update was requested. - */ - public void onBandwidthUpdateRequested() { - try { - networkAgent.onBandwidthUpdateRequested(); - } catch (RemoteException e) { - Log.e(TAG, "Error sending bandwidth update request event", e); - } - } - - /** - * Notify the NetworkAgent that validation status has changed. - */ - public void onValidationStatusChanged(int validationStatus, @Nullable String captivePortalUrl) { - try { - networkAgent.onValidationStatusChanged(validationStatus, captivePortalUrl); - } catch (RemoteException e) { - Log.e(TAG, "Error sending validation status change event", e); - } - } - - /** - * Notify the NetworkAgent that the acceptUnvalidated setting should be saved. - */ - public void onSaveAcceptUnvalidated(boolean acceptUnvalidated) { - try { - networkAgent.onSaveAcceptUnvalidated(acceptUnvalidated); - } catch (RemoteException e) { - Log.e(TAG, "Error sending accept unvalidated event", e); - } - } - - /** - * Notify the NetworkAgent that NATT socket keepalive should be started. - */ - public void onStartNattSocketKeepalive(int slot, int intervalDurationMs, - @NonNull NattKeepalivePacketData packetData) { - try { - networkAgent.onStartNattSocketKeepalive(slot, intervalDurationMs, packetData); - } catch (RemoteException e) { - Log.e(TAG, "Error sending NATT socket keepalive start event", e); - } - } - - /** - * Notify the NetworkAgent that TCP socket keepalive should be started. - */ - public void onStartTcpSocketKeepalive(int slot, int intervalDurationMs, - @NonNull TcpKeepalivePacketData packetData) { - try { - networkAgent.onStartTcpSocketKeepalive(slot, intervalDurationMs, packetData); - } catch (RemoteException e) { - Log.e(TAG, "Error sending TCP socket keepalive start event", e); - } - } - - /** - * Notify the NetworkAgent that socket keepalive should be stopped. - */ - public void onStopSocketKeepalive(int slot) { - try { - networkAgent.onStopSocketKeepalive(slot); - } catch (RemoteException e) { - Log.e(TAG, "Error sending TCP socket keepalive stop event", e); - } - } - - /** - * Notify the NetworkAgent that signal strength thresholds should be updated. - */ - public void onSignalStrengthThresholdsUpdated(@NonNull int[] thresholds) { - try { - networkAgent.onSignalStrengthThresholdsUpdated(thresholds); - } catch (RemoteException e) { - Log.e(TAG, "Error sending signal strength thresholds event", e); - } - } - - /** - * Notify the NetworkAgent that automatic reconnect should be prevented. - */ - public void onPreventAutomaticReconnect() { - try { - networkAgent.onPreventAutomaticReconnect(); - } catch (RemoteException e) { - Log.e(TAG, "Error sending prevent automatic reconnect event", e); - } - } - - /** - * Notify the NetworkAgent that a NATT keepalive packet filter should be added. - */ - public void onAddNattKeepalivePacketFilter(int slot, - @NonNull NattKeepalivePacketData packetData) { - try { - networkAgent.onAddNattKeepalivePacketFilter(slot, packetData); - } catch (RemoteException e) { - Log.e(TAG, "Error sending add NATT keepalive packet filter event", e); - } - } - - /** - * Notify the NetworkAgent that a TCP keepalive packet filter should be added. - */ - public void onAddTcpKeepalivePacketFilter(int slot, - @NonNull TcpKeepalivePacketData packetData) { - try { - networkAgent.onAddTcpKeepalivePacketFilter(slot, packetData); - } catch (RemoteException e) { - Log.e(TAG, "Error sending add TCP keepalive packet filter event", e); - } - } - - /** - * Notify the NetworkAgent that a keepalive packet filter should be removed. - */ - public void onRemoveKeepalivePacketFilter(int slot) { - try { - networkAgent.onRemoveKeepalivePacketFilter(slot); - } catch (RemoteException e) { - Log.e(TAG, "Error sending remove keepalive packet filter event", e); - } - } - - /** - * Notify the NetworkAgent that the qos filter should be registered against the given qos - * callback id. - */ - public void onQosFilterCallbackRegistered(final int qosCallbackId, - final QosFilter qosFilter) { - try { - networkAgent.onQosFilterCallbackRegistered(qosCallbackId, - new QosFilterParcelable(qosFilter)); - } catch (final RemoteException e) { - Log.e(TAG, "Error registering a qos callback id against a qos filter", e); - } - } - - /** - * Notify the NetworkAgent that the given qos callback id should be unregistered. - */ - public void onQosCallbackUnregistered(final int qosCallbackId) { - try { - networkAgent.onQosCallbackUnregistered(qosCallbackId); - } catch (RemoteException e) { - Log.e(TAG, "Error unregistering a qos callback id", e); - } - } - - /** - * Notify the NetworkAgent that the network is successfully connected. - */ - public void onNetworkCreated() { - try { - networkAgent.onNetworkCreated(); - } catch (RemoteException e) { - Log.e(TAG, "Error sending network created event", e); - } - } - - /** - * Notify the NetworkAgent that the native network has been destroyed. - */ - public void onNetworkDestroyed() { - try { - networkAgent.onNetworkDestroyed(); - } catch (RemoteException e) { - Log.e(TAG, "Error sending network destroyed event", e); - } - } - - // TODO: consider moving out of NetworkAgentInfo into its own class - private class NetworkAgentMessageHandler extends INetworkAgentRegistry.Stub { - private final Handler mHandler; - - private NetworkAgentMessageHandler(Handler handler) { - mHandler = handler; - } - - @Override - public void sendNetworkCapabilities(@NonNull NetworkCapabilities nc) { - Objects.requireNonNull(nc); - mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_CAPABILITIES_CHANGED, - new Pair<>(NetworkAgentInfo.this, nc)).sendToTarget(); - } - - @Override - public void sendLinkProperties(@NonNull LinkProperties lp) { - Objects.requireNonNull(lp); - mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED, - new Pair<>(NetworkAgentInfo.this, lp)).sendToTarget(); - } - - @Override - public void sendNetworkInfo(@NonNull NetworkInfo info) { - Objects.requireNonNull(info); - mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_INFO_CHANGED, - new Pair<>(NetworkAgentInfo.this, info)).sendToTarget(); - } - - @Override - public void sendScore(@NonNull final NetworkScore score) { - mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_SCORE_CHANGED, - new Pair<>(NetworkAgentInfo.this, score)).sendToTarget(); - } - - @Override - public void sendExplicitlySelected(boolean explicitlySelected, boolean acceptPartial) { - mHandler.obtainMessage(NetworkAgent.EVENT_SET_EXPLICITLY_SELECTED, - explicitlySelected ? 1 : 0, acceptPartial ? 1 : 0, - new Pair<>(NetworkAgentInfo.this, null)).sendToTarget(); - } - - @Override - public void sendSocketKeepaliveEvent(int slot, int reason) { - mHandler.obtainMessage(NetworkAgent.EVENT_SOCKET_KEEPALIVE, - slot, reason, new Pair<>(NetworkAgentInfo.this, null)).sendToTarget(); - } - - @Override - public void sendUnderlyingNetworks(@Nullable List networks) { - mHandler.obtainMessage(NetworkAgent.EVENT_UNDERLYING_NETWORKS_CHANGED, - new Pair<>(NetworkAgentInfo.this, networks)).sendToTarget(); - } - - @Override - public void sendEpsQosSessionAvailable(final int qosCallbackId, final QosSession session, - final EpsBearerQosSessionAttributes attributes) { - mQosCallbackTracker.sendEventEpsQosSessionAvailable(qosCallbackId, session, attributes); - } - - @Override - public void sendNrQosSessionAvailable(final int qosCallbackId, final QosSession session, - final NrQosSessionAttributes attributes) { - mQosCallbackTracker.sendEventNrQosSessionAvailable(qosCallbackId, session, attributes); - } - - @Override - public void sendQosSessionLost(final int qosCallbackId, final QosSession session) { - mQosCallbackTracker.sendEventQosSessionLost(qosCallbackId, session); - } - - @Override - public void sendQosCallbackError(final int qosCallbackId, - @QosCallbackException.ExceptionType final int exceptionType) { - mQosCallbackTracker.sendEventQosCallbackError(qosCallbackId, exceptionType); - } - - @Override - public void sendTeardownDelayMs(int teardownDelayMs) { - mHandler.obtainMessage(NetworkAgent.EVENT_TEARDOWN_DELAY_CHANGED, - teardownDelayMs, 0, new Pair<>(NetworkAgentInfo.this, null)).sendToTarget(); - } - - @Override - public void sendLingerDuration(final int durationMs) { - mHandler.obtainMessage(NetworkAgent.EVENT_LINGER_DURATION_CHANGED, - new Pair<>(NetworkAgentInfo.this, durationMs)).sendToTarget(); - } - } - - /** - * Inform NetworkAgentInfo that a new NetworkMonitor was created. - */ - public void onNetworkMonitorCreated(INetworkMonitor networkMonitor) { - mNetworkMonitor = new NetworkMonitorManager(networkMonitor); - } - - /** - * Set the NetworkCapabilities on this NetworkAgentInfo. Also attempts to notify NetworkMonitor - * of the new capabilities, if NetworkMonitor has been created. - * - *

      If {@link NetworkMonitor#notifyNetworkCapabilitiesChanged(NetworkCapabilities)} fails, - * the exception is logged but not reported to callers. - * - * @return the old capabilities of this network. - */ - @NonNull public synchronized NetworkCapabilities getAndSetNetworkCapabilities( - @NonNull final NetworkCapabilities nc) { - final NetworkCapabilities oldNc = networkCapabilities; - networkCapabilities = nc; - mScore = mScore.mixInScore(networkCapabilities, networkAgentConfig, everValidatedForYield(), - yieldToBadWiFi()); - final NetworkMonitorManager nm = mNetworkMonitor; - if (nm != null) { - nm.notifyNetworkCapabilitiesChanged(nc); - } - return oldNc; - } - - private boolean yieldToBadWiFi() { - // Only cellular networks yield to bad wifi - return networkCapabilities.hasTransport(TRANSPORT_CELLULAR) && !mConnService.avoidBadWifi(); - } - - public ConnectivityService connService() { - return mConnService; - } - - public NetworkAgentConfig netAgentConfig() { - return networkAgentConfig; - } - - public Handler handler() { - return mHandler; - } - - public Network network() { - return network; - } - - /** - * Get the NetworkMonitorManager in this NetworkAgentInfo. - * - *

      This will be null before {@link #onNetworkMonitorCreated(INetworkMonitor)} is called. - */ - public NetworkMonitorManager networkMonitor() { - return mNetworkMonitor; - } - - // Functions for manipulating the requests satisfied by this network. - // - // These functions must only called on ConnectivityService's main thread. - - private static final boolean ADD = true; - private static final boolean REMOVE = false; - - private void updateRequestCounts(boolean add, NetworkRequest request) { - int delta = add ? +1 : -1; - switch (request.type) { - case REQUEST: - mNumRequestNetworkRequests += delta; - break; - - case BACKGROUND_REQUEST: - mNumRequestNetworkRequests += delta; - mNumBackgroundNetworkRequests += delta; - break; - - case LISTEN: - case LISTEN_FOR_BEST: - case TRACK_DEFAULT: - case TRACK_SYSTEM_DEFAULT: - break; - - case NONE: - default: - Log.wtf(TAG, "Unhandled request type " + request.type); - break; - } - } - - /** - * Add {@code networkRequest} to this network as it's satisfied by this network. - * @return true if {@code networkRequest} was added or false if {@code networkRequest} was - * already present. - */ - public boolean addRequest(NetworkRequest networkRequest) { - NetworkRequest existing = mNetworkRequests.get(networkRequest.requestId); - if (existing == networkRequest) return false; - if (existing != null) { - // Should only happen if the requestId wraps. If that happens lots of other things will - // be broken as well. - Log.wtf(TAG, String.format("Duplicate requestId for %s and %s on %s", - networkRequest, existing, toShortString())); - updateRequestCounts(REMOVE, existing); - } - mNetworkRequests.put(networkRequest.requestId, networkRequest); - updateRequestCounts(ADD, networkRequest); - return true; - } - - /** - * Remove the specified request from this network. - */ - public void removeRequest(int requestId) { - NetworkRequest existing = mNetworkRequests.get(requestId); - if (existing == null) return; - updateRequestCounts(REMOVE, existing); - mNetworkRequests.remove(requestId); - if (existing.isRequest()) { - unlingerRequest(existing.requestId); - } - } - - /** - * Returns whether this network is currently satisfying the request with the specified ID. - */ - public boolean isSatisfyingRequest(int id) { - return mNetworkRequests.get(id) != null; - } - - /** - * Returns the request at the specified position in the list of requests satisfied by this - * network. - */ - public NetworkRequest requestAt(int index) { - return mNetworkRequests.valueAt(index); - } - - /** - * Returns the number of requests currently satisfied by this network for which - * {@link android.net.NetworkRequest#isRequest} returns {@code true}. - */ - public int numRequestNetworkRequests() { - return mNumRequestNetworkRequests; - } - - /** - * Returns the number of requests currently satisfied by this network of type - * {@link android.net.NetworkRequest.Type.BACKGROUND_REQUEST}. - */ - public int numBackgroundNetworkRequests() { - return mNumBackgroundNetworkRequests; - } - - /** - * Returns the number of foreground requests currently satisfied by this network. - */ - public int numForegroundNetworkRequests() { - return mNumRequestNetworkRequests - mNumBackgroundNetworkRequests; - } - - /** - * Returns the number of requests of any type currently satisfied by this network. - */ - public int numNetworkRequests() { - return mNetworkRequests.size(); - } - - /** - * Returns whether the network is a background network. A network is a background network if it - * does not have the NET_CAPABILITY_FOREGROUND capability, which implies it is satisfying no - * foreground request, is not lingering (i.e. kept for a while after being outscored), and is - * not a speculative network (i.e. kept pending validation when validation would have it - * outscore another foreground network). That implies it is being kept up by some background - * request (otherwise it would be torn down), maybe the mobile always-on request. - */ - public boolean isBackgroundNetwork() { - return !isVPN() && numForegroundNetworkRequests() == 0 && mNumBackgroundNetworkRequests > 0 - && !isLingering(); - } - - // Does this network satisfy request? - public boolean satisfies(NetworkRequest request) { - return created && - request.networkCapabilities.satisfiedByNetworkCapabilities(networkCapabilities); - } - - public boolean satisfiesImmutableCapabilitiesOf(NetworkRequest request) { - return created && - request.networkCapabilities.satisfiedByImmutableNetworkCapabilities( - networkCapabilities); - } - - /** Whether this network is a VPN. */ - public boolean isVPN() { - return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN); - } - - /** Whether this network might have underlying networks. Currently only true for VPNs. */ - public boolean supportsUnderlyingNetworks() { - return isVPN(); - } - - // Caller must not mutate. This method is called frequently and making a defensive copy - // would be too expensive. This is used by NetworkRanker.Scoreable, so it can be compared - // against other scoreables. - @Override public NetworkCapabilities getCapsNoCopy() { - return networkCapabilities; - } - - // NetworkRanker.Scoreable - @Override public FullScore getScore() { - return mScore; - } - - // Get the current score for this Network. This may be modified from what the - // NetworkAgent sent, as it has modifiers applied to it. - public int getCurrentScore() { - return mScore.getLegacyInt(); - } - - // Get the current score for this Network as if it was validated. This may be modified from - // what the NetworkAgent sent, as it has modifiers applied to it. - public int getCurrentScoreAsValidated() { - return mScore.getLegacyIntAsValidated(); - } - - /** - * Mix-in the ConnectivityService-managed bits in the score. - */ - public void setScore(final NetworkScore score) { - mScore = FullScore.fromNetworkScore(score, networkCapabilities, networkAgentConfig, - everValidatedForYield(), yieldToBadWiFi()); - } - - /** - * Update the ConnectivityService-managed bits in the score. - * - * Call this after updating the network agent config. - */ - public void updateScoreForNetworkAgentUpdate() { - mScore = mScore.mixInScore(networkCapabilities, networkAgentConfig, - everValidatedForYield(), yieldToBadWiFi()); - } - - private boolean everValidatedForYield() { - return everValidated && !avoidUnvalidated; - } - - /** - * Returns a Scoreable identical to this NAI, but validated. - * - * This is useful to probe what scoring would be if this network validated, to know - * whether to provisionally keep a network that may or may not validate. - * - * @return a Scoreable identical to this NAI, but validated. - */ - public NetworkRanker.Scoreable getValidatedScoreable() { - return new NetworkRanker.Scoreable() { - @Override public FullScore getScore() { - return mScore.asValidated(); - } - - @Override public NetworkCapabilities getCapsNoCopy() { - return networkCapabilities; - } - }; - } - - /** - * Return a {@link NetworkStateSnapshot} for this network. - */ - @NonNull - public NetworkStateSnapshot getNetworkStateSnapshot() { - synchronized (this) { - // Network objects are outwardly immutable so there is no point in duplicating. - // Duplicating also precludes sharing socket factories and connection pools. - final String subscriberId = (networkAgentConfig != null) - ? networkAgentConfig.subscriberId : null; - return new NetworkStateSnapshot(network, new NetworkCapabilities(networkCapabilities), - new LinkProperties(linkProperties), subscriberId, networkInfo.getType()); - } - } - - /** - * Sets the specified requestId to linger on this network for the specified time. Called by - * ConnectivityService when any request is moved to another network with a higher score, or - * when a network is newly created. - * - * @param requestId The requestId of the request that no longer need to be served by this - * network. Or {@link NetworkRequest.REQUEST_ID_NONE} if this is the - * {@code InactivityTimer} for a newly created network. - */ - // TODO: Consider creating a dedicated function for nascent network, e.g. start/stopNascent. - public void lingerRequest(int requestId, long now, long duration) { - if (mInactivityTimerForRequest.get(requestId) != null) { - // Cannot happen. Once a request is lingering on a particular network, we cannot - // re-linger it unless that network becomes the best for that request again, in which - // case we should have unlingered it. - Log.wtf(TAG, toShortString() + ": request " + requestId + " already lingered"); - } - final long expiryMs = now + duration; - InactivityTimer timer = new InactivityTimer(requestId, expiryMs); - if (VDBG) Log.d(TAG, "Adding InactivityTimer " + timer + " to " + toShortString()); - mInactivityTimers.add(timer); - mInactivityTimerForRequest.put(requestId, timer); - } - - /** - * Sets the specified requestId to linger on this network for the timeout set when - * initializing or modified by {@link #setLingerDuration(int)}. Called by - * ConnectivityService when any request is moved to another network with a higher score. - * - * @param requestId The requestId of the request that no longer need to be served by this - * network. - * @param now current system timestamp obtained by {@code SystemClock.elapsedRealtime}. - */ - public void lingerRequest(int requestId, long now) { - lingerRequest(requestId, now, mLingerDurationMs); - } - - /** - * Cancel lingering. Called by ConnectivityService when a request is added to this network. - * Returns true if the given requestId was lingering on this network, false otherwise. - */ - public boolean unlingerRequest(int requestId) { - InactivityTimer timer = mInactivityTimerForRequest.get(requestId); - if (timer != null) { - if (VDBG) { - Log.d(TAG, "Removing InactivityTimer " + timer + " from " + toShortString()); - } - mInactivityTimers.remove(timer); - mInactivityTimerForRequest.remove(requestId); - return true; - } - return false; - } - - public long getInactivityExpiry() { - return mInactivityExpiryMs; - } - - public void updateInactivityTimer() { - long newExpiry = mInactivityTimers.isEmpty() ? 0 : mInactivityTimers.last().expiryMs; - if (newExpiry == mInactivityExpiryMs) return; - - // Even if we're going to reschedule the timer, cancel it first. This is because the - // semantics of WakeupMessage guarantee that if cancel is called then the alarm will - // never call its callback (handleLingerComplete), even if it has already fired. - // WakeupMessage makes no such guarantees about rescheduling a message, so if mLingerMessage - // has already been dispatched, rescheduling to some time in the future won't stop it - // from calling its callback immediately. - if (mInactivityMessage != null) { - mInactivityMessage.cancel(); - mInactivityMessage = null; - } - - if (newExpiry > 0) { - // If the newExpiry timestamp is in the past, the wakeup message will fire immediately. - mInactivityMessage = new WakeupMessage( - mContext, mHandler, - "NETWORK_LINGER_COMPLETE." + network.getNetId() /* cmdName */, - EVENT_NETWORK_LINGER_COMPLETE /* cmd */, - 0 /* arg1 (unused) */, 0 /* arg2 (unused) */, - this /* obj (NetworkAgentInfo) */); - mInactivityMessage.schedule(newExpiry); - } - - mInactivityExpiryMs = newExpiry; - } - - public void setInactive() { - mInactive = true; - } - - public void unsetInactive() { - mInactive = false; - } - - public boolean isInactive() { - return mInactive; - } - - public boolean isLingering() { - return mInactive && !isNascent(); - } - - /** - * Set the linger duration for this NAI. - * @param durationMs The new linger duration, in milliseconds. - */ - public void setLingerDuration(final int durationMs) { - final long diff = durationMs - mLingerDurationMs; - final ArrayList newTimers = new ArrayList<>(); - for (final InactivityTimer timer : mInactivityTimers) { - if (timer.requestId == NetworkRequest.REQUEST_ID_NONE) { - // Don't touch nascent timer, re-add as is. - newTimers.add(timer); - } else { - newTimers.add(new InactivityTimer(timer.requestId, timer.expiryMs + diff)); - } - } - mInactivityTimers.clear(); - mInactivityTimers.addAll(newTimers); - updateInactivityTimer(); - mLingerDurationMs = durationMs; - } - - /** - * Return whether the network satisfies no request, but is still being kept up - * because it has just connected less than - * {@code ConnectivityService#DEFAULT_NASCENT_DELAY_MS}ms ago and is thus still considered - * nascent. Note that nascent mechanism uses inactivity timer which isn't - * associated with a request. Thus, use {@link NetworkRequest#REQUEST_ID_NONE} to identify it. - * - */ - public boolean isNascent() { - return mInactive && mInactivityTimers.size() == 1 - && mInactivityTimers.first().requestId == NetworkRequest.REQUEST_ID_NONE; - } - - public void clearInactivityState() { - if (mInactivityMessage != null) { - mInactivityMessage.cancel(); - mInactivityMessage = null; - } - mInactivityTimers.clear(); - mInactivityTimerForRequest.clear(); - // Sets mInactivityExpiryMs, cancels and nulls out mInactivityMessage. - updateInactivityTimer(); - mInactive = false; - } - - public void dumpInactivityTimers(PrintWriter pw) { - for (InactivityTimer timer : mInactivityTimers) { - pw.println(timer); - } - } - - /** - * Sets the most recent ConnectivityReport for this network. - * - *

      This should only be called from the ConnectivityService thread. - * - * @hide - */ - public void setConnectivityReport(@NonNull ConnectivityReport connectivityReport) { - mConnectivityReport = connectivityReport; - } - - /** - * Returns the most recent ConnectivityReport for this network, or null if none have been - * reported yet. - * - *

      This should only be called from the ConnectivityService thread. - * - * @hide - */ - @Nullable - public ConnectivityReport getConnectivityReport() { - return mConnectivityReport; - } - - // TODO: Print shorter members first and only print the boolean variable which value is true - // to improve readability. - public String toString() { - return "NetworkAgentInfo{" - + "network{" + network + "} handle{" + network.getNetworkHandle() + "} ni{" - + networkInfo.toShortString() + "} " - + mScore + " " - + (isNascent() ? " nascent" : (isLingering() ? " lingering" : "")) - + (everValidated ? " everValidated" : "") - + (lastValidated ? " lastValidated" : "") - + (partialConnectivity ? " partialConnectivity" : "") - + (everCaptivePortalDetected ? " everCaptivePortal" : "") - + (lastCaptivePortalDetected ? " isCaptivePortal" : "") - + (networkAgentConfig.explicitlySelected ? " explicitlySelected" : "") - + (networkAgentConfig.acceptUnvalidated ? " acceptUnvalidated" : "") - + (networkAgentConfig.acceptPartialConnectivity ? " acceptPartialConnectivity" : "") - + (clatd.isStarted() ? " clat{" + clatd + "} " : "") - + (declaredUnderlyingNetworks != null - ? " underlying{" + Arrays.toString(declaredUnderlyingNetworks) + "}" : "") - + " lp{" + linkProperties + "}" - + " nc{" + networkCapabilities + "}" - + "}"; - } - - /** - * Show a short string representing a Network. - * - * This is often not enough for debugging purposes for anything complex, but the full form - * is very long and hard to read, so this is useful when there isn't a lot of ambiguity. - * This represents the network with something like "[100 WIFI|VPN]" or "[108 MOBILE]". - */ - public String toShortString() { - return "[" + network.getNetId() + " " - + transportNamesOf(networkCapabilities.getTransportTypes()) + "]"; - } - - // Enables sorting in descending order of score. - @Override - public int compareTo(NetworkAgentInfo other) { - return other.getCurrentScore() - getCurrentScore(); - } - - /** - * Null-guarding version of NetworkAgentInfo#toShortString() - */ - @NonNull - public static String toShortString(@Nullable final NetworkAgentInfo nai) { - return null != nai ? nai.toShortString() : "[null]"; - } -} diff --git a/packages/Connectivity/service/src/com/android/server/connectivity/NetworkDiagnostics.java b/packages/Connectivity/service/src/com/android/server/connectivity/NetworkDiagnostics.java deleted file mode 100644 index 2e51be39bfae3..0000000000000 --- a/packages/Connectivity/service/src/com/android/server/connectivity/NetworkDiagnostics.java +++ /dev/null @@ -1,757 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import static android.system.OsConstants.*; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.net.InetAddresses; -import android.net.LinkAddress; -import android.net.LinkProperties; -import android.net.Network; -import android.net.RouteInfo; -import android.net.TrafficStats; -import android.net.shared.PrivateDnsConfig; -import android.net.util.NetworkConstants; -import android.os.SystemClock; -import android.system.ErrnoException; -import android.system.Os; -import android.system.StructTimeval; -import android.text.TextUtils; -import android.util.Pair; - -import com.android.internal.util.IndentingPrintWriter; -import com.android.net.module.util.NetworkStackConstants; - -import libcore.io.IoUtils; - -import java.io.Closeable; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.FileDescriptor; -import java.io.IOException; -import java.io.InterruptedIOException; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.NetworkInterface; -import java.net.SocketAddress; -import java.net.SocketException; -import java.net.UnknownHostException; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import javax.net.ssl.SNIHostName; -import javax.net.ssl.SNIServerName; -import javax.net.ssl.SSLParameters; -import javax.net.ssl.SSLSocket; -import javax.net.ssl.SSLSocketFactory; - -/** - * NetworkDiagnostics - * - * A simple class to diagnose network connectivity fundamentals. Current - * checks performed are: - * - ICMPv4/v6 echo requests for all routers - * - ICMPv4/v6 echo requests for all DNS servers - * - DNS UDP queries to all DNS servers - * - * Currently unimplemented checks include: - * - report ARP/ND data about on-link neighbors - * - DNS TCP queries to all DNS servers - * - HTTP DIRECT and PROXY checks - * - port 443 blocking/TLS intercept checks - * - QUIC reachability checks - * - MTU checks - * - * The supplied timeout bounds the entire diagnostic process. Each specific - * check class must implement this upper bound on measurements in whichever - * manner is most appropriate and effective. - * - * @hide - */ -public class NetworkDiagnostics { - private static final String TAG = "NetworkDiagnostics"; - - private static final InetAddress TEST_DNS4 = InetAddresses.parseNumericAddress("8.8.8.8"); - private static final InetAddress TEST_DNS6 = InetAddresses.parseNumericAddress( - "2001:4860:4860::8888"); - - // For brevity elsewhere. - private static final long now() { - return SystemClock.elapsedRealtime(); - } - - // Values from RFC 1035 section 4.1.1, names from . - // Should be a member of DnsUdpCheck, but "compiler says no". - public static enum DnsResponseCode { NOERROR, FORMERR, SERVFAIL, NXDOMAIN, NOTIMP, REFUSED }; - - private final Network mNetwork; - private final LinkProperties mLinkProperties; - private final PrivateDnsConfig mPrivateDnsCfg; - private final Integer mInterfaceIndex; - - private final long mTimeoutMs; - private final long mStartTime; - private final long mDeadlineTime; - - // A counter, initialized to the total number of measurements, - // so callers can wait for completion. - private final CountDownLatch mCountDownLatch; - - public class Measurement { - private static final String SUCCEEDED = "SUCCEEDED"; - private static final String FAILED = "FAILED"; - - private boolean succeeded; - - // Package private. TODO: investigate better encapsulation. - String description = ""; - long startTime; - long finishTime; - String result = ""; - Thread thread; - - public boolean checkSucceeded() { return succeeded; } - - void recordSuccess(String msg) { - maybeFixupTimes(); - succeeded = true; - result = SUCCEEDED + ": " + msg; - if (mCountDownLatch != null) { - mCountDownLatch.countDown(); - } - } - - void recordFailure(String msg) { - maybeFixupTimes(); - succeeded = false; - result = FAILED + ": " + msg; - if (mCountDownLatch != null) { - mCountDownLatch.countDown(); - } - } - - private void maybeFixupTimes() { - // Allows the caller to just set success/failure and not worry - // about also setting the correct finishing time. - if (finishTime == 0) { finishTime = now(); } - - // In cases where, for example, a failure has occurred before the - // measurement even began, fixup the start time to reflect as much. - if (startTime == 0) { startTime = finishTime; } - } - - @Override - public String toString() { - return description + ": " + result + " (" + (finishTime - startTime) + "ms)"; - } - } - - private final Map mIcmpChecks = new HashMap<>(); - private final Map, Measurement> mExplicitSourceIcmpChecks = - new HashMap<>(); - private final Map mDnsUdpChecks = new HashMap<>(); - private final Map mDnsTlsChecks = new HashMap<>(); - private final String mDescription; - - - public NetworkDiagnostics(Network network, LinkProperties lp, - @NonNull PrivateDnsConfig privateDnsCfg, long timeoutMs) { - mNetwork = network; - mLinkProperties = lp; - mPrivateDnsCfg = privateDnsCfg; - mInterfaceIndex = getInterfaceIndex(mLinkProperties.getInterfaceName()); - mTimeoutMs = timeoutMs; - mStartTime = now(); - mDeadlineTime = mStartTime + mTimeoutMs; - - // Hardcode measurements to TEST_DNS4 and TEST_DNS6 in order to test off-link connectivity. - // We are free to modify mLinkProperties with impunity because ConnectivityService passes us - // a copy and not the original object. It's easier to do it this way because we don't need - // to check whether the LinkProperties already contains these DNS servers because - // LinkProperties#addDnsServer checks for duplicates. - if (mLinkProperties.isReachable(TEST_DNS4)) { - mLinkProperties.addDnsServer(TEST_DNS4); - } - // TODO: we could use mLinkProperties.isReachable(TEST_DNS6) here, because we won't set any - // DNS servers for which isReachable() is false, but since this is diagnostic code, be extra - // careful. - if (mLinkProperties.hasGlobalIpv6Address() || mLinkProperties.hasIpv6DefaultRoute()) { - mLinkProperties.addDnsServer(TEST_DNS6); - } - - for (RouteInfo route : mLinkProperties.getRoutes()) { - if (route.hasGateway()) { - InetAddress gateway = route.getGateway(); - prepareIcmpMeasurement(gateway); - if (route.isIPv6Default()) { - prepareExplicitSourceIcmpMeasurements(gateway); - } - } - } - for (InetAddress nameserver : mLinkProperties.getDnsServers()) { - prepareIcmpMeasurement(nameserver); - prepareDnsMeasurement(nameserver); - - // Unlike the DnsResolver which doesn't do certificate validation in opportunistic mode, - // DoT probes to the DNS servers will fail if certificate validation fails. - prepareDnsTlsMeasurement(null /* hostname */, nameserver); - } - - for (InetAddress tlsNameserver : mPrivateDnsCfg.ips) { - // Reachability check is necessary since when resolving the strict mode hostname, - // NetworkMonitor always queries for both A and AAAA records, even if the network - // is IPv4-only or IPv6-only. - if (mLinkProperties.isReachable(tlsNameserver)) { - // If there are IPs, there must have been a name that resolved to them. - prepareDnsTlsMeasurement(mPrivateDnsCfg.hostname, tlsNameserver); - } - } - - mCountDownLatch = new CountDownLatch(totalMeasurementCount()); - - startMeasurements(); - - mDescription = "ifaces{" + TextUtils.join(",", mLinkProperties.getAllInterfaceNames()) + "}" - + " index{" + mInterfaceIndex + "}" - + " network{" + mNetwork + "}" - + " nethandle{" + mNetwork.getNetworkHandle() + "}"; - } - - private static Integer getInterfaceIndex(String ifname) { - try { - NetworkInterface ni = NetworkInterface.getByName(ifname); - return ni.getIndex(); - } catch (NullPointerException | SocketException e) { - return null; - } - } - - private static String socketAddressToString(@NonNull SocketAddress sockAddr) { - // The default toString() implementation is not the prettiest. - InetSocketAddress inetSockAddr = (InetSocketAddress) sockAddr; - InetAddress localAddr = inetSockAddr.getAddress(); - return String.format( - (localAddr instanceof Inet6Address ? "[%s]:%d" : "%s:%d"), - localAddr.getHostAddress(), inetSockAddr.getPort()); - } - - private void prepareIcmpMeasurement(InetAddress target) { - if (!mIcmpChecks.containsKey(target)) { - Measurement measurement = new Measurement(); - measurement.thread = new Thread(new IcmpCheck(target, measurement)); - mIcmpChecks.put(target, measurement); - } - } - - private void prepareExplicitSourceIcmpMeasurements(InetAddress target) { - for (LinkAddress l : mLinkProperties.getLinkAddresses()) { - InetAddress source = l.getAddress(); - if (source instanceof Inet6Address && l.isGlobalPreferred()) { - Pair srcTarget = new Pair<>(source, target); - if (!mExplicitSourceIcmpChecks.containsKey(srcTarget)) { - Measurement measurement = new Measurement(); - measurement.thread = new Thread(new IcmpCheck(source, target, measurement)); - mExplicitSourceIcmpChecks.put(srcTarget, measurement); - } - } - } - } - - private void prepareDnsMeasurement(InetAddress target) { - if (!mDnsUdpChecks.containsKey(target)) { - Measurement measurement = new Measurement(); - measurement.thread = new Thread(new DnsUdpCheck(target, measurement)); - mDnsUdpChecks.put(target, measurement); - } - } - - private void prepareDnsTlsMeasurement(@Nullable String hostname, @NonNull InetAddress target) { - // This might overwrite an existing entry in mDnsTlsChecks, because |target| can be an IP - // address configured by the network as well as an IP address learned by resolving the - // strict mode DNS hostname. If the entry is overwritten, the overwritten measurement - // thread will not execute. - Measurement measurement = new Measurement(); - measurement.thread = new Thread(new DnsTlsCheck(hostname, target, measurement)); - mDnsTlsChecks.put(target, measurement); - } - - private int totalMeasurementCount() { - return mIcmpChecks.size() + mExplicitSourceIcmpChecks.size() + mDnsUdpChecks.size() - + mDnsTlsChecks.size(); - } - - private void startMeasurements() { - for (Measurement measurement : mIcmpChecks.values()) { - measurement.thread.start(); - } - for (Measurement measurement : mExplicitSourceIcmpChecks.values()) { - measurement.thread.start(); - } - for (Measurement measurement : mDnsUdpChecks.values()) { - measurement.thread.start(); - } - for (Measurement measurement : mDnsTlsChecks.values()) { - measurement.thread.start(); - } - } - - public void waitForMeasurements() { - try { - mCountDownLatch.await(mDeadlineTime - now(), TimeUnit.MILLISECONDS); - } catch (InterruptedException ignored) {} - } - - public List getMeasurements() { - // TODO: Consider moving waitForMeasurements() in here to minimize the - // chance of caller errors. - - ArrayList measurements = new ArrayList(totalMeasurementCount()); - - // Sort measurements IPv4 first. - for (Map.Entry entry : mIcmpChecks.entrySet()) { - if (entry.getKey() instanceof Inet4Address) { - measurements.add(entry.getValue()); - } - } - for (Map.Entry, Measurement> entry : - mExplicitSourceIcmpChecks.entrySet()) { - if (entry.getKey().first instanceof Inet4Address) { - measurements.add(entry.getValue()); - } - } - for (Map.Entry entry : mDnsUdpChecks.entrySet()) { - if (entry.getKey() instanceof Inet4Address) { - measurements.add(entry.getValue()); - } - } - for (Map.Entry entry : mDnsTlsChecks.entrySet()) { - if (entry.getKey() instanceof Inet4Address) { - measurements.add(entry.getValue()); - } - } - - // IPv6 measurements second. - for (Map.Entry entry : mIcmpChecks.entrySet()) { - if (entry.getKey() instanceof Inet6Address) { - measurements.add(entry.getValue()); - } - } - for (Map.Entry, Measurement> entry : - mExplicitSourceIcmpChecks.entrySet()) { - if (entry.getKey().first instanceof Inet6Address) { - measurements.add(entry.getValue()); - } - } - for (Map.Entry entry : mDnsUdpChecks.entrySet()) { - if (entry.getKey() instanceof Inet6Address) { - measurements.add(entry.getValue()); - } - } - for (Map.Entry entry : mDnsTlsChecks.entrySet()) { - if (entry.getKey() instanceof Inet6Address) { - measurements.add(entry.getValue()); - } - } - - return measurements; - } - - public void dump(IndentingPrintWriter pw) { - pw.println(TAG + ":" + mDescription); - final long unfinished = mCountDownLatch.getCount(); - if (unfinished > 0) { - // This can't happen unless a caller forgets to call waitForMeasurements() - // or a measurement isn't implemented to correctly honor the timeout. - pw.println("WARNING: countdown wait incomplete: " - + unfinished + " unfinished measurements"); - } - - pw.increaseIndent(); - - String prefix; - for (Measurement m : getMeasurements()) { - prefix = m.checkSucceeded() ? "." : "F"; - pw.println(prefix + " " + m.toString()); - } - - pw.decreaseIndent(); - } - - - private class SimpleSocketCheck implements Closeable { - protected final InetAddress mSource; // Usually null. - protected final InetAddress mTarget; - protected final int mAddressFamily; - protected final Measurement mMeasurement; - protected FileDescriptor mFileDescriptor; - protected SocketAddress mSocketAddress; - - protected SimpleSocketCheck( - InetAddress source, InetAddress target, Measurement measurement) { - mMeasurement = measurement; - - if (target instanceof Inet6Address) { - Inet6Address targetWithScopeId = null; - if (target.isLinkLocalAddress() && mInterfaceIndex != null) { - try { - targetWithScopeId = Inet6Address.getByAddress( - null, target.getAddress(), mInterfaceIndex); - } catch (UnknownHostException e) { - mMeasurement.recordFailure(e.toString()); - } - } - mTarget = (targetWithScopeId != null) ? targetWithScopeId : target; - mAddressFamily = AF_INET6; - } else { - mTarget = target; - mAddressFamily = AF_INET; - } - - // We don't need to check the scope ID here because we currently only do explicit-source - // measurements from global IPv6 addresses. - mSource = source; - } - - protected SimpleSocketCheck(InetAddress target, Measurement measurement) { - this(null, target, measurement); - } - - protected void setupSocket( - int sockType, int protocol, long writeTimeout, long readTimeout, int dstPort) - throws ErrnoException, IOException { - final int oldTag = TrafficStats.getAndSetThreadStatsTag( - NetworkStackConstants.TAG_SYSTEM_PROBE); - try { - mFileDescriptor = Os.socket(mAddressFamily, sockType, protocol); - } finally { - // TODO: The tag should remain set until all traffic is sent and received. - // Consider tagging the socket after the measurement thread is started. - TrafficStats.setThreadStatsTag(oldTag); - } - // Setting SNDTIMEO is purely for defensive purposes. - Os.setsockoptTimeval(mFileDescriptor, - SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(writeTimeout)); - Os.setsockoptTimeval(mFileDescriptor, - SOL_SOCKET, SO_RCVTIMEO, StructTimeval.fromMillis(readTimeout)); - // TODO: Use IP_RECVERR/IPV6_RECVERR, pending OsContants availability. - mNetwork.bindSocket(mFileDescriptor); - if (mSource != null) { - Os.bind(mFileDescriptor, mSource, 0); - } - Os.connect(mFileDescriptor, mTarget, dstPort); - mSocketAddress = Os.getsockname(mFileDescriptor); - } - - protected boolean ensureMeasurementNecessary() { - if (mMeasurement.finishTime == 0) return false; - - // Countdown latch was not decremented when the measurement failed during setup. - mCountDownLatch.countDown(); - return true; - } - - @Override - public void close() { - IoUtils.closeQuietly(mFileDescriptor); - } - } - - - private class IcmpCheck extends SimpleSocketCheck implements Runnable { - private static final int TIMEOUT_SEND = 100; - private static final int TIMEOUT_RECV = 300; - private static final int PACKET_BUFSIZE = 512; - private final int mProtocol; - private final int mIcmpType; - - public IcmpCheck(InetAddress source, InetAddress target, Measurement measurement) { - super(source, target, measurement); - - if (mAddressFamily == AF_INET6) { - mProtocol = IPPROTO_ICMPV6; - mIcmpType = NetworkConstants.ICMPV6_ECHO_REQUEST_TYPE; - mMeasurement.description = "ICMPv6"; - } else { - mProtocol = IPPROTO_ICMP; - mIcmpType = NetworkConstants.ICMPV4_ECHO_REQUEST_TYPE; - mMeasurement.description = "ICMPv4"; - } - - mMeasurement.description += " dst{" + mTarget.getHostAddress() + "}"; - } - - public IcmpCheck(InetAddress target, Measurement measurement) { - this(null, target, measurement); - } - - @Override - public void run() { - if (ensureMeasurementNecessary()) return; - - try { - setupSocket(SOCK_DGRAM, mProtocol, TIMEOUT_SEND, TIMEOUT_RECV, 0); - } catch (ErrnoException | IOException e) { - mMeasurement.recordFailure(e.toString()); - return; - } - mMeasurement.description += " src{" + socketAddressToString(mSocketAddress) + "}"; - - // Build a trivial ICMP packet. - final byte[] icmpPacket = { - (byte) mIcmpType, 0, 0, 0, 0, 0, 0, 0 // ICMP header - }; - - int count = 0; - mMeasurement.startTime = now(); - while (now() < mDeadlineTime - (TIMEOUT_SEND + TIMEOUT_RECV)) { - count++; - icmpPacket[icmpPacket.length - 1] = (byte) count; - try { - Os.write(mFileDescriptor, icmpPacket, 0, icmpPacket.length); - } catch (ErrnoException | InterruptedIOException e) { - mMeasurement.recordFailure(e.toString()); - break; - } - - try { - ByteBuffer reply = ByteBuffer.allocate(PACKET_BUFSIZE); - Os.read(mFileDescriptor, reply); - // TODO: send a few pings back to back to guesstimate packet loss. - mMeasurement.recordSuccess("1/" + count); - break; - } catch (ErrnoException | InterruptedIOException e) { - continue; - } - } - if (mMeasurement.finishTime == 0) { - mMeasurement.recordFailure("0/" + count); - } - - close(); - } - } - - - private class DnsUdpCheck extends SimpleSocketCheck implements Runnable { - private static final int TIMEOUT_SEND = 100; - private static final int TIMEOUT_RECV = 500; - private static final int RR_TYPE_A = 1; - private static final int RR_TYPE_AAAA = 28; - private static final int PACKET_BUFSIZE = 512; - - protected final Random mRandom = new Random(); - - // Should be static, but the compiler mocks our puny, human attempts at reason. - protected String responseCodeStr(int rcode) { - try { - return DnsResponseCode.values()[rcode].toString(); - } catch (IndexOutOfBoundsException e) { - return String.valueOf(rcode); - } - } - - protected final int mQueryType; - - public DnsUdpCheck(InetAddress target, Measurement measurement) { - super(target, measurement); - - // TODO: Ideally, query the target for both types regardless of address family. - if (mAddressFamily == AF_INET6) { - mQueryType = RR_TYPE_AAAA; - } else { - mQueryType = RR_TYPE_A; - } - - mMeasurement.description = "DNS UDP dst{" + mTarget.getHostAddress() + "}"; - } - - @Override - public void run() { - if (ensureMeasurementNecessary()) return; - - try { - setupSocket(SOCK_DGRAM, IPPROTO_UDP, TIMEOUT_SEND, TIMEOUT_RECV, - NetworkConstants.DNS_SERVER_PORT); - } catch (ErrnoException | IOException e) { - mMeasurement.recordFailure(e.toString()); - return; - } - - // This needs to be fixed length so it can be dropped into the pre-canned packet. - final String sixRandomDigits = String.valueOf(mRandom.nextInt(900000) + 100000); - appendDnsToMeasurementDescription(sixRandomDigits, mSocketAddress); - - // Build a trivial DNS packet. - final byte[] dnsPacket = getDnsQueryPacket(sixRandomDigits); - - int count = 0; - mMeasurement.startTime = now(); - while (now() < mDeadlineTime - (TIMEOUT_RECV + TIMEOUT_RECV)) { - count++; - try { - Os.write(mFileDescriptor, dnsPacket, 0, dnsPacket.length); - } catch (ErrnoException | InterruptedIOException e) { - mMeasurement.recordFailure(e.toString()); - break; - } - - try { - ByteBuffer reply = ByteBuffer.allocate(PACKET_BUFSIZE); - Os.read(mFileDescriptor, reply); - // TODO: more correct and detailed evaluation of the response, - // possibly adding the returned IP address(es) to the output. - final String rcodeStr = (reply.limit() > 3) - ? " " + responseCodeStr((int) (reply.get(3)) & 0x0f) - : ""; - mMeasurement.recordSuccess("1/" + count + rcodeStr); - break; - } catch (ErrnoException | InterruptedIOException e) { - continue; - } - } - if (mMeasurement.finishTime == 0) { - mMeasurement.recordFailure("0/" + count); - } - - close(); - } - - protected byte[] getDnsQueryPacket(String sixRandomDigits) { - byte[] rnd = sixRandomDigits.getBytes(StandardCharsets.US_ASCII); - return new byte[] { - (byte) mRandom.nextInt(), (byte) mRandom.nextInt(), // [0-1] query ID - 1, 0, // [2-3] flags; byte[2] = 1 for recursion desired (RD). - 0, 1, // [4-5] QDCOUNT (number of queries) - 0, 0, // [6-7] ANCOUNT (number of answers) - 0, 0, // [8-9] NSCOUNT (number of name server records) - 0, 0, // [10-11] ARCOUNT (number of additional records) - 17, rnd[0], rnd[1], rnd[2], rnd[3], rnd[4], rnd[5], - '-', 'a', 'n', 'd', 'r', 'o', 'i', 'd', '-', 'd', 's', - 6, 'm', 'e', 't', 'r', 'i', 'c', - 7, 'g', 's', 't', 'a', 't', 'i', 'c', - 3, 'c', 'o', 'm', - 0, // null terminator of FQDN (root TLD) - 0, (byte) mQueryType, // QTYPE - 0, 1 // QCLASS, set to 1 = IN (Internet) - }; - } - - protected void appendDnsToMeasurementDescription( - String sixRandomDigits, SocketAddress sockAddr) { - mMeasurement.description += " src{" + socketAddressToString(sockAddr) + "}" - + " qtype{" + mQueryType + "}" - + " qname{" + sixRandomDigits + "-android-ds.metric.gstatic.com}"; - } - } - - // TODO: Have it inherited from SimpleSocketCheck, and separate common DNS helpers out of - // DnsUdpCheck. - private class DnsTlsCheck extends DnsUdpCheck { - private static final int TCP_CONNECT_TIMEOUT_MS = 2500; - private static final int TCP_TIMEOUT_MS = 2000; - private static final int DNS_TLS_PORT = 853; - private static final int DNS_HEADER_SIZE = 12; - - private final String mHostname; - - public DnsTlsCheck(@Nullable String hostname, @NonNull InetAddress target, - @NonNull Measurement measurement) { - super(target, measurement); - - mHostname = hostname; - mMeasurement.description = "DNS TLS dst{" + mTarget.getHostAddress() + "} hostname{" - + (mHostname == null ? "" : mHostname) + "}"; - } - - private SSLSocket setupSSLSocket() throws IOException { - // A TrustManager will be created and initialized with a KeyStore containing system - // CaCerts. During SSL handshake, it will be used to validate the certificates from - // the server. - SSLSocket sslSocket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(); - sslSocket.setSoTimeout(TCP_TIMEOUT_MS); - - if (!TextUtils.isEmpty(mHostname)) { - // Set SNI. - final List names = - Collections.singletonList(new SNIHostName(mHostname)); - SSLParameters params = sslSocket.getSSLParameters(); - params.setServerNames(names); - sslSocket.setSSLParameters(params); - } - - mNetwork.bindSocket(sslSocket); - return sslSocket; - } - - private void sendDoTProbe(@Nullable SSLSocket sslSocket) throws IOException { - final String sixRandomDigits = String.valueOf(mRandom.nextInt(900000) + 100000); - final byte[] dnsPacket = getDnsQueryPacket(sixRandomDigits); - - mMeasurement.startTime = now(); - sslSocket.connect(new InetSocketAddress(mTarget, DNS_TLS_PORT), TCP_CONNECT_TIMEOUT_MS); - - // Synchronous call waiting for the TLS handshake complete. - sslSocket.startHandshake(); - appendDnsToMeasurementDescription(sixRandomDigits, sslSocket.getLocalSocketAddress()); - - final DataOutputStream output = new DataOutputStream(sslSocket.getOutputStream()); - output.writeShort(dnsPacket.length); - output.write(dnsPacket, 0, dnsPacket.length); - - final DataInputStream input = new DataInputStream(sslSocket.getInputStream()); - final int replyLength = Short.toUnsignedInt(input.readShort()); - final byte[] reply = new byte[replyLength]; - int bytesRead = 0; - while (bytesRead < replyLength) { - bytesRead += input.read(reply, bytesRead, replyLength - bytesRead); - } - - if (bytesRead > DNS_HEADER_SIZE && bytesRead == replyLength) { - mMeasurement.recordSuccess("1/1 " + responseCodeStr((int) (reply[3]) & 0x0f)); - } else { - mMeasurement.recordFailure("1/1 Read " + bytesRead + " bytes while expected to be " - + replyLength + " bytes"); - } - } - - @Override - public void run() { - if (ensureMeasurementNecessary()) return; - - // No need to restore the tag, since this thread is only used for this measurement. - TrafficStats.getAndSetThreadStatsTag(NetworkStackConstants.TAG_SYSTEM_PROBE); - - try (SSLSocket sslSocket = setupSSLSocket()) { - sendDoTProbe(sslSocket); - } catch (IOException e) { - mMeasurement.recordFailure(e.toString()); - } - } - } -} diff --git a/packages/Connectivity/service/src/com/android/server/connectivity/NetworkNotificationManager.java b/packages/Connectivity/service/src/com/android/server/connectivity/NetworkNotificationManager.java deleted file mode 100644 index 3dc79c51d8a95..0000000000000 --- a/packages/Connectivity/service/src/com/android/server/connectivity/NetworkNotificationManager.java +++ /dev/null @@ -1,404 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; -import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; -import static android.net.NetworkCapabilities.TRANSPORT_VPN; -import static android.net.NetworkCapabilities.TRANSPORT_WIFI; - -import android.annotation.NonNull; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; -import android.graphics.drawable.Icon; -import android.net.ConnectivityResources; -import android.net.NetworkSpecifier; -import android.net.TelephonyNetworkSpecifier; -import android.net.wifi.WifiInfo; -import android.os.UserHandle; -import android.telephony.SubscriptionManager; -import android.telephony.TelephonyManager; -import android.text.TextUtils; -import android.util.Log; -import android.util.SparseArray; -import android.util.SparseIntArray; -import android.widget.Toast; - -import com.android.connectivity.resources.R; -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; - -public class NetworkNotificationManager { - - - public static enum NotificationType { - LOST_INTERNET(SystemMessage.NOTE_NETWORK_LOST_INTERNET), - NETWORK_SWITCH(SystemMessage.NOTE_NETWORK_SWITCH), - NO_INTERNET(SystemMessage.NOTE_NETWORK_NO_INTERNET), - PARTIAL_CONNECTIVITY(SystemMessage.NOTE_NETWORK_PARTIAL_CONNECTIVITY), - SIGN_IN(SystemMessage.NOTE_NETWORK_SIGN_IN), - PRIVATE_DNS_BROKEN(SystemMessage.NOTE_NETWORK_PRIVATE_DNS_BROKEN); - - public final int eventId; - - NotificationType(int eventId) { - this.eventId = eventId; - Holder.sIdToTypeMap.put(eventId, this); - } - - private static class Holder { - private static SparseArray sIdToTypeMap = new SparseArray<>(); - } - - public static NotificationType getFromId(int id) { - return Holder.sIdToTypeMap.get(id); - } - }; - - private static final String TAG = NetworkNotificationManager.class.getSimpleName(); - private static final boolean DBG = true; - - // Notification channels used by ConnectivityService mainline module, it should be aligned with - // SystemNotificationChannels so the channels are the same as the ones used as the system - // server. - public static final String NOTIFICATION_CHANNEL_NETWORK_STATUS = "NETWORK_STATUS"; - public static final String NOTIFICATION_CHANNEL_NETWORK_ALERTS = "NETWORK_ALERTS"; - - // The context is for the current user (system server) - private final Context mContext; - private final ConnectivityResources mResources; - private final TelephonyManager mTelephonyManager; - // The notification manager is created from a context for User.ALL, so notifications - // will be sent to all users. - private final NotificationManager mNotificationManager; - // Tracks the types of notifications managed by this instance, from creation to cancellation. - private final SparseIntArray mNotificationTypeMap; - - public NetworkNotificationManager(@NonNull final Context c, @NonNull final TelephonyManager t) { - mContext = c; - mTelephonyManager = t; - mNotificationManager = - (NotificationManager) c.createContextAsUser(UserHandle.ALL, 0 /* flags */) - .getSystemService(Context.NOTIFICATION_SERVICE); - mNotificationTypeMap = new SparseIntArray(); - mResources = new ConnectivityResources(mContext); - } - - @VisibleForTesting - protected static int approximateTransportType(NetworkAgentInfo nai) { - return nai.isVPN() ? TRANSPORT_VPN : getFirstTransportType(nai); - } - - // TODO: deal more gracefully with multi-transport networks. - private static int getFirstTransportType(NetworkAgentInfo nai) { - // TODO: The range is wrong, the safer and correct way is to change the range from - // MIN_TRANSPORT to MAX_TRANSPORT. - for (int i = 0; i < 64; i++) { - if (nai.networkCapabilities.hasTransport(i)) return i; - } - return -1; - } - - private String getTransportName(final int transportType) { - String[] networkTypes = mResources.get().getStringArray(R.array.network_switch_type_name); - try { - return networkTypes[transportType]; - } catch (IndexOutOfBoundsException e) { - return mResources.get().getString(R.string.network_switch_type_name_unknown); - } - } - - private static int getIcon(int transportType) { - return (transportType == TRANSPORT_WIFI) - ? R.drawable.stat_notify_wifi_in_range // TODO: Distinguish ! from ?. - : R.drawable.stat_notify_rssi_in_range; - } - - /** - * Show or hide network provisioning notifications. - * - * We use notifications for two purposes: to notify that a network requires sign in - * (NotificationType.SIGN_IN), or to notify that a network does not have Internet access - * (NotificationType.NO_INTERNET). We display at most one notification per ID, so on a - * particular network we can display the notification type that was most recently requested. - * So for example if a captive portal fails to reply within a few seconds of connecting, we - * might first display NO_INTERNET, and then when the captive portal check completes, display - * SIGN_IN. - * - * @param id an identifier that uniquely identifies this notification. This must match - * between show and hide calls. We use the NetID value but for legacy callers - * we concatenate the range of types with the range of NetIDs. - * @param notifyType the type of the notification. - * @param nai the network with which the notification is associated. For a SIGN_IN, NO_INTERNET, - * or LOST_INTERNET notification, this is the network we're connecting to. For a - * NETWORK_SWITCH notification it's the network that we switched from. When this network - * disconnects the notification is removed. - * @param switchToNai for a NETWORK_SWITCH notification, the network we are switching to. Null - * in all other cases. Only used to determine the text of the notification. - */ - public void showNotification(int id, NotificationType notifyType, NetworkAgentInfo nai, - NetworkAgentInfo switchToNai, PendingIntent intent, boolean highPriority) { - final String tag = tagFor(id); - final int eventId = notifyType.eventId; - final int transportType; - final CharSequence name; - if (nai != null) { - transportType = approximateTransportType(nai); - final String extraInfo = nai.networkInfo.getExtraInfo(); - if (nai.linkProperties != null && nai.linkProperties.getCaptivePortalData() != null - && !TextUtils.isEmpty(nai.linkProperties.getCaptivePortalData() - .getVenueFriendlyName())) { - name = nai.linkProperties.getCaptivePortalData().getVenueFriendlyName(); - } else { - name = TextUtils.isEmpty(extraInfo) - ? WifiInfo.sanitizeSsid(nai.networkCapabilities.getSsid()) : extraInfo; - } - // Only notify for Internet-capable networks. - if (!nai.networkCapabilities.hasCapability(NET_CAPABILITY_INTERNET)) return; - } else { - // Legacy notifications. - transportType = TRANSPORT_CELLULAR; - name = ""; - } - - // Clear any previous notification with lower priority, otherwise return. http://b/63676954. - // A new SIGN_IN notification with a new intent should override any existing one. - final int previousEventId = mNotificationTypeMap.get(id); - final NotificationType previousNotifyType = NotificationType.getFromId(previousEventId); - if (priority(previousNotifyType) > priority(notifyType)) { - Log.d(TAG, String.format( - "ignoring notification %s for network %s with existing notification %s", - notifyType, id, previousNotifyType)); - return; - } - clearNotification(id); - - if (DBG) { - Log.d(TAG, String.format( - "showNotification tag=%s event=%s transport=%s name=%s highPriority=%s", - tag, nameOf(eventId), getTransportName(transportType), name, highPriority)); - } - - final Resources r = mResources.get(); - final CharSequence title; - final CharSequence details; - Icon icon = Icon.createWithResource( - mResources.getResourcesContext(), getIcon(transportType)); - if (notifyType == NotificationType.NO_INTERNET && transportType == TRANSPORT_WIFI) { - title = r.getString(R.string.wifi_no_internet, name); - details = r.getString(R.string.wifi_no_internet_detailed); - } else if (notifyType == NotificationType.PRIVATE_DNS_BROKEN) { - if (transportType == TRANSPORT_CELLULAR) { - title = r.getString(R.string.mobile_no_internet); - } else if (transportType == TRANSPORT_WIFI) { - title = r.getString(R.string.wifi_no_internet, name); - } else { - title = r.getString(R.string.other_networks_no_internet); - } - details = r.getString(R.string.private_dns_broken_detailed); - } else if (notifyType == NotificationType.PARTIAL_CONNECTIVITY - && transportType == TRANSPORT_WIFI) { - title = r.getString(R.string.network_partial_connectivity, name); - details = r.getString(R.string.network_partial_connectivity_detailed); - } else if (notifyType == NotificationType.LOST_INTERNET && - transportType == TRANSPORT_WIFI) { - title = r.getString(R.string.wifi_no_internet, name); - details = r.getString(R.string.wifi_no_internet_detailed); - } else if (notifyType == NotificationType.SIGN_IN) { - switch (transportType) { - case TRANSPORT_WIFI: - title = r.getString(R.string.wifi_available_sign_in, 0); - details = r.getString(R.string.network_available_sign_in_detailed, name); - break; - case TRANSPORT_CELLULAR: - title = r.getString(R.string.network_available_sign_in, 0); - // TODO: Change this to pull from NetworkInfo once a printable - // name has been added to it - NetworkSpecifier specifier = nai.networkCapabilities.getNetworkSpecifier(); - int subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID; - if (specifier instanceof TelephonyNetworkSpecifier) { - subId = ((TelephonyNetworkSpecifier) specifier).getSubscriptionId(); - } - - details = mTelephonyManager.createForSubscriptionId(subId) - .getNetworkOperatorName(); - break; - default: - title = r.getString(R.string.network_available_sign_in, 0); - details = r.getString(R.string.network_available_sign_in_detailed, name); - break; - } - } else if (notifyType == NotificationType.NETWORK_SWITCH) { - String fromTransport = getTransportName(transportType); - String toTransport = getTransportName(approximateTransportType(switchToNai)); - title = r.getString(R.string.network_switch_metered, toTransport); - details = r.getString(R.string.network_switch_metered_detail, toTransport, - fromTransport); - } else if (notifyType == NotificationType.NO_INTERNET - || notifyType == NotificationType.PARTIAL_CONNECTIVITY) { - // NO_INTERNET and PARTIAL_CONNECTIVITY notification for non-WiFi networks - // are sent, but they are not implemented yet. - return; - } else { - Log.wtf(TAG, "Unknown notification type " + notifyType + " on network transport " - + getTransportName(transportType)); - return; - } - // When replacing an existing notification for a given network, don't alert, just silently - // update the existing notification. Note that setOnlyAlertOnce() will only work for the - // same id, and the id used here is the NotificationType which is different in every type of - // notification. This is required because the notification metrics only track the ID but not - // the tag. - final boolean hasPreviousNotification = previousNotifyType != null; - final String channelId = (highPriority && !hasPreviousNotification) - ? NOTIFICATION_CHANNEL_NETWORK_ALERTS : NOTIFICATION_CHANNEL_NETWORK_STATUS; - Notification.Builder builder = new Notification.Builder(mContext, channelId) - .setWhen(System.currentTimeMillis()) - .setShowWhen(notifyType == NotificationType.NETWORK_SWITCH) - .setSmallIcon(icon) - .setAutoCancel(true) - .setTicker(title) - .setColor(mContext.getColor(android.R.color.system_notification_accent_color)) - .setContentTitle(title) - .setContentIntent(intent) - .setLocalOnly(true) - .setOnlyAlertOnce(true) - // TODO: consider having action buttons to disconnect on the sign-in notification - // especially if it is ongoing - .setOngoing(notifyType == NotificationType.SIGN_IN - && r.getBoolean(R.bool.config_ongoingSignInNotification)); - - if (notifyType == NotificationType.NETWORK_SWITCH) { - builder.setStyle(new Notification.BigTextStyle().bigText(details)); - } else { - builder.setContentText(details); - } - - if (notifyType == NotificationType.SIGN_IN) { - builder.extend(new Notification.TvExtender().setChannelId(channelId)); - } - - Notification notification = builder.build(); - - mNotificationTypeMap.put(id, eventId); - try { - mNotificationManager.notify(tag, eventId, notification); - } catch (NullPointerException npe) { - Log.d(TAG, "setNotificationVisible: visible notificationManager error", npe); - } - } - - /** - * Clear the notification with the given id, only if it matches the given type. - */ - public void clearNotification(int id, NotificationType notifyType) { - final int previousEventId = mNotificationTypeMap.get(id); - final NotificationType previousNotifyType = NotificationType.getFromId(previousEventId); - if (notifyType != previousNotifyType) { - return; - } - clearNotification(id); - } - - public void clearNotification(int id) { - if (mNotificationTypeMap.indexOfKey(id) < 0) { - return; - } - final String tag = tagFor(id); - final int eventId = mNotificationTypeMap.get(id); - if (DBG) { - Log.d(TAG, String.format("clearing notification tag=%s event=%s", tag, - nameOf(eventId))); - } - try { - mNotificationManager.cancel(tag, eventId); - } catch (NullPointerException npe) { - Log.d(TAG, String.format( - "failed to clear notification tag=%s event=%s", tag, nameOf(eventId)), npe); - } - mNotificationTypeMap.delete(id); - } - - /** - * Legacy provisioning notifications coming directly from DcTracker. - */ - public void setProvNotificationVisible(boolean visible, int id, String action) { - if (visible) { - // For legacy purposes, action is sent as the action + the phone ID from DcTracker. - // Split the string here and send the phone ID as an extra instead. - String[] splitAction = action.split(":"); - Intent intent = new Intent(splitAction[0]); - try { - intent.putExtra("provision.phone.id", Integer.parseInt(splitAction[1])); - } catch (NumberFormatException ignored) { } - PendingIntent pendingIntent = PendingIntent.getBroadcast( - mContext, 0 /* requestCode */, intent, PendingIntent.FLAG_IMMUTABLE); - showNotification(id, NotificationType.SIGN_IN, null, null, pendingIntent, false); - } else { - clearNotification(id); - } - } - - public void showToast(NetworkAgentInfo fromNai, NetworkAgentInfo toNai) { - String fromTransport = getTransportName(approximateTransportType(fromNai)); - String toTransport = getTransportName(approximateTransportType(toNai)); - String text = mResources.get().getString( - R.string.network_switch_metered_toast, fromTransport, toTransport); - Toast.makeText(mContext, text, Toast.LENGTH_LONG).show(); - } - - @VisibleForTesting - static String tagFor(int id) { - return String.format("ConnectivityNotification:%d", id); - } - - @VisibleForTesting - static String nameOf(int eventId) { - NotificationType t = NotificationType.getFromId(eventId); - return (t != null) ? t.name() : "UNKNOWN"; - } - - /** - * A notification with a higher number will take priority over a notification with a lower - * number. - */ - private static int priority(NotificationType t) { - if (t == null) { - return 0; - } - switch (t) { - case SIGN_IN: - return 6; - case PARTIAL_CONNECTIVITY: - return 5; - case PRIVATE_DNS_BROKEN: - return 4; - case NO_INTERNET: - return 3; - case NETWORK_SWITCH: - return 2; - case LOST_INTERNET: - return 1; - default: - return 0; - } - } -} diff --git a/packages/Connectivity/service/src/com/android/server/connectivity/NetworkOffer.java b/packages/Connectivity/service/src/com/android/server/connectivity/NetworkOffer.java deleted file mode 100644 index 8285e7a8a3cb9..0000000000000 --- a/packages/Connectivity/service/src/com/android/server/connectivity/NetworkOffer.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import android.annotation.NonNull; -import android.net.INetworkOfferCallback; -import android.net.NetworkCapabilities; -import android.net.NetworkRequest; -import android.os.RemoteException; - -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; - -/** - * Represents an offer made by a NetworkProvider to create a network if a need arises. - * - * This class contains the prospective score and capabilities of the network. The provider - * is not obligated to caps able to create a network satisfying this, nor to build a network - * with the exact score and/or capabilities passed ; after all, not all providers know in - * advance what a network will look like after it's connected. Instead, this is meant as a - * filter to limit requests sent to the provider by connectivity to those that this offer stands - * a chance to fulfill. - * - * @see NetworkProvider#offerNetwork. - * - * @hide - */ -public class NetworkOffer implements NetworkRanker.Scoreable { - @NonNull public final FullScore score; - @NonNull public final NetworkCapabilities caps; - @NonNull public final INetworkOfferCallback callback; - @NonNull public final int providerId; - // While this could, in principle, be deduced from the old values of the satisfying networks, - // doing so would add a lot of complexity and performance penalties. For each request, the - // ranker would have to run again to figure out if this offer used to be able to beat the - // previous satisfier to know if there is a change in whether this offer is now needed ; - // besides, there would be a need to handle an edge case when a new request comes online, - // where it's not satisfied before the first rematch, where starting to satisfy a request - // should not result in sending unneeded to this offer. This boolean, while requiring that - // the offers are only ever manipulated on the CS thread, is by far a simpler and - // economical solution. - private final Set mCurrentlyNeeded = new HashSet<>(); - - public NetworkOffer(@NonNull final FullScore score, - @NonNull final NetworkCapabilities caps, - @NonNull final INetworkOfferCallback callback, - @NonNull final int providerId) { - this.score = Objects.requireNonNull(score); - this.caps = Objects.requireNonNull(caps); - this.callback = Objects.requireNonNull(callback); - this.providerId = providerId; - } - - /** - * Get the score filter of this offer - */ - @Override @NonNull public FullScore getScore() { - return score; - } - - /** - * Get the capabilities filter of this offer - */ - @Override @NonNull public NetworkCapabilities getCapsNoCopy() { - return caps; - } - - /** - * Tell the provider for this offer that the network is needed for a request. - * @param request the request for which the offer is needed - */ - public void onNetworkNeeded(@NonNull final NetworkRequest request) { - if (mCurrentlyNeeded.contains(request)) { - throw new IllegalStateException("Network already needed"); - } - mCurrentlyNeeded.add(request); - try { - callback.onNetworkNeeded(request); - } catch (final RemoteException e) { - // The provider is dead. It will be removed by the death recipient. - } - } - - /** - * Tell the provider for this offer that the network is no longer needed for this request. - * - * onNetworkNeeded will have been called with the same request before. - * - * @param request the request - */ - public void onNetworkUnneeded(@NonNull final NetworkRequest request) { - if (!mCurrentlyNeeded.contains(request)) { - throw new IllegalStateException("Network already unneeded"); - } - mCurrentlyNeeded.remove(request); - try { - callback.onNetworkUnneeded(request); - } catch (final RemoteException e) { - // The provider is dead. It will be removed by the death recipient. - } - } - - /** - * Returns whether this offer is currently needed for this request. - * @param request the request - * @return whether the offer is currently considered needed - */ - public boolean neededFor(@NonNull final NetworkRequest request) { - return mCurrentlyNeeded.contains(request); - } - - /** - * Migrate from, and take over, a previous offer. - * - * When an updated offer is sent from a provider, call this method on the new offer, passing - * the old one, to take over the state. - * - * @param previousOffer the previous offer - */ - public void migrateFrom(@NonNull final NetworkOffer previousOffer) { - if (!callback.asBinder().equals(previousOffer.callback.asBinder())) { - throw new IllegalArgumentException("Can only migrate from a previous version of" - + " the same offer"); - } - mCurrentlyNeeded.clear(); - mCurrentlyNeeded.addAll(previousOffer.mCurrentlyNeeded); - } - - @Override - public String toString() { - return "NetworkOffer [ Score " + score + " ]"; - } -} diff --git a/packages/Connectivity/service/src/com/android/server/connectivity/NetworkRanker.java b/packages/Connectivity/service/src/com/android/server/connectivity/NetworkRanker.java deleted file mode 100644 index d7eb9c8a59b85..0000000000000 --- a/packages/Connectivity/service/src/com/android/server/connectivity/NetworkRanker.java +++ /dev/null @@ -1,351 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH; -import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; -import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET; -import static android.net.NetworkCapabilities.TRANSPORT_WIFI; -import static android.net.NetworkScore.POLICY_EXITING; -import static android.net.NetworkScore.POLICY_TRANSPORT_PRIMARY; -import static android.net.NetworkScore.POLICY_YIELD_TO_BAD_WIFI; - -import static com.android.net.module.util.CollectionUtils.filter; -import static com.android.server.connectivity.FullScore.POLICY_ACCEPT_UNVALIDATED; -import static com.android.server.connectivity.FullScore.POLICY_EVER_USER_SELECTED; -import static com.android.server.connectivity.FullScore.POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD; -import static com.android.server.connectivity.FullScore.POLICY_IS_INVINCIBLE; -import static com.android.server.connectivity.FullScore.POLICY_IS_VALIDATED; -import static com.android.server.connectivity.FullScore.POLICY_IS_VPN; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.net.NetworkCapabilities; -import android.net.NetworkRequest; - -import com.android.net.module.util.CollectionUtils; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.function.Predicate; - -/** - * A class that knows how to find the best network matching a request out of a list of networks. - */ -public class NetworkRanker { - // Historically the legacy ints have been 0~100 in principle (though the highest score in - // AOSP has always been 90). This is relied on by VPNs that send a legacy score of 101. - public static final int LEGACY_INT_MAX = 100; - - /** - * A class that can be scored against other scoreables. - */ - public interface Scoreable { - /** Get score of this scoreable */ - FullScore getScore(); - /** Get capabilities of this scoreable */ - NetworkCapabilities getCapsNoCopy(); - } - - private static final boolean USE_POLICY_RANKING = true; - - public NetworkRanker() { } - - /** - * Find the best network satisfying this request among the list of passed networks. - */ - @Nullable - public NetworkAgentInfo getBestNetwork(@NonNull final NetworkRequest request, - @NonNull final Collection nais, - @Nullable final NetworkAgentInfo currentSatisfier) { - final ArrayList candidates = filter(nais, nai -> nai.satisfies(request)); - if (candidates.size() == 1) return candidates.get(0); // Only one potential satisfier - if (candidates.size() <= 0) return null; // No network can satisfy this request - if (USE_POLICY_RANKING) { - return getBestNetworkByPolicy(candidates, currentSatisfier); - } else { - return getBestNetworkByLegacyInt(candidates); - } - } - - // Transport preference order, if it comes down to that. - private static final int[] PREFERRED_TRANSPORTS_ORDER = { TRANSPORT_ETHERNET, TRANSPORT_WIFI, - TRANSPORT_BLUETOOTH, TRANSPORT_CELLULAR }; - - // Function used to partition a list into two working areas depending on whether they - // satisfy a predicate. All items satisfying the predicate will be put in |positive|, all - // items that don't will be put in |negative|. - // This is useful in this file because many of the ranking checks will retain only networks that - // satisfy a predicate if any of them do, but keep them all if all of them do. Having working - // areas is uncustomary in Java, but this function is called in a fairly intensive manner - // and doing allocation quite that often might affect performance quite badly. - private static void partitionInto(@NonNull final List source, @NonNull Predicate test, - @NonNull final List positive, @NonNull final List negative) { - positive.clear(); - negative.clear(); - for (final T item : source) { - if (test.test(item)) { - positive.add(item); - } else { - negative.add(item); - } - } - } - - private boolean isBadWiFi(@NonNull final T candidate) { - return candidate.getScore().hasPolicy(POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD) - && candidate.getCapsNoCopy().hasTransport(TRANSPORT_WIFI); - } - - /** - * Apply the "yield to bad WiFi" policy. - * - * This function must run immediately after the validation policy. - * - * If any of the accepted networks has the "yield to bad WiFi" policy AND there are some - * bad WiFis in the rejected list, then move the networks with the policy to the rejected - * list. If this leaves no accepted network, then move the bad WiFis back to the accepted list. - * - * This function returns nothing, but will have updated accepted and rejected in-place. - * - * @param accepted networks accepted by the validation policy - * @param rejected networks rejected by the validation policy - */ - private void applyYieldToBadWifiPolicy(@NonNull ArrayList accepted, - @NonNull ArrayList rejected) { - if (!CollectionUtils.any(accepted, n -> n.getScore().hasPolicy(POLICY_YIELD_TO_BAD_WIFI))) { - // No network with the policy : do nothing. - return; - } - if (!CollectionUtils.any(rejected, n -> isBadWiFi(n))) { - // No bad WiFi : do nothing. - return; - } - if (CollectionUtils.all(accepted, n -> n.getScore().hasPolicy(POLICY_YIELD_TO_BAD_WIFI))) { - // All validated networks yield to bad WiFis : keep bad WiFis alongside with the - // yielders. This is important because the yielders need to be compared to the bad - // wifis by the following policies (e.g. exiting). - final ArrayList acceptedYielders = new ArrayList<>(accepted); - final ArrayList rejectedWithBadWiFis = new ArrayList<>(rejected); - partitionInto(rejectedWithBadWiFis, n -> isBadWiFi(n), accepted, rejected); - accepted.addAll(acceptedYielders); - return; - } - // Only some of the validated networks yield to bad WiFi : keep only the ones who don't. - final ArrayList acceptedWithYielders = new ArrayList<>(accepted); - partitionInto(acceptedWithYielders, n -> !n.getScore().hasPolicy(POLICY_YIELD_TO_BAD_WIFI), - accepted, rejected); - } - - /** - * Get the best network among a list of candidates according to policy. - * @param candidates the candidates - * @param currentSatisfier the current satisfier, or null if none - * @return the best network - */ - @Nullable public T getBestNetworkByPolicy( - @NonNull List candidates, - @Nullable final T currentSatisfier) { - // Used as working areas. - final ArrayList accepted = - new ArrayList<>(candidates.size() /* initialCapacity */); - final ArrayList rejected = - new ArrayList<>(candidates.size() /* initialCapacity */); - - // The following tests will search for a network matching a given criterion. They all - // function the same way : if any network matches the criterion, drop from consideration - // all networks that don't. To achieve this, the tests below : - // 1. partition the list of remaining candidates into accepted and rejected networks. - // 2. if only one candidate remains, that's the winner : if accepted.size == 1 return [0] - // 3. if multiple remain, keep only the accepted networks and go on to the next criterion. - // Because the working areas will be wiped, a copy of the accepted networks needs to be - // made. - // 4. if none remain, the criterion did not help discriminate so keep them all. As an - // optimization, skip creating a new array and go on to the next criterion. - - // If a network is invincible, use it. - partitionInto(candidates, nai -> nai.getScore().hasPolicy(POLICY_IS_INVINCIBLE), - accepted, rejected); - if (accepted.size() == 1) return accepted.get(0); - if (accepted.size() > 0 && rejected.size() > 0) candidates = new ArrayList<>(accepted); - - // If there is a connected VPN, use it. - partitionInto(candidates, nai -> nai.getScore().hasPolicy(POLICY_IS_VPN), - accepted, rejected); - if (accepted.size() == 1) return accepted.get(0); - if (accepted.size() > 0 && rejected.size() > 0) candidates = new ArrayList<>(accepted); - - // Selected & Accept-unvalidated policy : if any network has both of these, then don't - // choose one that doesn't. - partitionInto(candidates, nai -> nai.getScore().hasPolicy(POLICY_EVER_USER_SELECTED) - && nai.getScore().hasPolicy(POLICY_ACCEPT_UNVALIDATED), - accepted, rejected); - if (accepted.size() == 1) return accepted.get(0); - if (accepted.size() > 0 && rejected.size() > 0) candidates = new ArrayList<>(accepted); - - // If any network is validated (or should be accepted even if it's not validated), then - // don't choose one that isn't. - partitionInto(candidates, nai -> nai.getScore().hasPolicy(POLICY_IS_VALIDATED) - || nai.getScore().hasPolicy(POLICY_ACCEPT_UNVALIDATED), - accepted, rejected); - // Yield to bad wifi policy : if any network has the "yield to bad WiFi" policy and - // there are bad WiFis connected, then accept the bad WiFis and reject the networks with - // the policy. - applyYieldToBadWifiPolicy(accepted, rejected); - if (accepted.size() == 1) return accepted.get(0); - if (accepted.size() > 0 && rejected.size() > 0) candidates = new ArrayList<>(accepted); - - // If any network is not exiting, don't choose one that is. - partitionInto(candidates, nai -> !nai.getScore().hasPolicy(POLICY_EXITING), - accepted, rejected); - if (accepted.size() == 1) return accepted.get(0); - if (accepted.size() > 0 && rejected.size() > 0) candidates = new ArrayList<>(accepted); - - // TODO : If any network is unmetered, don't choose a metered network. - // This can't be implemented immediately because prospective networks are always - // considered unmetered because factories don't know if the network will be metered. - // Saying an unmetered network always beats a metered one would mean that when metered wifi - // is connected, the offer for telephony would beat WiFi but the actual metered network - // would lose, so we'd have an infinite loop where telephony would continually bring up - // a network that is immediately torn down. - // Fix this by getting the agent to tell connectivity whether the network they will - // bring up is metered. Cell knows that in advance, while WiFi has a good estimate and - // can revise it if the network later turns out to be metered. - // partitionInto(candidates, nai -> nai.getScore().hasPolicy(POLICY_IS_UNMETERED), - // accepted, rejected); - // if (accepted.size() == 1) return accepted.get(0); - // if (accepted.size() > 0 && rejected.size() > 0) candidates = new ArrayList<>(accepted); - - // If any network is for the default subscription, don't choose a network for another - // subscription with the same transport. - partitionInto(candidates, nai -> nai.getScore().hasPolicy(POLICY_TRANSPORT_PRIMARY), - accepted, rejected); - if (accepted.size() > 0) { - // Some networks are primary for their transport. For each transport, keep only the - // primary, but also keep all networks for which there isn't a primary (which are now - // in the |rejected| array). - // So for each primary network, remove from |rejected| all networks with the same - // transports as one of the primary networks. The remaining networks should be accepted. - for (final T defaultSubNai : accepted) { - final int[] transports = defaultSubNai.getCapsNoCopy().getTransportTypes(); - rejected.removeIf( - nai -> Arrays.equals(transports, nai.getCapsNoCopy().getTransportTypes())); - } - // Now the |rejected| list contains networks with transports for which there isn't - // a primary network. Add them back to the candidates. - accepted.addAll(rejected); - candidates = new ArrayList<>(accepted); - } - if (1 == candidates.size()) return candidates.get(0); - // If there were no primary network, then candidates.size() > 0 because it didn't - // change from the previous result. If there were, it's guaranteed candidates.size() > 0 - // because accepted.size() > 0 above. - - // If some of the networks have a better transport than others, keep only the ones with - // the best transports. - for (final int transport : PREFERRED_TRANSPORTS_ORDER) { - partitionInto(candidates, nai -> nai.getCapsNoCopy().hasTransport(transport), - accepted, rejected); - if (accepted.size() == 1) return accepted.get(0); - if (accepted.size() > 0 && rejected.size() > 0) { - candidates = new ArrayList<>(accepted); - break; - } - } - - // At this point there are still multiple networks passing all the tests above. If any - // of them is the previous satisfier, keep it. - if (candidates.contains(currentSatisfier)) return currentSatisfier; - - // If there are still multiple options at this point but none of them is any of the - // transports above, it doesn't matter which is returned. They are all the same. - return candidates.get(0); - } - - // TODO : switch to the policy implementation and remove - // Almost equivalent to Collections.max(nais), but allows returning null if no network - // satisfies the request. - private NetworkAgentInfo getBestNetworkByLegacyInt( - @NonNull final Collection nais) { - NetworkAgentInfo bestNetwork = null; - int bestScore = Integer.MIN_VALUE; - for (final NetworkAgentInfo nai : nais) { - final int naiScore = nai.getCurrentScore(); - if (naiScore > bestScore) { - bestNetwork = nai; - bestScore = naiScore; - } - } - return bestNetwork; - } - - /** - * Returns whether a {@link Scoreable} has a chance to beat a champion network for a request. - * - * Offers are sent by network providers when they think they might be able to make a network - * with the characteristics contained in the offer. If the offer has no chance to beat - * the currently best network for a given request, there is no point in the provider spending - * power trying to find and bring up such a network. - * - * Note that having an offer up does not constitute a commitment from the provider part - * to be able to bring up a network with these characteristics, or a network at all for - * that matter. This is only used to save power by letting providers know when they can't - * beat a current champion. - * - * @param request The request to evaluate against. - * @param champion The currently best network for this request. - * @param contestant The offer. - * @return Whether the offer stands a chance to beat the champion. - */ - public boolean mightBeat(@NonNull final NetworkRequest request, - @Nullable final NetworkAgentInfo champion, - @NonNull final Scoreable contestant) { - // If this network can't even satisfy the request then it can't beat anything, not - // even an absence of network. It can't satisfy it anyway. - if (!request.canBeSatisfiedBy(contestant.getCapsNoCopy())) return false; - // If there is no satisfying network, then this network can beat, because some network - // is always better than no network. - if (null == champion) return true; - if (USE_POLICY_RANKING) { - // If there is no champion, the offer can always beat. - // Otherwise rank them. - final ArrayList candidates = new ArrayList<>(); - candidates.add(champion); - candidates.add(contestant); - return contestant == getBestNetworkByPolicy(candidates, champion); - } else { - return mightBeatByLegacyInt(champion.getScore(), contestant); - } - } - - /** - * Returns whether a contestant might beat a champion according to the legacy int. - */ - private boolean mightBeatByLegacyInt(@Nullable final FullScore championScore, - @NonNull final Scoreable contestant) { - final int offerIntScore; - if (contestant.getCapsNoCopy().hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) { - // If the offer might have Internet access, then it might validate. - offerIntScore = contestant.getScore().getLegacyIntAsValidated(); - } else { - offerIntScore = contestant.getScore().getLegacyInt(); - } - return championScore.getLegacyInt() < offerIntScore; - } -} diff --git a/packages/Connectivity/service/src/com/android/server/connectivity/OsCompat.java b/packages/Connectivity/service/src/com/android/server/connectivity/OsCompat.java deleted file mode 100644 index 57e3dcdf0d73f..0000000000000 --- a/packages/Connectivity/service/src/com/android/server/connectivity/OsCompat.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import android.system.ErrnoException; -import android.system.Os; - -import java.io.FileDescriptor; - -/** - * Compatibility utility for android.system.Os core platform APIs. - * - * Connectivity has access to such APIs, but they are not part of the module_current stubs yet - * (only core_current). Most stable core platform APIs are included manually in the connectivity - * build rules, but because Os is also part of the base java SDK that is earlier on the - * classpath, the extra core platform APIs are not seen. - * - * TODO (b/157639992, b/183097033): remove as soon as core_current is part of system_server_current - * @hide - */ -public class OsCompat { - // This value should be correct on all architectures supported by Android, but hardcoding ioctl - // numbers should be avoided. - /** - * @see android.system.OsConstants#TIOCOUTQ - */ - public static final int TIOCOUTQ = 0x5411; - - /** - * @see android.system.Os#getsockoptInt(FileDescriptor, int, int) - */ - public static int getsockoptInt(FileDescriptor fd, int level, int option) throws - ErrnoException { - try { - return (int) Os.class.getMethod( - "getsockoptInt", FileDescriptor.class, int.class, int.class) - .invoke(null, fd, level, option); - } catch (ReflectiveOperationException e) { - if (e.getCause() instanceof ErrnoException) { - throw (ErrnoException) e.getCause(); - } - throw new IllegalStateException("Error calling getsockoptInt", e); - } - } - - /** - * @see android.system.Os#ioctlInt(FileDescriptor, int) - */ - public static int ioctlInt(FileDescriptor fd, int cmd) throws - ErrnoException { - try { - return (int) Os.class.getMethod( - "ioctlInt", FileDescriptor.class, int.class).invoke(null, fd, cmd); - } catch (ReflectiveOperationException e) { - if (e.getCause() instanceof ErrnoException) { - throw (ErrnoException) e.getCause(); - } - throw new IllegalStateException("Error calling ioctlInt", e); - } - } -} diff --git a/packages/Connectivity/service/src/com/android/server/connectivity/PermissionMonitor.java b/packages/Connectivity/service/src/com/android/server/connectivity/PermissionMonitor.java deleted file mode 100644 index 9bda59cc867e0..0000000000000 --- a/packages/Connectivity/service/src/com/android/server/connectivity/PermissionMonitor.java +++ /dev/null @@ -1,829 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import static android.Manifest.permission.CHANGE_NETWORK_STATE; -import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS; -import static android.Manifest.permission.INTERNET; -import static android.Manifest.permission.NETWORK_STACK; -import static android.Manifest.permission.UPDATE_DEVICE_STATS; -import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; -import static android.content.pm.PackageManager.GET_PERMISSIONS; -import static android.content.pm.PackageManager.MATCH_ANY_USER; -import static android.net.ConnectivitySettingsManager.APPS_ALLOWED_ON_RESTRICTED_NETWORKS; -import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; -import static android.os.Process.INVALID_UID; -import static android.os.Process.SYSTEM_UID; - -import static com.android.net.module.util.CollectionUtils.toIntArray; - -import android.annotation.NonNull; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.database.ContentObserver; -import android.net.ConnectivitySettingsManager; -import android.net.INetd; -import android.net.UidRange; -import android.net.Uri; -import android.os.Build; -import android.os.RemoteException; -import android.os.ServiceSpecificException; -import android.os.SystemConfigManager; -import android.os.UserHandle; -import android.os.UserManager; -import android.provider.Settings; -import android.system.OsConstants; -import android.util.ArraySet; -import android.util.Log; -import android.util.SparseArray; -import android.util.SparseIntArray; - -import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.IndentingPrintWriter; -import com.android.net.module.util.CollectionUtils; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -/** - * A utility class to inform Netd of UID permisisons. - * Does a mass update at boot and then monitors for app install/remove. - * - * @hide - */ -public class PermissionMonitor { - private static final String TAG = "PermissionMonitor"; - private static final boolean DBG = true; - protected static final Boolean SYSTEM = Boolean.TRUE; - protected static final Boolean NETWORK = Boolean.FALSE; - private static final int VERSION_Q = Build.VERSION_CODES.Q; - - private final PackageManager mPackageManager; - private final UserManager mUserManager; - private final SystemConfigManager mSystemConfigManager; - private final INetd mNetd; - private final Dependencies mDeps; - private final Context mContext; - - @GuardedBy("this") - private final Set mUsers = new HashSet<>(); - - // Keys are app uids. Values are true for SYSTEM permission and false for NETWORK permission. - @GuardedBy("this") - private final Map mApps = new HashMap<>(); - - // Keys are active non-bypassable and fully-routed VPN's interface name, Values are uid ranges - // for apps under the VPN - @GuardedBy("this") - private final Map> mVpnUidRanges = new HashMap<>(); - - // A set of appIds for apps across all users on the device. We track appIds instead of uids - // directly to reduce its size and also eliminate the need to update this set when user is - // added/removed. - @GuardedBy("this") - private final Set mAllApps = new HashSet<>(); - - // A set of apps which are allowed to use restricted networks. These apps can't hold the - // CONNECTIVITY_USE_RESTRICTED_NETWORKS permission because they can't be signature|privileged - // apps. However, these apps should still be able to use restricted networks under certain - // conditions (e.g. government app using emergency services). So grant netd system permission - // to uids whose package name is listed in APPS_ALLOWED_ON_RESTRICTED_NETWORKS setting. - @GuardedBy("this") - private final Set mAppsAllowedOnRestrictedNetworks = new ArraySet<>(); - - private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); - final Uri packageData = intent.getData(); - final String packageName = - packageData != null ? packageData.getSchemeSpecificPart() : null; - - if (Intent.ACTION_PACKAGE_ADDED.equals(action)) { - onPackageAdded(packageName, uid); - } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) { - onPackageRemoved(packageName, uid); - } else { - Log.wtf(TAG, "received unexpected intent: " + action); - } - } - }; - - /** - * Dependencies of PermissionMonitor, for injection in tests. - */ - @VisibleForTesting - public static class Dependencies { - /** - * Get device first sdk version. - */ - public int getDeviceFirstSdkInt() { - return Build.VERSION.DEVICE_INITIAL_SDK_INT; - } - - /** - * Get apps allowed to use restricted networks via ConnectivitySettingsManager. - */ - public Set getAppsAllowedOnRestrictedNetworks(@NonNull Context context) { - return ConnectivitySettingsManager.getAppsAllowedOnRestrictedNetworks(context); - } - - /** - * Register ContentObserver for given Uri. - */ - public void registerContentObserver(@NonNull Context context, @NonNull Uri uri, - boolean notifyForDescendants, @NonNull ContentObserver observer) { - context.getContentResolver().registerContentObserver( - uri, notifyForDescendants, observer); - } - } - - public PermissionMonitor(@NonNull final Context context, @NonNull final INetd netd) { - this(context, netd, new Dependencies()); - } - - @VisibleForTesting - PermissionMonitor(@NonNull final Context context, @NonNull final INetd netd, - @NonNull final Dependencies deps) { - mPackageManager = context.getPackageManager(); - mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); - mSystemConfigManager = context.getSystemService(SystemConfigManager.class); - mNetd = netd; - mDeps = deps; - mContext = context; - } - - // Intended to be called only once at startup, after the system is ready. Installs a broadcast - // receiver to monitor ongoing UID changes, so this shouldn't/needn't be called again. - public synchronized void startMonitoring() { - log("Monitoring"); - - final Context userAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */); - final IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED); - intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); - intentFilter.addDataScheme("package"); - userAllContext.registerReceiver( - mIntentReceiver, intentFilter, null /* broadcastPermission */, - null /* scheduler */); - - // Register APPS_ALLOWED_ON_RESTRICTED_NETWORKS setting observer - mDeps.registerContentObserver( - userAllContext, - Settings.Secure.getUriFor(APPS_ALLOWED_ON_RESTRICTED_NETWORKS), - false /* notifyForDescendants */, - new ContentObserver(null) { - @Override - public void onChange(boolean selfChange) { - onSettingChanged(); - } - }); - - // Read APPS_ALLOWED_ON_RESTRICTED_NETWORKS setting and update - // mAppsAllowedOnRestrictedNetworks. - updateAppsAllowedOnRestrictedNetworks(mDeps.getAppsAllowedOnRestrictedNetworks(mContext)); - - List apps = mPackageManager.getInstalledPackages(GET_PERMISSIONS - | MATCH_ANY_USER); - if (apps == null) { - loge("No apps"); - return; - } - - SparseIntArray netdPermsUids = new SparseIntArray(); - - for (PackageInfo app : apps) { - int uid = app.applicationInfo != null ? app.applicationInfo.uid : INVALID_UID; - if (uid < 0) { - continue; - } - mAllApps.add(UserHandle.getAppId(uid)); - - boolean isNetwork = hasNetworkPermission(app); - boolean hasRestrictedPermission = hasRestrictedNetworkPermission(app); - - if (isNetwork || hasRestrictedPermission) { - Boolean permission = mApps.get(uid); - // If multiple packages share a UID (cf: android:sharedUserId) and ask for different - // permissions, don't downgrade (i.e., if it's already SYSTEM, leave it as is). - if (permission == null || permission == NETWORK) { - mApps.put(uid, hasRestrictedPermission); - } - } - - //TODO: unify the management of the permissions into one codepath. - int otherNetdPerms = getNetdPermissionMask(app.requestedPermissions, - app.requestedPermissionsFlags); - netdPermsUids.put(uid, netdPermsUids.get(uid) | otherNetdPerms); - } - - mUsers.addAll(mUserManager.getUserHandles(true /* excludeDying */)); - - final SparseArray netdPermToSystemPerm = new SparseArray<>(); - netdPermToSystemPerm.put(INetd.PERMISSION_INTERNET, INTERNET); - netdPermToSystemPerm.put(INetd.PERMISSION_UPDATE_DEVICE_STATS, UPDATE_DEVICE_STATS); - for (int i = 0; i < netdPermToSystemPerm.size(); i++) { - final int netdPermission = netdPermToSystemPerm.keyAt(i); - final String systemPermission = netdPermToSystemPerm.valueAt(i); - final int[] hasPermissionUids = - mSystemConfigManager.getSystemPermissionUids(systemPermission); - for (int j = 0; j < hasPermissionUids.length; j++) { - final int uid = hasPermissionUids[j]; - netdPermsUids.put(uid, netdPermsUids.get(uid) | netdPermission); - } - } - log("Users: " + mUsers.size() + ", Apps: " + mApps.size()); - update(mUsers, mApps, true); - sendPackagePermissionsToNetd(netdPermsUids); - } - - @VisibleForTesting - void updateAppsAllowedOnRestrictedNetworks(final Set apps) { - mAppsAllowedOnRestrictedNetworks.clear(); - mAppsAllowedOnRestrictedNetworks.addAll(apps); - } - - @VisibleForTesting - static boolean isVendorApp(@NonNull ApplicationInfo appInfo) { - return appInfo.isVendor() || appInfo.isOem() || appInfo.isProduct(); - } - - @VisibleForTesting - boolean isCarryoverPackage(final ApplicationInfo appInfo) { - if (appInfo == null) return false; - return (appInfo.targetSdkVersion < VERSION_Q && isVendorApp(appInfo)) - // Backward compatibility for b/114245686, on devices that launched before Q daemons - // and apps running as the system UID are exempted from this check. - || (appInfo.uid == SYSTEM_UID && mDeps.getDeviceFirstSdkInt() < VERSION_Q); - } - - @VisibleForTesting - boolean isAppAllowedOnRestrictedNetworks(@NonNull final PackageInfo app) { - // Check whether package name is in allowed on restricted networks app list. If so, this app - // can have netd system permission. - return mAppsAllowedOnRestrictedNetworks.contains(app.packageName); - } - - @VisibleForTesting - boolean hasPermission(@NonNull final PackageInfo app, @NonNull final String permission) { - if (app.requestedPermissions == null || app.requestedPermissionsFlags == null) { - return false; - } - final int index = CollectionUtils.indexOf(app.requestedPermissions, permission); - if (index < 0 || index >= app.requestedPermissionsFlags.length) return false; - return (app.requestedPermissionsFlags[index] & REQUESTED_PERMISSION_GRANTED) != 0; - } - - @VisibleForTesting - boolean hasNetworkPermission(@NonNull final PackageInfo app) { - return hasPermission(app, CHANGE_NETWORK_STATE); - } - - @VisibleForTesting - boolean hasRestrictedNetworkPermission(@NonNull final PackageInfo app) { - // TODO : remove carryover package check in the future(b/31479477). All apps should just - // request the appropriate permission for their use case since android Q. - return isCarryoverPackage(app.applicationInfo) || isAppAllowedOnRestrictedNetworks(app) - || hasPermission(app, PERMISSION_MAINLINE_NETWORK_STACK) - || hasPermission(app, NETWORK_STACK) - || hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS); - } - - /** Returns whether the given uid has using background network permission. */ - public synchronized boolean hasUseBackgroundNetworksPermission(final int uid) { - // Apps with any of the CHANGE_NETWORK_STATE, NETWORK_STACK, CONNECTIVITY_INTERNAL or - // CONNECTIVITY_USE_RESTRICTED_NETWORKS permission has the permission to use background - // networks. mApps contains the result of checks for both hasNetworkPermission and - // hasRestrictedNetworkPermission. If uid is in the mApps list that means uid has one of - // permissions at least. - return mApps.containsKey(uid); - } - - /** - * Returns whether the given uid has permission to use restricted networks. - */ - public synchronized boolean hasRestrictedNetworksPermission(int uid) { - return Boolean.TRUE.equals(mApps.get(uid)); - } - - private void update(Set users, Map apps, boolean add) { - List network = new ArrayList<>(); - List system = new ArrayList<>(); - for (Entry app : apps.entrySet()) { - List list = app.getValue() ? system : network; - for (UserHandle user : users) { - if (user == null) continue; - - list.add(user.getUid(app.getKey())); - } - } - try { - if (add) { - mNetd.networkSetPermissionForUser(INetd.PERMISSION_NETWORK, toIntArray(network)); - mNetd.networkSetPermissionForUser(INetd.PERMISSION_SYSTEM, toIntArray(system)); - } else { - mNetd.networkClearPermissionForUser(toIntArray(network)); - mNetd.networkClearPermissionForUser(toIntArray(system)); - } - } catch (RemoteException e) { - loge("Exception when updating permissions: " + e); - } - } - - /** - * Called when a user is added. See {link #ACTION_USER_ADDED}. - * - * @param user The integer userHandle of the added user. See {@link #EXTRA_USER_HANDLE}. - * - * @hide - */ - public synchronized void onUserAdded(@NonNull UserHandle user) { - mUsers.add(user); - - Set users = new HashSet<>(); - users.add(user); - update(users, mApps, true); - } - - /** - * Called when an user is removed. See {link #ACTION_USER_REMOVED}. - * - * @param user The integer userHandle of the removed user. See {@link #EXTRA_USER_HANDLE}. - * - * @hide - */ - public synchronized void onUserRemoved(@NonNull UserHandle user) { - mUsers.remove(user); - - Set users = new HashSet<>(); - users.add(user); - update(users, mApps, false); - } - - @VisibleForTesting - protected Boolean highestPermissionForUid(Boolean currentPermission, String name) { - if (currentPermission == SYSTEM) { - return currentPermission; - } - try { - final PackageInfo app = mPackageManager.getPackageInfo(name, - GET_PERMISSIONS | MATCH_ANY_USER); - final boolean isNetwork = hasNetworkPermission(app); - final boolean hasRestrictedPermission = hasRestrictedNetworkPermission(app); - if (isNetwork || hasRestrictedPermission) { - currentPermission = hasRestrictedPermission; - } - } catch (NameNotFoundException e) { - // App not found. - loge("NameNotFoundException " + name); - } - return currentPermission; - } - - private int getPermissionForUid(final int uid) { - int permission = INetd.PERMISSION_NONE; - // Check all the packages for this UID. The UID has the permission if any of the - // packages in it has the permission. - final String[] packages = mPackageManager.getPackagesForUid(uid); - if (packages != null && packages.length > 0) { - for (String name : packages) { - final PackageInfo app = getPackageInfo(name); - if (app != null && app.requestedPermissions != null) { - permission |= getNetdPermissionMask(app.requestedPermissions, - app.requestedPermissionsFlags); - } - } - } else { - // The last package of this uid is removed from device. Clean the package up. - permission = INetd.PERMISSION_UNINSTALLED; - } - return permission; - } - - /** - * Called when a package is added. - * - * @param packageName The name of the new package. - * @param uid The uid of the new package. - * - * @hide - */ - public synchronized void onPackageAdded(@NonNull final String packageName, final int uid) { - // TODO: Netd is using appId for checking traffic permission. Correct the methods that are - // using appId instead of uid actually - sendPackagePermissionsForUid(UserHandle.getAppId(uid), getPermissionForUid(uid)); - - // If multiple packages share a UID (cf: android:sharedUserId) and ask for different - // permissions, don't downgrade (i.e., if it's already SYSTEM, leave it as is). - final Boolean permission = highestPermissionForUid(mApps.get(uid), packageName); - if (permission != mApps.get(uid)) { - mApps.put(uid, permission); - - Map apps = new HashMap<>(); - apps.put(uid, permission); - update(mUsers, apps, true); - } - - // If the newly-installed package falls within some VPN's uid range, update Netd with it. - // This needs to happen after the mApps update above, since removeBypassingUids() depends - // on mApps to check if the package can bypass VPN. - for (Map.Entry> vpn : mVpnUidRanges.entrySet()) { - if (UidRange.containsUid(vpn.getValue(), uid)) { - final Set changedUids = new HashSet<>(); - changedUids.add(uid); - removeBypassingUids(changedUids, /* vpnAppUid */ -1); - updateVpnUids(vpn.getKey(), changedUids, true); - } - } - mAllApps.add(UserHandle.getAppId(uid)); - } - - private Boolean highestUidNetworkPermission(int uid) { - Boolean permission = null; - final String[] packages = mPackageManager.getPackagesForUid(uid); - if (!CollectionUtils.isEmpty(packages)) { - for (String name : packages) { - permission = highestPermissionForUid(permission, name); - if (permission == SYSTEM) { - break; - } - } - } - return permission; - } - - /** - * Called when a package is removed. - * - * @param packageName The name of the removed package or null. - * @param uid containing the integer uid previously assigned to the package. - * - * @hide - */ - public synchronized void onPackageRemoved(@NonNull final String packageName, final int uid) { - // TODO: Netd is using appId for checking traffic permission. Correct the methods that are - // using appId instead of uid actually - sendPackagePermissionsForUid(UserHandle.getAppId(uid), getPermissionForUid(uid)); - - // If the newly-removed package falls within some VPN's uid range, update Netd with it. - // This needs to happen before the mApps update below, since removeBypassingUids() depends - // on mApps to check if the package can bypass VPN. - for (Map.Entry> vpn : mVpnUidRanges.entrySet()) { - if (UidRange.containsUid(vpn.getValue(), uid)) { - final Set changedUids = new HashSet<>(); - changedUids.add(uid); - removeBypassingUids(changedUids, /* vpnAppUid */ -1); - updateVpnUids(vpn.getKey(), changedUids, false); - } - } - // If the package has been removed from all users on the device, clear it form mAllApps. - if (mPackageManager.getNameForUid(uid) == null) { - mAllApps.remove(UserHandle.getAppId(uid)); - } - - Map apps = new HashMap<>(); - final Boolean permission = highestUidNetworkPermission(uid); - if (permission == SYSTEM) { - // An app with this UID still has the SYSTEM permission. - // Therefore, this UID must already have the SYSTEM permission. - // Nothing to do. - return; - } - - if (permission == mApps.get(uid)) { - // The permissions of this UID have not changed. Nothing to do. - return; - } else if (permission != null) { - mApps.put(uid, permission); - apps.put(uid, permission); - update(mUsers, apps, true); - } else { - mApps.remove(uid); - apps.put(uid, NETWORK); // doesn't matter which permission we pick here - update(mUsers, apps, false); - } - } - - private static int getNetdPermissionMask(String[] requestedPermissions, - int[] requestedPermissionsFlags) { - int permissions = 0; - if (requestedPermissions == null || requestedPermissionsFlags == null) return permissions; - for (int i = 0; i < requestedPermissions.length; i++) { - if (requestedPermissions[i].equals(INTERNET) - && ((requestedPermissionsFlags[i] & REQUESTED_PERMISSION_GRANTED) != 0)) { - permissions |= INetd.PERMISSION_INTERNET; - } - if (requestedPermissions[i].equals(UPDATE_DEVICE_STATS) - && ((requestedPermissionsFlags[i] & REQUESTED_PERMISSION_GRANTED) != 0)) { - permissions |= INetd.PERMISSION_UPDATE_DEVICE_STATS; - } - } - return permissions; - } - - private PackageInfo getPackageInfo(String packageName) { - try { - PackageInfo app = mPackageManager.getPackageInfo(packageName, GET_PERMISSIONS - | MATCH_ANY_USER); - return app; - } catch (NameNotFoundException e) { - return null; - } - } - - /** - * Called when a new set of UID ranges are added to an active VPN network - * - * @param iface The active VPN network's interface name - * @param rangesToAdd The new UID ranges to be added to the network - * @param vpnAppUid The uid of the VPN app - */ - public synchronized void onVpnUidRangesAdded(@NonNull String iface, Set rangesToAdd, - int vpnAppUid) { - // Calculate the list of new app uids under the VPN due to the new UID ranges and update - // Netd about them. Because mAllApps only contains appIds instead of uids, the result might - // be an overestimation if an app is not installed on the user on which the VPN is running, - // but that's safe. - final Set changedUids = intersectUids(rangesToAdd, mAllApps); - removeBypassingUids(changedUids, vpnAppUid); - updateVpnUids(iface, changedUids, true); - if (mVpnUidRanges.containsKey(iface)) { - mVpnUidRanges.get(iface).addAll(rangesToAdd); - } else { - mVpnUidRanges.put(iface, new HashSet(rangesToAdd)); - } - } - - /** - * Called when a set of UID ranges are removed from an active VPN network - * - * @param iface The VPN network's interface name - * @param rangesToRemove Existing UID ranges to be removed from the VPN network - * @param vpnAppUid The uid of the VPN app - */ - public synchronized void onVpnUidRangesRemoved(@NonNull String iface, - Set rangesToRemove, int vpnAppUid) { - // Calculate the list of app uids that are no longer under the VPN due to the removed UID - // ranges and update Netd about them. - final Set changedUids = intersectUids(rangesToRemove, mAllApps); - removeBypassingUids(changedUids, vpnAppUid); - updateVpnUids(iface, changedUids, false); - Set existingRanges = mVpnUidRanges.getOrDefault(iface, null); - if (existingRanges == null) { - loge("Attempt to remove unknown vpn uid Range iface = " + iface); - return; - } - existingRanges.removeAll(rangesToRemove); - if (existingRanges.size() == 0) { - mVpnUidRanges.remove(iface); - } - } - - /** - * Compute the intersection of a set of UidRanges and appIds. Returns a set of uids - * that satisfies: - * 1. falls into one of the UidRange - * 2. matches one of the appIds - */ - private Set intersectUids(Set ranges, Set appIds) { - Set result = new HashSet<>(); - for (UidRange range : ranges) { - for (int userId = range.getStartUser(); userId <= range.getEndUser(); userId++) { - for (int appId : appIds) { - final UserHandle handle = UserHandle.of(userId); - if (handle == null) continue; - - final int uid = handle.getUid(appId); - if (range.contains(uid)) { - result.add(uid); - } - } - } - } - return result; - } - - /** - * Remove all apps which can elect to bypass the VPN from the list of uids - * - * An app can elect to bypass the VPN if it hold SYSTEM permission, or if its the active VPN - * app itself. - * - * @param uids The list of uids to operate on - * @param vpnAppUid The uid of the VPN app - */ - private void removeBypassingUids(Set uids, int vpnAppUid) { - uids.remove(vpnAppUid); - uids.removeIf(uid -> mApps.getOrDefault(uid, NETWORK) == SYSTEM); - } - - /** - * Update netd about the list of uids that are under an active VPN connection which they cannot - * bypass. - * - * This is to instruct netd to set up appropriate filtering rules for these uids, such that they - * can only receive ingress packets from the VPN's tunnel interface (and loopback). - * - * @param iface the interface name of the active VPN connection - * @param add {@code true} if the uids are to be added to the interface, {@code false} if they - * are to be removed from the interface. - */ - private void updateVpnUids(String iface, Set uids, boolean add) { - if (uids.size() == 0) { - return; - } - try { - if (add) { - mNetd.firewallAddUidInterfaceRules(iface, toIntArray(uids)); - } else { - mNetd.firewallRemoveUidInterfaceRules(toIntArray(uids)); - } - } catch (ServiceSpecificException e) { - // Silently ignore exception when device does not support eBPF, otherwise just log - // the exception and do not crash - if (e.errorCode != OsConstants.EOPNOTSUPP) { - loge("Exception when updating permissions: ", e); - } - } catch (RemoteException e) { - loge("Exception when updating permissions: ", e); - } - } - - /** - * Called by PackageListObserver when a package is installed/uninstalled. Send the updated - * permission information to netd. - * - * @param uid the app uid of the package installed - * @param permissions the permissions the app requested and netd cares about. - * - * @hide - */ - @VisibleForTesting - void sendPackagePermissionsForUid(int uid, int permissions) { - SparseIntArray netdPermissionsAppIds = new SparseIntArray(); - netdPermissionsAppIds.put(uid, permissions); - sendPackagePermissionsToNetd(netdPermissionsAppIds); - } - - /** - * Called by packageManagerService to send IPC to netd. Grant or revoke the INTERNET - * and/or UPDATE_DEVICE_STATS permission of the uids in array. - * - * @param netdPermissionsAppIds integer pairs of uids and the permission granted to it. If the - * permission is 0, revoke all permissions of that uid. - * - * @hide - */ - @VisibleForTesting - void sendPackagePermissionsToNetd(SparseIntArray netdPermissionsAppIds) { - if (mNetd == null) { - Log.e(TAG, "Failed to get the netd service"); - return; - } - ArrayList allPermissionAppIds = new ArrayList<>(); - ArrayList internetPermissionAppIds = new ArrayList<>(); - ArrayList updateStatsPermissionAppIds = new ArrayList<>(); - ArrayList noPermissionAppIds = new ArrayList<>(); - ArrayList uninstalledAppIds = new ArrayList<>(); - for (int i = 0; i < netdPermissionsAppIds.size(); i++) { - int permissions = netdPermissionsAppIds.valueAt(i); - switch(permissions) { - case (INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS): - allPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); - break; - case INetd.PERMISSION_INTERNET: - internetPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); - break; - case INetd.PERMISSION_UPDATE_DEVICE_STATS: - updateStatsPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); - break; - case INetd.PERMISSION_NONE: - noPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); - break; - case INetd.PERMISSION_UNINSTALLED: - uninstalledAppIds.add(netdPermissionsAppIds.keyAt(i)); - break; - default: - Log.e(TAG, "unknown permission type: " + permissions + "for uid: " - + netdPermissionsAppIds.keyAt(i)); - } - } - try { - // TODO: add a lock inside netd to protect IPC trafficSetNetPermForUids() - if (allPermissionAppIds.size() != 0) { - mNetd.trafficSetNetPermForUids( - INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS, - toIntArray(allPermissionAppIds)); - } - if (internetPermissionAppIds.size() != 0) { - mNetd.trafficSetNetPermForUids(INetd.PERMISSION_INTERNET, - toIntArray(internetPermissionAppIds)); - } - if (updateStatsPermissionAppIds.size() != 0) { - mNetd.trafficSetNetPermForUids(INetd.PERMISSION_UPDATE_DEVICE_STATS, - toIntArray(updateStatsPermissionAppIds)); - } - if (noPermissionAppIds.size() != 0) { - mNetd.trafficSetNetPermForUids(INetd.PERMISSION_NONE, - toIntArray(noPermissionAppIds)); - } - if (uninstalledAppIds.size() != 0) { - mNetd.trafficSetNetPermForUids(INetd.PERMISSION_UNINSTALLED, - toIntArray(uninstalledAppIds)); - } - } catch (RemoteException e) { - Log.e(TAG, "Pass appId list of special permission failed." + e); - } - } - - /** Should only be used by unit tests */ - @VisibleForTesting - public Set getVpnUidRanges(String iface) { - return mVpnUidRanges.get(iface); - } - - private synchronized void onSettingChanged() { - // Step1. Update apps allowed to use restricted networks and compute the set of packages to - // update. - final Set packagesToUpdate = new ArraySet<>(mAppsAllowedOnRestrictedNetworks); - updateAppsAllowedOnRestrictedNetworks(mDeps.getAppsAllowedOnRestrictedNetworks(mContext)); - packagesToUpdate.addAll(mAppsAllowedOnRestrictedNetworks); - - final Map updatedApps = new HashMap<>(); - final Map removedApps = new HashMap<>(); - - // Step2. For each package to update, find out its new permission. - for (String app : packagesToUpdate) { - final PackageInfo info = getPackageInfo(app); - if (info == null || info.applicationInfo == null) continue; - - final int uid = info.applicationInfo.uid; - final Boolean permission = highestUidNetworkPermission(uid); - - if (null == permission) { - removedApps.put(uid, NETWORK); // Doesn't matter which permission is set here. - mApps.remove(uid); - } else { - updatedApps.put(uid, permission); - mApps.put(uid, permission); - } - } - - // Step3. Update or revoke permission for uids with netd. - update(mUsers, updatedApps, true /* add */); - update(mUsers, removedApps, false /* add */); - } - - /** Dump info to dumpsys */ - public void dump(IndentingPrintWriter pw) { - pw.println("Interface filtering rules:"); - pw.increaseIndent(); - for (Map.Entry> vpn : mVpnUidRanges.entrySet()) { - pw.println("Interface: " + vpn.getKey()); - pw.println("UIDs: " + vpn.getValue().toString()); - pw.println(); - } - pw.decreaseIndent(); - } - - private static void log(String s) { - if (DBG) { - Log.d(TAG, s); - } - } - - private static void loge(String s) { - Log.e(TAG, s); - } - - private static void loge(String s, Throwable e) { - Log.e(TAG, s, e); - } -} diff --git a/packages/Connectivity/service/src/com/android/server/connectivity/ProfileNetworkPreferences.java b/packages/Connectivity/service/src/com/android/server/connectivity/ProfileNetworkPreferences.java deleted file mode 100644 index dd2815d9e2e3c..0000000000000 --- a/packages/Connectivity/service/src/com/android/server/connectivity/ProfileNetworkPreferences.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.net.NetworkCapabilities; -import android.os.UserHandle; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * A data class containing all the per-profile network preferences. - * - * A given profile can only have one preference. - */ -public class ProfileNetworkPreferences { - /** - * A single preference, as it applies to a given user profile. - */ - public static class Preference { - @NonNull public final UserHandle user; - // Capabilities are only null when sending an object to remove the setting for a user - @Nullable public final NetworkCapabilities capabilities; - - public Preference(@NonNull final UserHandle user, - @Nullable final NetworkCapabilities capabilities) { - this.user = user; - this.capabilities = null == capabilities ? null : new NetworkCapabilities(capabilities); - } - - /** toString */ - public String toString() { - return "[ProfileNetworkPreference user=" + user + " caps=" + capabilities + "]"; - } - } - - @NonNull public final List preferences; - - public ProfileNetworkPreferences() { - preferences = Collections.EMPTY_LIST; - } - - private ProfileNetworkPreferences(@NonNull final List list) { - preferences = Collections.unmodifiableList(list); - } - - /** - * Returns a new object consisting of this object plus the passed preference. - * - * If a preference already exists for the same user, it will be replaced by the passed - * preference. Passing a Preference object containing a null capabilities object is equivalent - * to (and indeed, implemented as) removing the preference for this user. - */ - public ProfileNetworkPreferences plus(@NonNull final Preference pref) { - final ArrayList newPrefs = new ArrayList<>(); - for (final Preference existingPref : preferences) { - if (!existingPref.user.equals(pref.user)) { - newPrefs.add(existingPref); - } - } - if (null != pref.capabilities) { - newPrefs.add(pref); - } - return new ProfileNetworkPreferences(newPrefs); - } - - public boolean isEmpty() { - return preferences.isEmpty(); - } -} diff --git a/packages/Connectivity/service/src/com/android/server/connectivity/ProxyTracker.java b/packages/Connectivity/service/src/com/android/server/connectivity/ProxyTracker.java deleted file mode 100644 index bc0929c206598..0000000000000 --- a/packages/Connectivity/service/src/com/android/server/connectivity/ProxyTracker.java +++ /dev/null @@ -1,358 +0,0 @@ -/** - * Copyright (c) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import static android.net.ConnectivitySettingsManager.GLOBAL_HTTP_PROXY_EXCLUSION_LIST; -import static android.net.ConnectivitySettingsManager.GLOBAL_HTTP_PROXY_HOST; -import static android.net.ConnectivitySettingsManager.GLOBAL_HTTP_PROXY_PAC; -import static android.net.ConnectivitySettingsManager.GLOBAL_HTTP_PROXY_PORT; -import static android.provider.Settings.Global.HTTP_PROXY; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.net.Network; -import android.net.PacProxyManager; -import android.net.Proxy; -import android.net.ProxyInfo; -import android.net.Uri; -import android.os.Binder; -import android.os.Handler; -import android.os.UserHandle; -import android.provider.Settings; -import android.text.TextUtils; -import android.util.Log; -import android.util.Pair; - -import com.android.internal.annotations.GuardedBy; -import com.android.net.module.util.ProxyUtils; - -import java.util.Collections; -import java.util.Objects; - -/** - * A class to handle proxy for ConnectivityService. - * - * @hide - */ -public class ProxyTracker { - private static final String TAG = ProxyTracker.class.getSimpleName(); - private static final boolean DBG = true; - - // EXTRA_PROXY_INFO is now @removed. In order to continue sending it, hardcode its value here. - // The Proxy.EXTRA_PROXY_INFO constant is not visible to this code because android.net.Proxy - // a hidden platform constant not visible to mainline modules. - private static final String EXTRA_PROXY_INFO = "android.intent.extra.PROXY_INFO"; - - @NonNull - private final Context mContext; - - @NonNull - private final Object mProxyLock = new Object(); - // The global proxy is the proxy that is set device-wide, overriding any network-specific - // proxy. Note however that proxies are hints ; the system does not enforce their use. Hence - // this value is only for querying. - @Nullable - @GuardedBy("mProxyLock") - private ProxyInfo mGlobalProxy = null; - // The default proxy is the proxy that applies to no particular network if the global proxy - // is not set. Individual networks have their own settings that override this. This member - // is set through setDefaultProxy, which is called when the default network changes proxies - // in its LinkProperties, or when ConnectivityService switches to a new default network, or - // when PacProxyService resolves the proxy. - @Nullable - @GuardedBy("mProxyLock") - private volatile ProxyInfo mDefaultProxy = null; - // Whether the default proxy is enabled. - @GuardedBy("mProxyLock") - private boolean mDefaultProxyEnabled = true; - - private final Handler mConnectivityServiceHandler; - - private final PacProxyManager mPacProxyManager; - - private class PacProxyInstalledListener implements PacProxyManager.PacProxyInstalledListener { - private final int mEvent; - - PacProxyInstalledListener(int event) { - mEvent = event; - } - - public void onPacProxyInstalled(@Nullable Network network, @NonNull ProxyInfo proxy) { - mConnectivityServiceHandler - .sendMessage(mConnectivityServiceHandler - .obtainMessage(mEvent, new Pair<>(network, proxy))); - } - } - - public ProxyTracker(@NonNull final Context context, - @NonNull final Handler connectivityServiceInternalHandler, final int pacChangedEvent) { - mContext = context; - mConnectivityServiceHandler = connectivityServiceInternalHandler; - mPacProxyManager = context.getSystemService(PacProxyManager.class); - - PacProxyInstalledListener listener = new PacProxyInstalledListener(pacChangedEvent); - mPacProxyManager.addPacProxyInstalledListener( - mConnectivityServiceHandler::post, listener); - } - - // Convert empty ProxyInfo's to null as null-checks are used to determine if proxies are present - // (e.g. if mGlobalProxy==null fall back to network-specific proxy, if network-specific - // proxy is null then there is no proxy in place). - @Nullable - private static ProxyInfo canonicalizeProxyInfo(@Nullable final ProxyInfo proxy) { - if (proxy != null && TextUtils.isEmpty(proxy.getHost()) - && Uri.EMPTY.equals(proxy.getPacFileUrl())) { - return null; - } - return proxy; - } - - // ProxyInfo equality functions with a couple modifications over ProxyInfo.equals() to make it - // better for determining if a new proxy broadcast is necessary: - // 1. Canonicalize empty ProxyInfos to null so an empty proxy compares equal to null so as to - // avoid unnecessary broadcasts. - // 2. Make sure all parts of the ProxyInfo's compare true, including the host when a PAC URL - // is in place. This is important so legacy PAC resolver (see com.android.proxyhandler) - // changes aren't missed. The legacy PAC resolver pretends to be a simple HTTP proxy but - // actually uses the PAC to resolve; this results in ProxyInfo's with PAC URL, host and port - // all set. - public static boolean proxyInfoEqual(@Nullable final ProxyInfo a, @Nullable final ProxyInfo b) { - final ProxyInfo pa = canonicalizeProxyInfo(a); - final ProxyInfo pb = canonicalizeProxyInfo(b); - // ProxyInfo.equals() doesn't check hosts when PAC URLs are present, but we need to check - // hosts even when PAC URLs are present to account for the legacy PAC resolver. - return Objects.equals(pa, pb) && (pa == null || Objects.equals(pa.getHost(), pb.getHost())); - } - - /** - * Gets the default system-wide proxy. - * - * This will return the global proxy if set, otherwise the default proxy if in use. Note - * that this is not necessarily the proxy that any given process should use, as the right - * proxy for a process is the proxy for the network this process will use, which may be - * different from this value. This value is simply the default in case there is no proxy set - * in the network that will be used by a specific process. - * @return The default system-wide proxy or null if none. - */ - @Nullable - public ProxyInfo getDefaultProxy() { - // This information is already available as a world read/writable jvm property. - synchronized (mProxyLock) { - if (mGlobalProxy != null) return mGlobalProxy; - if (mDefaultProxyEnabled) return mDefaultProxy; - return null; - } - } - - /** - * Gets the global proxy. - * - * @return The global proxy or null if none. - */ - @Nullable - public ProxyInfo getGlobalProxy() { - // This information is already available as a world read/writable jvm property. - synchronized (mProxyLock) { - return mGlobalProxy; - } - } - - /** - * Read the global proxy settings and cache them in memory. - */ - public void loadGlobalProxy() { - if (loadDeprecatedGlobalHttpProxy()) { - return; - } - ContentResolver res = mContext.getContentResolver(); - String host = Settings.Global.getString(res, GLOBAL_HTTP_PROXY_HOST); - int port = Settings.Global.getInt(res, GLOBAL_HTTP_PROXY_PORT, 0); - String exclList = Settings.Global.getString(res, GLOBAL_HTTP_PROXY_EXCLUSION_LIST); - String pacFileUrl = Settings.Global.getString(res, GLOBAL_HTTP_PROXY_PAC); - if (!TextUtils.isEmpty(host) || !TextUtils.isEmpty(pacFileUrl)) { - ProxyInfo proxyProperties; - if (!TextUtils.isEmpty(pacFileUrl)) { - proxyProperties = ProxyInfo.buildPacProxy(Uri.parse(pacFileUrl)); - } else { - proxyProperties = ProxyInfo.buildDirectProxy(host, port, - ProxyUtils.exclusionStringAsList(exclList)); - } - if (!proxyProperties.isValid()) { - if (DBG) Log.d(TAG, "Invalid proxy properties, ignoring: " + proxyProperties); - return; - } - - synchronized (mProxyLock) { - mGlobalProxy = proxyProperties; - } - - if (!TextUtils.isEmpty(pacFileUrl)) { - mConnectivityServiceHandler.post( - () -> mPacProxyManager.setCurrentProxyScriptUrl(proxyProperties)); - } - } - } - - /** - * Read the global proxy from the deprecated Settings.Global.HTTP_PROXY setting and apply it. - * Returns {@code true} when global proxy was set successfully from deprecated setting. - */ - public boolean loadDeprecatedGlobalHttpProxy() { - final String proxy = Settings.Global.getString(mContext.getContentResolver(), HTTP_PROXY); - if (!TextUtils.isEmpty(proxy)) { - String data[] = proxy.split(":"); - if (data.length == 0) { - return false; - } - - final String proxyHost = data[0]; - int proxyPort = 8080; - if (data.length > 1) { - try { - proxyPort = Integer.parseInt(data[1]); - } catch (NumberFormatException e) { - return false; - } - } - final ProxyInfo p = ProxyInfo.buildDirectProxy(proxyHost, proxyPort, - Collections.emptyList()); - setGlobalProxy(p); - return true; - } - return false; - } - - /** - * Sends the system broadcast informing apps about a new proxy configuration. - * - * Confusingly this method also sets the PAC file URL. TODO : separate this, it has nothing - * to do in a "sendProxyBroadcast" method. - */ - public void sendProxyBroadcast() { - final ProxyInfo defaultProxy = getDefaultProxy(); - final ProxyInfo proxyInfo = null != defaultProxy ? - defaultProxy : ProxyInfo.buildDirectProxy("", 0, Collections.emptyList()); - mPacProxyManager.setCurrentProxyScriptUrl(proxyInfo); - - if (!shouldSendBroadcast(proxyInfo)) { - return; - } - if (DBG) Log.d(TAG, "sending Proxy Broadcast for " + proxyInfo); - Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION); - intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING | - Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - intent.putExtra(EXTRA_PROXY_INFO, proxyInfo); - final long ident = Binder.clearCallingIdentity(); - try { - mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - private boolean shouldSendBroadcast(ProxyInfo proxy) { - return Uri.EMPTY.equals(proxy.getPacFileUrl()) || proxy.getPort() > 0; - } - - /** - * Sets the global proxy in memory. Also writes the values to the global settings of the device. - * - * @param proxyInfo the proxy spec, or null for no proxy. - */ - public void setGlobalProxy(@Nullable ProxyInfo proxyInfo) { - synchronized (mProxyLock) { - // ProxyInfo#equals is not commutative :( and is public API, so it can't be fixed. - if (proxyInfo == mGlobalProxy) return; - if (proxyInfo != null && proxyInfo.equals(mGlobalProxy)) return; - if (mGlobalProxy != null && mGlobalProxy.equals(proxyInfo)) return; - - final String host; - final int port; - final String exclList; - final String pacFileUrl; - if (proxyInfo != null && (!TextUtils.isEmpty(proxyInfo.getHost()) || - !Uri.EMPTY.equals(proxyInfo.getPacFileUrl()))) { - if (!proxyInfo.isValid()) { - if (DBG) Log.d(TAG, "Invalid proxy properties, ignoring: " + proxyInfo); - return; - } - mGlobalProxy = new ProxyInfo(proxyInfo); - host = mGlobalProxy.getHost(); - port = mGlobalProxy.getPort(); - exclList = ProxyUtils.exclusionListAsString(mGlobalProxy.getExclusionList()); - pacFileUrl = Uri.EMPTY.equals(proxyInfo.getPacFileUrl()) - ? "" : proxyInfo.getPacFileUrl().toString(); - } else { - host = ""; - port = 0; - exclList = ""; - pacFileUrl = ""; - mGlobalProxy = null; - } - final ContentResolver res = mContext.getContentResolver(); - final long token = Binder.clearCallingIdentity(); - try { - Settings.Global.putString(res, GLOBAL_HTTP_PROXY_HOST, host); - Settings.Global.putInt(res, GLOBAL_HTTP_PROXY_PORT, port); - Settings.Global.putString(res, GLOBAL_HTTP_PROXY_EXCLUSION_LIST, exclList); - Settings.Global.putString(res, GLOBAL_HTTP_PROXY_PAC, pacFileUrl); - } finally { - Binder.restoreCallingIdentity(token); - } - - sendProxyBroadcast(); - } - } - - /** - * Sets the default proxy for the device. - * - * The default proxy is the proxy used for networks that do not have a specific proxy. - * @param proxyInfo the proxy spec, or null for no proxy. - */ - public void setDefaultProxy(@Nullable ProxyInfo proxyInfo) { - synchronized (mProxyLock) { - if (Objects.equals(mDefaultProxy, proxyInfo)) return; - if (proxyInfo != null && !proxyInfo.isValid()) { - if (DBG) Log.d(TAG, "Invalid proxy properties, ignoring: " + proxyInfo); - return; - } - - // This call could be coming from the PacProxyService, containing the port of the - // local proxy. If this new proxy matches the global proxy then copy this proxy to the - // global (to get the correct local port), and send a broadcast. - // TODO: Switch PacProxyService to have its own message to send back rather than - // reusing EVENT_HAS_CHANGED_PROXY and this call to handleApplyDefaultProxy. - if ((mGlobalProxy != null) && (proxyInfo != null) - && (!Uri.EMPTY.equals(proxyInfo.getPacFileUrl())) - && proxyInfo.getPacFileUrl().equals(mGlobalProxy.getPacFileUrl())) { - mGlobalProxy = proxyInfo; - sendProxyBroadcast(); - return; - } - mDefaultProxy = proxyInfo; - - if (mGlobalProxy != null) return; - if (mDefaultProxyEnabled) { - sendProxyBroadcast(); - } - } - } -} diff --git a/packages/Connectivity/service/src/com/android/server/connectivity/QosCallbackAgentConnection.java b/packages/Connectivity/service/src/com/android/server/connectivity/QosCallbackAgentConnection.java deleted file mode 100644 index 534dbe7699a75..0000000000000 --- a/packages/Connectivity/service/src/com/android/server/connectivity/QosCallbackAgentConnection.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import static android.net.QosCallbackException.EX_TYPE_FILTER_NONE; - -import android.annotation.NonNull; -import android.net.IQosCallback; -import android.net.Network; -import android.net.QosCallbackException; -import android.net.QosFilter; -import android.net.QosSession; -import android.os.IBinder; -import android.os.RemoteException; -import android.telephony.data.EpsBearerQosSessionAttributes; -import android.telephony.data.NrQosSessionAttributes; -import android.util.Log; - -import java.util.Objects; - -/** - * Wraps callback related information and sends messages between network agent and the application. - *

      - * This is a satellite class of {@link com.android.server.ConnectivityService} and not meant - * to be used in other contexts. - * - * @hide - */ -class QosCallbackAgentConnection implements IBinder.DeathRecipient { - private static final String TAG = QosCallbackAgentConnection.class.getSimpleName(); - private static final boolean DBG = false; - - private final int mAgentCallbackId; - @NonNull private final QosCallbackTracker mQosCallbackTracker; - @NonNull private final IQosCallback mCallback; - @NonNull private final IBinder mBinder; - @NonNull private final QosFilter mFilter; - @NonNull private final NetworkAgentInfo mNetworkAgentInfo; - - private final int mUid; - - /** - * Gets the uid - * @return uid - */ - int getUid() { - return mUid; - } - - /** - * Gets the binder - * @return binder - */ - @NonNull - IBinder getBinder() { - return mBinder; - } - - /** - * Gets the callback id - * - * @return callback id - */ - int getAgentCallbackId() { - return mAgentCallbackId; - } - - /** - * Gets the network tied to the callback of this connection - * - * @return network - */ - @NonNull - Network getNetwork() { - return mFilter.getNetwork(); - } - - QosCallbackAgentConnection(@NonNull final QosCallbackTracker qosCallbackTracker, - final int agentCallbackId, - @NonNull final IQosCallback callback, - @NonNull final QosFilter filter, - final int uid, - @NonNull final NetworkAgentInfo networkAgentInfo) { - Objects.requireNonNull(qosCallbackTracker, "qosCallbackTracker must be non-null"); - Objects.requireNonNull(callback, "callback must be non-null"); - Objects.requireNonNull(filter, "filter must be non-null"); - Objects.requireNonNull(networkAgentInfo, "networkAgentInfo must be non-null"); - - mQosCallbackTracker = qosCallbackTracker; - mAgentCallbackId = agentCallbackId; - mCallback = callback; - mFilter = filter; - mUid = uid; - mBinder = mCallback.asBinder(); - mNetworkAgentInfo = networkAgentInfo; - } - - @Override - public void binderDied() { - logw("binderDied: binder died with callback id: " + mAgentCallbackId); - mQosCallbackTracker.unregisterCallback(mCallback); - } - - void unlinkToDeathRecipient() { - mBinder.unlinkToDeath(this, 0); - } - - // Returns false if the NetworkAgent was never notified. - boolean sendCmdRegisterCallback() { - final int exceptionType = mFilter.validate(); - if (exceptionType != EX_TYPE_FILTER_NONE) { - try { - if (DBG) log("sendCmdRegisterCallback: filter validation failed"); - mCallback.onError(exceptionType); - } catch (final RemoteException e) { - loge("sendCmdRegisterCallback:", e); - } - return false; - } - - try { - mBinder.linkToDeath(this, 0); - } catch (final RemoteException e) { - loge("failed linking to death recipient", e); - return false; - } - mNetworkAgentInfo.onQosFilterCallbackRegistered(mAgentCallbackId, mFilter); - return true; - } - - void sendCmdUnregisterCallback() { - if (DBG) log("sendCmdUnregisterCallback: unregistering"); - mNetworkAgentInfo.onQosCallbackUnregistered(mAgentCallbackId); - } - - void sendEventEpsQosSessionAvailable(final QosSession session, - final EpsBearerQosSessionAttributes attributes) { - try { - if (DBG) log("sendEventEpsQosSessionAvailable: sending..."); - mCallback.onQosEpsBearerSessionAvailable(session, attributes); - } catch (final RemoteException e) { - loge("sendEventEpsQosSessionAvailable: remote exception", e); - } - } - - void sendEventNrQosSessionAvailable(final QosSession session, - final NrQosSessionAttributes attributes) { - try { - if (DBG) log("sendEventNrQosSessionAvailable: sending..."); - mCallback.onNrQosSessionAvailable(session, attributes); - } catch (final RemoteException e) { - loge("sendEventNrQosSessionAvailable: remote exception", e); - } - } - - void sendEventQosSessionLost(@NonNull final QosSession session) { - try { - if (DBG) log("sendEventQosSessionLost: sending..."); - mCallback.onQosSessionLost(session); - } catch (final RemoteException e) { - loge("sendEventQosSessionLost: remote exception", e); - } - } - - void sendEventQosCallbackError(@QosCallbackException.ExceptionType final int exceptionType) { - try { - if (DBG) log("sendEventQosCallbackError: sending..."); - mCallback.onError(exceptionType); - } catch (final RemoteException e) { - loge("sendEventQosCallbackError: remote exception", e); - } - } - - private static void log(@NonNull final String msg) { - Log.d(TAG, msg); - } - - private static void logw(@NonNull final String msg) { - Log.w(TAG, msg); - } - - private static void loge(@NonNull final String msg, final Throwable t) { - Log.e(TAG, msg, t); - } -} diff --git a/packages/Connectivity/service/src/com/android/server/connectivity/QosCallbackTracker.java b/packages/Connectivity/service/src/com/android/server/connectivity/QosCallbackTracker.java deleted file mode 100644 index b6ab47b276e33..0000000000000 --- a/packages/Connectivity/service/src/com/android/server/connectivity/QosCallbackTracker.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.net.IQosCallback; -import android.net.Network; -import android.net.QosCallbackException; -import android.net.QosFilter; -import android.net.QosSession; -import android.os.Binder; -import android.os.Handler; -import android.os.IBinder; -import android.telephony.data.EpsBearerQosSessionAttributes; -import android.telephony.data.NrQosSessionAttributes; -import android.util.Log; - -import com.android.net.module.util.CollectionUtils; -import com.android.server.ConnectivityService; - -import java.util.ArrayList; -import java.util.List; - -/** - * Tracks qos callbacks and handles the communication between the network agent and application. - *

      - * Any method prefixed by handle must be called from the - * {@link com.android.server.ConnectivityService} handler thread. - * - * @hide - */ -public class QosCallbackTracker { - private static final String TAG = QosCallbackTracker.class.getSimpleName(); - private static final boolean DBG = true; - - @NonNull - private final Handler mConnectivityServiceHandler; - - @NonNull - private final ConnectivityService.PerUidCounter mNetworkRequestCounter; - - /** - * Each agent gets a unique callback id that is used to proxy messages back to the original - * callback. - *

      - * Note: The fact that this is initialized to 0 is to ensure that the thread running - * {@link #handleRegisterCallback(IQosCallback, QosFilter, int, NetworkAgentInfo)} sees the - * initialized value. This would not necessarily be the case if the value was initialized to - * the non-default value. - *

      - * Note: The term previous does not apply to the first callback id that is assigned. - */ - private int mPreviousAgentCallbackId = 0; - - @NonNull - private final List mConnections = new ArrayList<>(); - - /** - * - * @param connectivityServiceHandler must be the same handler used with - * {@link com.android.server.ConnectivityService} - * @param networkRequestCounter keeps track of the number of open requests under a given - * uid - */ - public QosCallbackTracker(@NonNull final Handler connectivityServiceHandler, - final ConnectivityService.PerUidCounter networkRequestCounter) { - mConnectivityServiceHandler = connectivityServiceHandler; - mNetworkRequestCounter = networkRequestCounter; - } - - /** - * Registers the callback with the tracker - * - * @param callback the callback to register - * @param filter the filter being registered alongside the callback - */ - public void registerCallback(@NonNull final IQosCallback callback, - @NonNull final QosFilter filter, @NonNull final NetworkAgentInfo networkAgentInfo) { - final int uid = Binder.getCallingUid(); - - // Enforce that the number of requests under this uid has exceeded the allowed number - mNetworkRequestCounter.incrementCountOrThrow(uid); - - mConnectivityServiceHandler.post( - () -> handleRegisterCallback(callback, filter, uid, networkAgentInfo)); - } - - private void handleRegisterCallback(@NonNull final IQosCallback callback, - @NonNull final QosFilter filter, final int uid, - @NonNull final NetworkAgentInfo networkAgentInfo) { - final QosCallbackAgentConnection ac = - handleRegisterCallbackInternal(callback, filter, uid, networkAgentInfo); - if (ac != null) { - if (DBG) log("handleRegisterCallback: added callback " + ac.getAgentCallbackId()); - mConnections.add(ac); - } else { - mNetworkRequestCounter.decrementCount(uid); - } - } - - private QosCallbackAgentConnection handleRegisterCallbackInternal( - @NonNull final IQosCallback callback, - @NonNull final QosFilter filter, final int uid, - @NonNull final NetworkAgentInfo networkAgentInfo) { - final IBinder binder = callback.asBinder(); - if (CollectionUtils.any(mConnections, c -> c.getBinder().equals(binder))) { - // A duplicate registration would have only made this far due to a programming error. - logwtf("handleRegisterCallback: Callbacks can only be register once."); - return null; - } - - mPreviousAgentCallbackId = mPreviousAgentCallbackId + 1; - final int newCallbackId = mPreviousAgentCallbackId; - - final QosCallbackAgentConnection ac = - new QosCallbackAgentConnection(this, newCallbackId, callback, - filter, uid, networkAgentInfo); - - final int exceptionType = filter.validate(); - if (exceptionType != QosCallbackException.EX_TYPE_FILTER_NONE) { - ac.sendEventQosCallbackError(exceptionType); - return null; - } - - // Only add to the callback maps if the NetworkAgent successfully registered it - if (!ac.sendCmdRegisterCallback()) { - // There was an issue when registering the agent - if (DBG) log("handleRegisterCallback: error sending register callback"); - mNetworkRequestCounter.decrementCount(uid); - return null; - } - return ac; - } - - /** - * Unregisters callback - * @param callback callback to unregister - */ - public void unregisterCallback(@NonNull final IQosCallback callback) { - mConnectivityServiceHandler.post(() -> handleUnregisterCallback(callback.asBinder(), true)); - } - - private void handleUnregisterCallback(@NonNull final IBinder binder, - final boolean sendToNetworkAgent) { - final int connIndex = - CollectionUtils.indexOf(mConnections, c -> c.getBinder().equals(binder)); - if (connIndex < 0) { - logw("handleUnregisterCallback: no matching agentConnection"); - return; - } - final QosCallbackAgentConnection agentConnection = mConnections.get(connIndex); - - if (DBG) { - log("handleUnregisterCallback: unregister " - + agentConnection.getAgentCallbackId()); - } - - mNetworkRequestCounter.decrementCount(agentConnection.getUid()); - mConnections.remove(agentConnection); - - if (sendToNetworkAgent) { - agentConnection.sendCmdUnregisterCallback(); - } - agentConnection.unlinkToDeathRecipient(); - } - - /** - * Called when the NetworkAgent sends the qos session available event for EPS - * - * @param qosCallbackId the callback id that the qos session is now available to - * @param session the qos session that is now available - * @param attributes the qos attributes that are now available on the qos session - */ - public void sendEventEpsQosSessionAvailable(final int qosCallbackId, - final QosSession session, - final EpsBearerQosSessionAttributes attributes) { - runOnAgentConnection(qosCallbackId, "sendEventEpsQosSessionAvailable: ", - ac -> ac.sendEventEpsQosSessionAvailable(session, attributes)); - } - - /** - * Called when the NetworkAgent sends the qos session available event for NR - * - * @param qosCallbackId the callback id that the qos session is now available to - * @param session the qos session that is now available - * @param attributes the qos attributes that are now available on the qos session - */ - public void sendEventNrQosSessionAvailable(final int qosCallbackId, - final QosSession session, - final NrQosSessionAttributes attributes) { - runOnAgentConnection(qosCallbackId, "sendEventNrQosSessionAvailable: ", - ac -> ac.sendEventNrQosSessionAvailable(session, attributes)); - } - - /** - * Called when the NetworkAgent sends the qos session lost event - * - * @param qosCallbackId the callback id that lost the qos session - * @param session the corresponding qos session - */ - public void sendEventQosSessionLost(final int qosCallbackId, - final QosSession session) { - runOnAgentConnection(qosCallbackId, "sendEventQosSessionLost: ", - ac -> ac.sendEventQosSessionLost(session)); - } - - /** - * Called when the NetworkAgent sends the qos session on error event - * - * @param qosCallbackId the callback id that should receive the exception - * @param exceptionType the type of exception that caused the callback to error - */ - public void sendEventQosCallbackError(final int qosCallbackId, - @QosCallbackException.ExceptionType final int exceptionType) { - runOnAgentConnection(qosCallbackId, "sendEventQosCallbackError: ", - ac -> { - ac.sendEventQosCallbackError(exceptionType); - handleUnregisterCallback(ac.getBinder(), false); - }); - } - - /** - * Unregisters all callbacks associated to this network agent - * - * Note: Must be called on the connectivity service handler thread - * - * @param network the network that was released - */ - public void handleNetworkReleased(@Nullable final Network network) { - // Iterate in reverse order as agent connections will be removed when unregistering - for (int i = mConnections.size() - 1; i >= 0; i--) { - final QosCallbackAgentConnection agentConnection = mConnections.get(i); - if (!agentConnection.getNetwork().equals(network)) continue; - agentConnection.sendEventQosCallbackError( - QosCallbackException.EX_TYPE_FILTER_NETWORK_RELEASED); - - // Call unregister workflow w\o sending anything to agent since it is disconnected. - handleUnregisterCallback(agentConnection.getBinder(), false); - } - } - - private interface AgentConnectionAction { - void execute(@NonNull QosCallbackAgentConnection agentConnection); - } - - @Nullable - private void runOnAgentConnection(final int qosCallbackId, - @NonNull final String logPrefix, - @NonNull final AgentConnectionAction action) { - mConnectivityServiceHandler.post(() -> { - final int acIndex = CollectionUtils.indexOf(mConnections, - c -> c.getAgentCallbackId() == qosCallbackId); - if (acIndex == -1) { - loge(logPrefix + ": " + qosCallbackId + " missing callback id"); - return; - } - - action.execute(mConnections.get(acIndex)); - }); - } - - private static void log(final String msg) { - Log.d(TAG, msg); - } - - private static void logw(final String msg) { - Log.w(TAG, msg); - } - - private static void loge(final String msg) { - Log.e(TAG, msg); - } - - private static void logwtf(final String msg) { - Log.wtf(TAG, msg); - } -} diff --git a/packages/Connectivity/service/src/com/android/server/connectivity/TcpKeepaliveController.java b/packages/Connectivity/service/src/com/android/server/connectivity/TcpKeepaliveController.java deleted file mode 100644 index 73f34751731ef..0000000000000 --- a/packages/Connectivity/service/src/com/android/server/connectivity/TcpKeepaliveController.java +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.server.connectivity; - -import static android.net.SocketKeepalive.DATA_RECEIVED; -import static android.net.SocketKeepalive.ERROR_INVALID_SOCKET; -import static android.net.SocketKeepalive.ERROR_SOCKET_NOT_IDLE; -import static android.net.SocketKeepalive.ERROR_UNSUPPORTED; -import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR; -import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT; -import static android.system.OsConstants.ENOPROTOOPT; -import static android.system.OsConstants.FIONREAD; -import static android.system.OsConstants.IPPROTO_IP; -import static android.system.OsConstants.IPPROTO_TCP; -import static android.system.OsConstants.IP_TOS; -import static android.system.OsConstants.IP_TTL; - -import static com.android.server.connectivity.OsCompat.TIOCOUTQ; - -import android.annotation.NonNull; -import android.net.InvalidPacketException; -import android.net.NetworkUtils; -import android.net.SocketKeepalive.InvalidSocketException; -import android.net.TcpKeepalivePacketData; -import android.net.TcpKeepalivePacketDataParcelable; -import android.net.TcpRepairWindow; -import android.net.util.KeepalivePacketDataUtil; -import android.os.Handler; -import android.os.MessageQueue; -import android.os.Messenger; -import android.system.ErrnoException; -import android.system.Os; -import android.util.Log; -import android.util.SparseArray; - -import com.android.internal.annotations.GuardedBy; -import com.android.server.connectivity.KeepaliveTracker.KeepaliveInfo; - -import java.io.FileDescriptor; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.net.SocketException; - -/** - * Manage tcp socket which offloads tcp keepalive. - * - * The input socket will be changed to repair mode and the application - * will not have permission to read/write data. If the application wants - * to write data, it must stop tcp keepalive offload to leave repair mode - * first. If a remote packet arrives, repair mode will be turned off and - * offload will be stopped. The application will receive a callback to know - * it can start reading data. - * - * {start,stop}SocketMonitor are thread-safe, but care must be taken in the - * order in which they are called. Please note that while calling - * {@link #startSocketMonitor(FileDescriptor, Messenger, int)} multiple times - * with either the same slot or the same FileDescriptor without stopping it in - * between will result in an exception, calling {@link #stopSocketMonitor(int)} - * multiple times with the same int is explicitly a no-op. - * Please also note that switching the socket to repair mode is not synchronized - * with either of these operations and has to be done in an orderly fashion - * with stopSocketMonitor. Take care in calling these in the right order. - * @hide - */ -public class TcpKeepaliveController { - private static final String TAG = "TcpKeepaliveController"; - private static final boolean DBG = false; - - private final MessageQueue mFdHandlerQueue; - - private static final int FD_EVENTS = EVENT_INPUT | EVENT_ERROR; - - // Reference include/uapi/linux/tcp.h - private static final int TCP_REPAIR = 19; - private static final int TCP_REPAIR_QUEUE = 20; - private static final int TCP_QUEUE_SEQ = 21; - private static final int TCP_NO_QUEUE = 0; - private static final int TCP_RECV_QUEUE = 1; - private static final int TCP_SEND_QUEUE = 2; - private static final int TCP_REPAIR_OFF = 0; - private static final int TCP_REPAIR_ON = 1; - // Reference include/uapi/linux/sockios.h - private static final int SIOCINQ = FIONREAD; - private static final int SIOCOUTQ = TIOCOUTQ; - - /** - * Keeps track of packet listeners. - * Key: slot number of keepalive offload. - * Value: {@link FileDescriptor} being listened to. - */ - @GuardedBy("mListeners") - private final SparseArray mListeners = new SparseArray<>(); - - public TcpKeepaliveController(final Handler connectivityServiceHandler) { - mFdHandlerQueue = connectivityServiceHandler.getLooper().getQueue(); - } - - /** Build tcp keepalive packet. */ - public static TcpKeepalivePacketData getTcpKeepalivePacket(@NonNull FileDescriptor fd) - throws InvalidPacketException, InvalidSocketException { - try { - final TcpKeepalivePacketDataParcelable tcpDetails = switchToRepairMode(fd); - return KeepalivePacketDataUtil.fromStableParcelable(tcpDetails); - } catch (InvalidPacketException | InvalidSocketException e) { - switchOutOfRepairMode(fd); - throw e; - } - } - /** - * Switch the tcp socket to repair mode and query detail tcp information. - * - * @param fd the fd of socket on which to use keepalive offload. - * @return a {@link TcpKeepalivePacketDataParcelable} object for current - * tcp/ip information. - */ - private static TcpKeepalivePacketDataParcelable switchToRepairMode(FileDescriptor fd) - throws InvalidSocketException { - if (DBG) Log.i(TAG, "switchToRepairMode to start tcp keepalive : " + fd); - final TcpKeepalivePacketDataParcelable tcpDetails = new TcpKeepalivePacketDataParcelable(); - final SocketAddress srcSockAddr; - final SocketAddress dstSockAddr; - final TcpRepairWindow trw; - - // Query source address and port. - try { - srcSockAddr = Os.getsockname(fd); - } catch (ErrnoException e) { - Log.e(TAG, "Get sockname fail: ", e); - throw new InvalidSocketException(ERROR_INVALID_SOCKET, e); - } - if (srcSockAddr instanceof InetSocketAddress) { - tcpDetails.srcAddress = getAddress((InetSocketAddress) srcSockAddr); - tcpDetails.srcPort = getPort((InetSocketAddress) srcSockAddr); - } else { - Log.e(TAG, "Invalid or mismatched SocketAddress"); - throw new InvalidSocketException(ERROR_INVALID_SOCKET); - } - // Query destination address and port. - try { - dstSockAddr = Os.getpeername(fd); - } catch (ErrnoException e) { - Log.e(TAG, "Get peername fail: ", e); - throw new InvalidSocketException(ERROR_INVALID_SOCKET, e); - } - if (dstSockAddr instanceof InetSocketAddress) { - tcpDetails.dstAddress = getAddress((InetSocketAddress) dstSockAddr); - tcpDetails.dstPort = getPort((InetSocketAddress) dstSockAddr); - } else { - Log.e(TAG, "Invalid or mismatched peer SocketAddress"); - throw new InvalidSocketException(ERROR_INVALID_SOCKET); - } - - // Query sequence and ack number - dropAllIncomingPackets(fd, true); - try { - // Switch to tcp repair mode. - Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR, TCP_REPAIR_ON); - - // Check if socket is idle. - if (!isSocketIdle(fd)) { - Log.e(TAG, "Socket is not idle"); - throw new InvalidSocketException(ERROR_SOCKET_NOT_IDLE); - } - // Query write sequence number from SEND_QUEUE. - Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR_QUEUE, TCP_SEND_QUEUE); - tcpDetails.seq = OsCompat.getsockoptInt(fd, IPPROTO_TCP, TCP_QUEUE_SEQ); - // Query read sequence number from RECV_QUEUE. - Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR_QUEUE, TCP_RECV_QUEUE); - tcpDetails.ack = OsCompat.getsockoptInt(fd, IPPROTO_TCP, TCP_QUEUE_SEQ); - // Switch to NO_QUEUE to prevent illegal socket read/write in repair mode. - Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR_QUEUE, TCP_NO_QUEUE); - // Finally, check if socket is still idle. TODO : this check needs to move to - // after starting polling to prevent a race. - if (!isReceiveQueueEmpty(fd)) { - Log.e(TAG, "Fatal: receive queue of this socket is not empty"); - throw new InvalidSocketException(ERROR_INVALID_SOCKET); - } - if (!isSendQueueEmpty(fd)) { - Log.e(TAG, "Socket is not idle"); - throw new InvalidSocketException(ERROR_SOCKET_NOT_IDLE); - } - - // Query tcp window size. - trw = NetworkUtils.getTcpRepairWindow(fd); - tcpDetails.rcvWnd = trw.rcvWnd; - tcpDetails.rcvWndScale = trw.rcvWndScale; - if (tcpDetails.srcAddress.length == 4 /* V4 address length */) { - // Query TOS. - tcpDetails.tos = OsCompat.getsockoptInt(fd, IPPROTO_IP, IP_TOS); - // Query TTL. - tcpDetails.ttl = OsCompat.getsockoptInt(fd, IPPROTO_IP, IP_TTL); - } - } catch (ErrnoException e) { - Log.e(TAG, "Exception reading TCP state from socket", e); - if (e.errno == ENOPROTOOPT) { - // ENOPROTOOPT may happen in kernel version lower than 4.8. - // Treat it as ERROR_UNSUPPORTED. - throw new InvalidSocketException(ERROR_UNSUPPORTED, e); - } else { - throw new InvalidSocketException(ERROR_INVALID_SOCKET, e); - } - } finally { - dropAllIncomingPackets(fd, false); - } - - // Keepalive sequence number is last sequence number - 1. If it couldn't be retrieved, - // then it must be set to -1, so decrement in all cases. - tcpDetails.seq = tcpDetails.seq - 1; - - return tcpDetails; - } - - /** - * Switch the tcp socket out of repair mode. - * - * @param fd the fd of socket to switch back to normal. - */ - private static void switchOutOfRepairMode(@NonNull final FileDescriptor fd) { - try { - Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR, TCP_REPAIR_OFF); - } catch (ErrnoException e) { - Log.e(TAG, "Cannot switch socket out of repair mode", e); - // Well, there is not much to do here to recover - } - } - - /** - * Start monitoring incoming packets. - * - * @param fd socket fd to monitor. - * @param ki a {@link KeepaliveInfo} that tracks information about a socket keepalive. - * @param slot keepalive slot. - */ - public void startSocketMonitor(@NonNull final FileDescriptor fd, - @NonNull final KeepaliveInfo ki, final int slot) - throws IllegalArgumentException, InvalidSocketException { - synchronized (mListeners) { - if (null != mListeners.get(slot)) { - throw new IllegalArgumentException("This slot is already taken"); - } - for (int i = 0; i < mListeners.size(); ++i) { - if (fd.equals(mListeners.valueAt(i))) { - Log.e(TAG, "This fd is already registered."); - throw new InvalidSocketException(ERROR_INVALID_SOCKET); - } - } - mFdHandlerQueue.addOnFileDescriptorEventListener(fd, FD_EVENTS, (readyFd, events) -> { - // This can't be called twice because the queue guarantees that once the listener - // is unregistered it can't be called again, even for a message that arrived - // before it was unregistered. - final int reason; - if (0 != (events & EVENT_ERROR)) { - reason = ERROR_INVALID_SOCKET; - } else { - reason = DATA_RECEIVED; - } - ki.onFileDescriptorInitiatedStop(reason); - // The listener returns the new set of events to listen to. Because 0 means no - // event, the listener gets unregistered. - return 0; - }); - mListeners.put(slot, fd); - } - } - - /** Stop socket monitor */ - // This slot may have been stopped automatically already because the socket received data, - // was closed on the other end or otherwise suffered some error. In this case, this function - // is a no-op. - public void stopSocketMonitor(final int slot) { - final FileDescriptor fd; - synchronized (mListeners) { - fd = mListeners.get(slot); - if (null == fd) return; - mListeners.remove(slot); - } - mFdHandlerQueue.removeOnFileDescriptorEventListener(fd); - if (DBG) Log.d(TAG, "Moving socket out of repair mode for stop : " + fd); - switchOutOfRepairMode(fd); - } - - private static byte [] getAddress(InetSocketAddress inetAddr) { - return inetAddr.getAddress().getAddress(); - } - - private static int getPort(InetSocketAddress inetAddr) { - return inetAddr.getPort(); - } - - private static boolean isSocketIdle(FileDescriptor fd) throws ErrnoException { - return isReceiveQueueEmpty(fd) && isSendQueueEmpty(fd); - } - - private static boolean isReceiveQueueEmpty(FileDescriptor fd) - throws ErrnoException { - final int result = OsCompat.ioctlInt(fd, SIOCINQ); - if (result != 0) { - Log.e(TAG, "Read queue has data"); - return false; - } - return true; - } - - private static boolean isSendQueueEmpty(FileDescriptor fd) - throws ErrnoException { - final int result = OsCompat.ioctlInt(fd, SIOCOUTQ); - if (result != 0) { - Log.e(TAG, "Write queue has data"); - return false; - } - return true; - } - - private static void dropAllIncomingPackets(FileDescriptor fd, boolean enable) - throws InvalidSocketException { - try { - if (enable) { - NetworkUtils.attachDropAllBPFFilter(fd); - } else { - NetworkUtils.detachBPFFilter(fd); - } - } catch (SocketException e) { - Log.e(TAG, "Socket Exception: ", e); - throw new InvalidSocketException(ERROR_INVALID_SOCKET, e); - } - } -} diff --git a/packages/Connectivity/tests/OWNERS b/packages/Connectivity/tests/OWNERS deleted file mode 100644 index d3836d4c6c574..0000000000000 --- a/packages/Connectivity/tests/OWNERS +++ /dev/null @@ -1,8 +0,0 @@ -set noparent - -codewiz@google.com -jchalard@google.com -junyulai@google.com -lorenzo@google.com -reminv@google.com -satk@google.com diff --git a/packages/Connectivity/tests/TEST_MAPPING b/packages/Connectivity/tests/TEST_MAPPING deleted file mode 100644 index 502f885ceb785..0000000000000 --- a/packages/Connectivity/tests/TEST_MAPPING +++ /dev/null @@ -1,34 +0,0 @@ -{ - "presubmit": [ - { - "name": "FrameworksNetIntegrationTests" - } - ], - "postsubmit": [ - { - "name": "FrameworksNetDeflakeTest" - } - ], - "auto-postsubmit": [ - // Test tag for automotive targets. These are only running in postsubmit so as to harden the - // automotive targets to avoid introducing additional test flake and build time. The plan for - // presubmit testing for auto is to augment the existing tests to cover auto use cases as well. - // Additionally, this tag is used in targeted test suites to limit resource usage on the test - // infra during the hardening phase. - // TODO: this tag to be removed once the above is no longer an issue. - { - "name": "FrameworksNetTests" - }, - { - "name": "FrameworksNetIntegrationTests" - }, - { - "name": "FrameworksNetDeflakeTest" - } - ], - "imports": [ - { - "path": "packages/modules/Connectivity" - } - ] -} \ No newline at end of file diff --git a/packages/Connectivity/tests/common/Android.bp b/packages/Connectivity/tests/common/Android.bp deleted file mode 100644 index 73314532a52f2..0000000000000 --- a/packages/Connectivity/tests/common/Android.bp +++ /dev/null @@ -1,67 +0,0 @@ -// -// 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. -// - -// Tests in this folder are included both in unit tests and CTS. -// They must be fast and stable, and exercise public or test APIs. -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_base_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_base_license"], -} - -java_library { - name: "FrameworksNetCommonTests", - defaults: ["framework-connectivity-test-defaults"], - srcs: [ - "java/**/*.java", - "java/**/*.kt", - ], - static_libs: [ - "androidx.core_core", - "androidx.test.rules", - "junit", - "mockito-target-minus-junit4", - "modules-utils-build", - "net-tests-utils", - "net-utils-framework-common", - "platform-test-annotations", - ], - libs: [ - "android.test.base.stubs", - ], -} - -// defaults for tests that need to build against framework-connectivity's @hide APIs -// Only usable from targets that have visibility on framework-connectivity.impl. -// Instead of using this, consider avoiding to depend on hidden connectivity APIs in -// tests. -java_defaults { - name: "framework-connectivity-test-defaults", - sdk_version: "core_platform", // tests can use @CorePlatformApi's - libs: [ - // order matters: classes in framework-connectivity are resolved before framework, - // meaning @hide APIs in framework-connectivity are resolved before @SystemApi - // stubs in framework - "framework-connectivity.impl", - "framework", - - // if sdk_version="" this gets automatically included, but here we need to add manually. - "framework-res", - ], -} diff --git a/packages/Connectivity/tests/common/java/ParseExceptionTest.kt b/packages/Connectivity/tests/common/java/ParseExceptionTest.kt deleted file mode 100644 index b702d61a9fe16..0000000000000 --- a/packages/Connectivity/tests/common/java/ParseExceptionTest.kt +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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. - */ - -import android.net.ParseException -import android.os.Build -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.filters.SmallTest -import com.android.testutils.DevSdkIgnoreRule -import junit.framework.Assert.assertEquals -import junit.framework.Assert.assertNull -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith - -@SmallTest -@RunWith(AndroidJUnit4::class) -class ParseExceptionTest { - @get:Rule - val ignoreRule = DevSdkIgnoreRule(ignoreClassUpTo = Build.VERSION_CODES.R) - - @Test - fun testConstructor_WithCause() { - val testMessage = "Test message" - val base = Exception("Test") - val exception = ParseException(testMessage, base) - - assertEquals(testMessage, exception.response) - assertEquals(base, exception.cause) - } - - @Test - fun testConstructor_NoCause() { - val testMessage = "Test message" - val exception = ParseException(testMessage) - - assertEquals(testMessage, exception.response) - assertNull(exception.cause) - } -} \ No newline at end of file diff --git a/packages/Connectivity/tests/common/java/android/net/CaptivePortalDataTest.kt b/packages/Connectivity/tests/common/java/android/net/CaptivePortalDataTest.kt deleted file mode 100644 index 18a93319b271c..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/CaptivePortalDataTest.kt +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net - -import android.os.Build -import androidx.test.filters.SmallTest -import com.android.modules.utils.build.SdkLevel -import com.android.testutils.assertParcelSane -import com.android.testutils.assertParcelingIsLossless -import com.android.testutils.DevSdkIgnoreRule -import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo -import com.android.testutils.DevSdkIgnoreRunner -import org.junit.Assert.assertFalse -import org.junit.Assert.assertTrue -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith -import kotlin.test.assertEquals -import kotlin.test.assertNotEquals - -@SmallTest -@RunWith(DevSdkIgnoreRunner::class) -@IgnoreUpTo(Build.VERSION_CODES.Q) -class CaptivePortalDataTest { - @Rule @JvmField - val ignoreRule = DevSdkIgnoreRule() - - private val data = CaptivePortalData.Builder() - .setRefreshTime(123L) - .setUserPortalUrl(Uri.parse("https://portal.example.com/test")) - .setVenueInfoUrl(Uri.parse("https://venue.example.com/test")) - .setSessionExtendable(true) - .setBytesRemaining(456L) - .setExpiryTime(789L) - .setCaptive(true) - .apply { - if (SdkLevel.isAtLeastS()) { - setVenueFriendlyName("venue friendly name") - } - } - .build() - - private val dataFromPasspoint = CaptivePortalData.Builder() - .setCaptive(true) - .apply { - if (SdkLevel.isAtLeastS()) { - setVenueFriendlyName("venue friendly name") - setUserPortalUrl(Uri.parse("https://tc.example.com/passpoint"), - CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) - setVenueInfoUrl(Uri.parse("https://venue.example.com/passpoint"), - CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) - } - } - .build() - - private fun makeBuilder() = CaptivePortalData.Builder(data) - - @Test - fun testParcelUnparcel() { - val fieldCount = if (SdkLevel.isAtLeastS()) 10 else 7 - assertParcelSane(data, fieldCount) - assertParcelSane(dataFromPasspoint, fieldCount) - - assertParcelingIsLossless(makeBuilder().setUserPortalUrl(null).build()) - assertParcelingIsLossless(makeBuilder().setVenueInfoUrl(null).build()) - } - - @Test - fun testEquals() { - assertEquals(data, makeBuilder().build()) - - assertNotEqualsAfterChange { it.setRefreshTime(456L) } - assertNotEqualsAfterChange { it.setUserPortalUrl(Uri.parse("https://example.com/")) } - assertNotEqualsAfterChange { it.setUserPortalUrl(null) } - assertNotEqualsAfterChange { it.setVenueInfoUrl(Uri.parse("https://example.com/")) } - assertNotEqualsAfterChange { it.setVenueInfoUrl(null) } - assertNotEqualsAfterChange { it.setSessionExtendable(false) } - assertNotEqualsAfterChange { it.setBytesRemaining(789L) } - assertNotEqualsAfterChange { it.setExpiryTime(12L) } - assertNotEqualsAfterChange { it.setCaptive(false) } - - if (SdkLevel.isAtLeastS()) { - assertNotEqualsAfterChange { it.setVenueFriendlyName("another friendly name") } - assertNotEqualsAfterChange { it.setVenueFriendlyName(null) } - - assertEquals(dataFromPasspoint, CaptivePortalData.Builder(dataFromPasspoint).build()) - assertNotEqualsAfterChange { it.setUserPortalUrl( - Uri.parse("https://tc.example.com/passpoint")) } - assertNotEqualsAfterChange { it.setUserPortalUrl( - Uri.parse("https://tc.example.com/passpoint"), - CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER) } - assertNotEqualsAfterChange { it.setUserPortalUrl( - Uri.parse("https://tc.example.com/other"), - CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) } - assertNotEqualsAfterChange { it.setUserPortalUrl( - Uri.parse("https://tc.example.com/passpoint"), - CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER) } - assertNotEqualsAfterChange { it.setVenueInfoUrl( - Uri.parse("https://venue.example.com/passpoint")) } - assertNotEqualsAfterChange { it.setVenueInfoUrl( - Uri.parse("https://venue.example.com/other"), - CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) } - assertNotEqualsAfterChange { it.setVenueInfoUrl( - Uri.parse("https://venue.example.com/passpoint"), - CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER) } - } - } - - @Test - fun testUserPortalUrl() { - assertEquals(Uri.parse("https://portal.example.com/test"), data.userPortalUrl) - } - - @Test - fun testVenueInfoUrl() { - assertEquals(Uri.parse("https://venue.example.com/test"), data.venueInfoUrl) - } - - @Test - fun testIsSessionExtendable() { - assertTrue(data.isSessionExtendable) - } - - @Test - fun testByteLimit() { - assertEquals(456L, data.byteLimit) - // Test byteLimit unset. - assertEquals(-1L, CaptivePortalData.Builder(null).build().byteLimit) - } - - @Test - fun testRefreshTimeMillis() { - assertEquals(123L, data.refreshTimeMillis) - } - - @Test - fun testExpiryTimeMillis() { - assertEquals(789L, data.expiryTimeMillis) - // Test expiryTimeMillis unset. - assertEquals(-1L, CaptivePortalData.Builder(null).build().expiryTimeMillis) - } - - @Test - fun testIsCaptive() { - assertTrue(data.isCaptive) - assertFalse(makeBuilder().setCaptive(false).build().isCaptive) - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.R) - fun testVenueFriendlyName() { - assertEquals("venue friendly name", data.venueFriendlyName) - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.R) - fun testGetVenueInfoUrlSource() { - assertEquals(CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER, - data.venueInfoUrlSource) - assertEquals(CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT, - dataFromPasspoint.venueInfoUrlSource) - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.R) - fun testGetUserPortalUrlSource() { - assertEquals(CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER, - data.userPortalUrlSource) - assertEquals(CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT, - dataFromPasspoint.userPortalUrlSource) - } - - private fun CaptivePortalData.mutate(mutator: (CaptivePortalData.Builder) -> Unit) = - CaptivePortalData.Builder(this).apply { mutator(this) }.build() - - private fun assertNotEqualsAfterChange(mutator: (CaptivePortalData.Builder) -> Unit) { - assertNotEquals(data, data.mutate(mutator)) - } -} \ No newline at end of file diff --git a/packages/Connectivity/tests/common/java/android/net/CaptivePortalTest.java b/packages/Connectivity/tests/common/java/android/net/CaptivePortalTest.java deleted file mode 100644 index 15d3398d43c0f..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/CaptivePortalTest.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static org.junit.Assert.assertEquals; - -import android.os.Build; -import android.os.RemoteException; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.testutils.DevSdkIgnoreRule; -import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter; -import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class CaptivePortalTest { - @Rule - public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule(); - - private static final int DEFAULT_TIMEOUT_MS = 5000; - private static final String TEST_PACKAGE_NAME = "com.google.android.test"; - - private final class MyCaptivePortalImpl extends ICaptivePortal.Stub { - int mCode = -1; - String mPackageName = null; - - @Override - public void appResponse(final int response) throws RemoteException { - mCode = response; - } - - @Override - public void appRequest(final int request) throws RemoteException { - mCode = request; - } - - // This is only @Override on R- - public void logEvent(int eventId, String packageName) throws RemoteException { - mCode = eventId; - mPackageName = packageName; - } - } - - private interface TestFunctor { - void useCaptivePortal(CaptivePortal o); - } - - private MyCaptivePortalImpl runCaptivePortalTest(TestFunctor f) { - final MyCaptivePortalImpl cp = new MyCaptivePortalImpl(); - f.useCaptivePortal(new CaptivePortal(cp.asBinder())); - return cp; - } - - @Test - public void testReportCaptivePortalDismissed() { - final MyCaptivePortalImpl result = - runCaptivePortalTest(c -> c.reportCaptivePortalDismissed()); - assertEquals(result.mCode, CaptivePortal.APP_RETURN_DISMISSED); - } - - @Test - public void testIgnoreNetwork() { - final MyCaptivePortalImpl result = runCaptivePortalTest(c -> c.ignoreNetwork()); - assertEquals(result.mCode, CaptivePortal.APP_RETURN_UNWANTED); - } - - @Test - public void testUseNetwork() { - final MyCaptivePortalImpl result = runCaptivePortalTest(c -> c.useNetwork()); - assertEquals(result.mCode, CaptivePortal.APP_RETURN_WANTED_AS_IS); - } - - @IgnoreUpTo(Build.VERSION_CODES.Q) - @Test - public void testReevaluateNetwork() { - final MyCaptivePortalImpl result = runCaptivePortalTest(c -> c.reevaluateNetwork()); - assertEquals(result.mCode, CaptivePortal.APP_REQUEST_REEVALUATION_REQUIRED); - } - - @IgnoreUpTo(Build.VERSION_CODES.R) - @Test - public void testLogEvent() { - /** - * From S testLogEvent is expected to do nothing but shouldn't crash (the API - * logEvent has been deprecated). - */ - final MyCaptivePortalImpl result = runCaptivePortalTest(c -> c.logEvent( - 0, - TEST_PACKAGE_NAME)); - } - - @IgnoreAfter(Build.VERSION_CODES.R) - @Test - public void testLogEvent_UntilR() { - final MyCaptivePortalImpl result = runCaptivePortalTest(c -> c.logEvent( - 42, TEST_PACKAGE_NAME)); - assertEquals(result.mCode, 42); - assertEquals(result.mPackageName, TEST_PACKAGE_NAME); - } -} diff --git a/packages/Connectivity/tests/common/java/android/net/DependenciesTest.java b/packages/Connectivity/tests/common/java/android/net/DependenciesTest.java deleted file mode 100644 index ac1c28a45462b..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/DependenciesTest.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.concurrent.TimeUnit; - -/** - * A simple class that tests dependencies to java standard tools from the - * Network stack. These tests are not meant to be comprehensive tests of - * the relevant APIs : such tests belong in the relevant test suite for - * these dependencies. Instead, this just makes sure coverage is present - * by calling the methods in the exact way (or a representative way of how) - * they are called in the network stack. - */ -@RunWith(AndroidJUnit4.class) -@SmallTest -public class DependenciesTest { - // Used to in ipmemorystore's RegularMaintenanceJobService to convert - // 24 hours into seconds - @Test - public void testTimeUnit() { - final int hours = 24; - final long inSeconds = TimeUnit.HOURS.toMillis(hours); - assertEquals(inSeconds, hours * 60 * 60 * 1000); - } - - private byte[] makeTrivialArray(final int size) { - final byte[] src = new byte[size]; - for (int i = 0; i < size; ++i) { - src[i] = (byte) i; - } - return src; - } - - // Used in ApfFilter to find an IP address from a byte array - @Test - public void testArrays() { - final int size = 128; - final byte[] src = makeTrivialArray(size); - - // Test copy - final int copySize = 16; - final int offset = 24; - final byte[] expected = new byte[copySize]; - for (int i = 0; i < copySize; ++i) { - expected[i] = (byte) (offset + i); - } - - final byte[] copy = Arrays.copyOfRange(src, offset, offset + copySize); - assertArrayEquals(expected, copy); - assertArrayEquals(new byte[0], Arrays.copyOfRange(src, size, size)); - } - - // Used mainly in the Dhcp code - @Test - public void testCopyOf() { - final byte[] src = makeTrivialArray(128); - final byte[] copy = Arrays.copyOf(src, src.length); - assertArrayEquals(src, copy); - assertFalse(src == copy); - - assertArrayEquals(new byte[0], Arrays.copyOf(src, 0)); - - final int excess = 16; - final byte[] biggerCopy = Arrays.copyOf(src, src.length + excess); - for (int i = src.length; i < src.length + excess; ++i) { - assertEquals(0, biggerCopy[i]); - } - for (int i = src.length - 1; i >= 0; --i) { - assertEquals(src[i], biggerCopy[i]); - } - } - - // Used mainly in DnsUtils but also various other places - @Test - public void testAsList() { - final int size = 24; - final Object[] src = new Object[size]; - final ArrayList expected = new ArrayList<>(size); - for (int i = 0; i < size; ++i) { - final Object o = new Object(); - src[i] = o; - expected.add(o); - } - assertEquals(expected, Arrays.asList(src)); - } -} diff --git a/packages/Connectivity/tests/common/java/android/net/DhcpInfoTest.java b/packages/Connectivity/tests/common/java/android/net/DhcpInfoTest.java deleted file mode 100644 index ab4726bab573b..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/DhcpInfoTest.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static com.android.net.module.util.Inet4AddressUtils.inet4AddressToIntHTL; -import static com.android.testutils.MiscAsserts.assertFieldCountEquals; -import static com.android.testutils.ParcelUtils.parcelingRoundTrip; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import android.annotation.Nullable; - -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.net.Inet4Address; -import java.net.InetAddress; - -@RunWith(AndroidJUnit4.class) -public class DhcpInfoTest { - private static final String STR_ADDR1 = "255.255.255.255"; - private static final String STR_ADDR2 = "127.0.0.1"; - private static final String STR_ADDR3 = "192.168.1.1"; - private static final String STR_ADDR4 = "192.168.1.0"; - private static final int LEASE_TIME = 9999; - - private int ipToInteger(String ipString) throws Exception { - return inet4AddressToIntHTL((Inet4Address) InetAddress.getByName(ipString)); - } - - private DhcpInfo createDhcpInfoObject() throws Exception { - final DhcpInfo dhcpInfo = new DhcpInfo(); - dhcpInfo.ipAddress = ipToInteger(STR_ADDR1); - dhcpInfo.gateway = ipToInteger(STR_ADDR2); - dhcpInfo.netmask = ipToInteger(STR_ADDR3); - dhcpInfo.dns1 = ipToInteger(STR_ADDR4); - dhcpInfo.dns2 = ipToInteger(STR_ADDR4); - dhcpInfo.serverAddress = ipToInteger(STR_ADDR2); - dhcpInfo.leaseDuration = LEASE_TIME; - return dhcpInfo; - } - - @Test - public void testConstructor() { - new DhcpInfo(); - } - - @Test - public void testToString() throws Exception { - final String expectedDefault = "ipaddr 0.0.0.0 gateway 0.0.0.0 netmask 0.0.0.0 " - + "dns1 0.0.0.0 dns2 0.0.0.0 DHCP server 0.0.0.0 lease 0 seconds"; - - DhcpInfo dhcpInfo = new DhcpInfo(); - - // Test default string. - assertEquals(expectedDefault, dhcpInfo.toString()); - - dhcpInfo = createDhcpInfoObject(); - - final String expected = "ipaddr " + STR_ADDR1 + " gateway " + STR_ADDR2 + " netmask " - + STR_ADDR3 + " dns1 " + STR_ADDR4 + " dns2 " + STR_ADDR4 + " DHCP server " - + STR_ADDR2 + " lease " + LEASE_TIME + " seconds"; - // Test with new values - assertEquals(expected, dhcpInfo.toString()); - } - - private boolean dhcpInfoEquals(@Nullable DhcpInfo left, @Nullable DhcpInfo right) { - if (left == null && right == null) return true; - - if (left == null || right == null) return false; - - return left.ipAddress == right.ipAddress - && left.gateway == right.gateway - && left.netmask == right.netmask - && left.dns1 == right.dns1 - && left.dns2 == right.dns2 - && left.serverAddress == right.serverAddress - && left.leaseDuration == right.leaseDuration; - } - - @Test - public void testParcelDhcpInfo() throws Exception { - // Cannot use assertParcelSane() here because this requires .equals() to work as - // defined, but DhcpInfo has a different legacy behavior that we cannot change. - final DhcpInfo dhcpInfo = createDhcpInfoObject(); - assertFieldCountEquals(7, DhcpInfo.class); - - final DhcpInfo dhcpInfoRoundTrip = parcelingRoundTrip(dhcpInfo); - assertTrue(dhcpInfoEquals(null, null)); - assertFalse(dhcpInfoEquals(null, dhcpInfoRoundTrip)); - assertFalse(dhcpInfoEquals(dhcpInfo, null)); - assertTrue(dhcpInfoEquals(dhcpInfo, dhcpInfoRoundTrip)); - } -} diff --git a/packages/Connectivity/tests/common/java/android/net/IpPrefixTest.java b/packages/Connectivity/tests/common/java/android/net/IpPrefixTest.java deleted file mode 100644 index 50ecb428359e2..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/IpPrefixTest.java +++ /dev/null @@ -1,374 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static com.android.testutils.MiscAsserts.assertEqualBothWays; -import static com.android.testutils.MiscAsserts.assertFieldCountEquals; -import static com.android.testutils.MiscAsserts.assertNotEqualEitherWay; -import static com.android.testutils.ParcelUtils.assertParcelingIsLossless; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.net.InetAddress; -import java.util.Random; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class IpPrefixTest { - - private static InetAddress address(String addr) { - return InetAddress.parseNumericAddress(addr); - } - - // Explicitly cast everything to byte because "error: possible loss of precision". - private static final byte[] IPV4_BYTES = { (byte) 192, (byte) 0, (byte) 2, (byte) 4}; - private static final byte[] IPV6_BYTES = { - (byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8, - (byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte) 0xef, - (byte) 0x0f, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xa0 - }; - - @Test - public void testConstructor() { - IpPrefix p; - try { - p = new IpPrefix((byte[]) null, 9); - fail("Expected NullPointerException: null byte array"); - } catch (RuntimeException expected) { } - - try { - p = new IpPrefix((InetAddress) null, 10); - fail("Expected NullPointerException: null InetAddress"); - } catch (RuntimeException expected) { } - - try { - p = new IpPrefix((String) null); - fail("Expected NullPointerException: null String"); - } catch (RuntimeException expected) { } - - - try { - byte[] b2 = {1, 2, 3, 4, 5}; - p = new IpPrefix(b2, 29); - fail("Expected IllegalArgumentException: invalid array length"); - } catch (IllegalArgumentException expected) { } - - try { - p = new IpPrefix("1.2.3.4"); - fail("Expected IllegalArgumentException: no prefix length"); - } catch (IllegalArgumentException expected) { } - - try { - p = new IpPrefix("1.2.3.4/"); - fail("Expected IllegalArgumentException: empty prefix length"); - } catch (IllegalArgumentException expected) { } - - try { - p = new IpPrefix("foo/32"); - fail("Expected IllegalArgumentException: invalid address"); - } catch (IllegalArgumentException expected) { } - - try { - p = new IpPrefix("1/32"); - fail("Expected IllegalArgumentException: deprecated IPv4 format"); - } catch (IllegalArgumentException expected) { } - - try { - p = new IpPrefix("1.2.3.256/32"); - fail("Expected IllegalArgumentException: invalid IPv4 address"); - } catch (IllegalArgumentException expected) { } - - try { - p = new IpPrefix("foo/32"); - fail("Expected IllegalArgumentException: non-address"); - } catch (IllegalArgumentException expected) { } - - try { - p = new IpPrefix("f00:::/32"); - fail("Expected IllegalArgumentException: invalid IPv6 address"); - } catch (IllegalArgumentException expected) { } - - p = new IpPrefix("/64"); - assertEquals("::/64", p.toString()); - - p = new IpPrefix("/128"); - assertEquals("::1/128", p.toString()); - - p = new IpPrefix("[2001:db8::123]/64"); - assertEquals("2001:db8::/64", p.toString()); - } - - @Test - public void testTruncation() { - IpPrefix p; - - p = new IpPrefix(IPV4_BYTES, 32); - assertEquals("192.0.2.4/32", p.toString()); - - p = new IpPrefix(IPV4_BYTES, 29); - assertEquals("192.0.2.0/29", p.toString()); - - p = new IpPrefix(IPV4_BYTES, 8); - assertEquals("192.0.0.0/8", p.toString()); - - p = new IpPrefix(IPV4_BYTES, 0); - assertEquals("0.0.0.0/0", p.toString()); - - try { - p = new IpPrefix(IPV4_BYTES, 33); - fail("Expected IllegalArgumentException: invalid prefix length"); - } catch (RuntimeException expected) { } - - try { - p = new IpPrefix(IPV4_BYTES, 128); - fail("Expected IllegalArgumentException: invalid prefix length"); - } catch (RuntimeException expected) { } - - try { - p = new IpPrefix(IPV4_BYTES, -1); - fail("Expected IllegalArgumentException: negative prefix length"); - } catch (RuntimeException expected) { } - - p = new IpPrefix(IPV6_BYTES, 128); - assertEquals("2001:db8:dead:beef:f00::a0/128", p.toString()); - - p = new IpPrefix(IPV6_BYTES, 122); - assertEquals("2001:db8:dead:beef:f00::80/122", p.toString()); - - p = new IpPrefix(IPV6_BYTES, 64); - assertEquals("2001:db8:dead:beef::/64", p.toString()); - - p = new IpPrefix(IPV6_BYTES, 3); - assertEquals("2000::/3", p.toString()); - - p = new IpPrefix(IPV6_BYTES, 0); - assertEquals("::/0", p.toString()); - - try { - p = new IpPrefix(IPV6_BYTES, -1); - fail("Expected IllegalArgumentException: negative prefix length"); - } catch (RuntimeException expected) { } - - try { - p = new IpPrefix(IPV6_BYTES, 129); - fail("Expected IllegalArgumentException: negative prefix length"); - } catch (RuntimeException expected) { } - - } - - @Test - public void testEquals() { - IpPrefix p1, p2; - - p1 = new IpPrefix("192.0.2.251/23"); - p2 = new IpPrefix(new byte[]{(byte) 192, (byte) 0, (byte) 2, (byte) 251}, 23); - assertEqualBothWays(p1, p2); - - p1 = new IpPrefix("192.0.2.5/23"); - assertEqualBothWays(p1, p2); - - p1 = new IpPrefix("192.0.2.5/24"); - assertNotEqualEitherWay(p1, p2); - - p1 = new IpPrefix("192.0.4.5/23"); - assertNotEqualEitherWay(p1, p2); - - - p1 = new IpPrefix("2001:db8:dead:beef:f00::80/122"); - p2 = new IpPrefix(IPV6_BYTES, 122); - assertEquals("2001:db8:dead:beef:f00::80/122", p2.toString()); - assertEqualBothWays(p1, p2); - - p1 = new IpPrefix("2001:db8:dead:beef:f00::bf/122"); - assertEqualBothWays(p1, p2); - - p1 = new IpPrefix("2001:db8:dead:beef:f00::8:0/123"); - assertNotEqualEitherWay(p1, p2); - - p1 = new IpPrefix("2001:db8:dead:beef::/122"); - assertNotEqualEitherWay(p1, p2); - - // 192.0.2.4/32 != c000:0204::/32. - byte[] ipv6bytes = new byte[16]; - System.arraycopy(IPV4_BYTES, 0, ipv6bytes, 0, IPV4_BYTES.length); - p1 = new IpPrefix(ipv6bytes, 32); - assertEqualBothWays(p1, new IpPrefix("c000:0204::/32")); - - p2 = new IpPrefix(IPV4_BYTES, 32); - assertNotEqualEitherWay(p1, p2); - } - - @Test - public void testContainsInetAddress() { - IpPrefix p = new IpPrefix("2001:db8:f00::ace:d00d/127"); - assertTrue(p.contains(address("2001:db8:f00::ace:d00c"))); - assertTrue(p.contains(address("2001:db8:f00::ace:d00d"))); - assertFalse(p.contains(address("2001:db8:f00::ace:d00e"))); - assertFalse(p.contains(address("2001:db8:f00::bad:d00d"))); - assertFalse(p.contains(address("2001:4868:4860::8888"))); - assertFalse(p.contains(address("8.8.8.8"))); - - p = new IpPrefix("192.0.2.0/23"); - assertTrue(p.contains(address("192.0.2.43"))); - assertTrue(p.contains(address("192.0.3.21"))); - assertFalse(p.contains(address("192.0.0.21"))); - assertFalse(p.contains(address("8.8.8.8"))); - assertFalse(p.contains(address("2001:4868:4860::8888"))); - - IpPrefix ipv6Default = new IpPrefix("::/0"); - assertTrue(ipv6Default.contains(address("2001:db8::f00"))); - assertFalse(ipv6Default.contains(address("192.0.2.1"))); - - IpPrefix ipv4Default = new IpPrefix("0.0.0.0/0"); - assertTrue(ipv4Default.contains(address("255.255.255.255"))); - assertTrue(ipv4Default.contains(address("192.0.2.1"))); - assertFalse(ipv4Default.contains(address("2001:db8::f00"))); - } - - @Test - public void testContainsIpPrefix() { - assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("0.0.0.0/0"))); - assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("1.2.3.4/0"))); - assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("1.2.3.4/8"))); - assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("1.2.3.4/24"))); - assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("1.2.3.4/23"))); - - assertTrue(new IpPrefix("1.2.3.4/8").containsPrefix(new IpPrefix("1.2.3.4/8"))); - assertTrue(new IpPrefix("1.2.3.4/8").containsPrefix(new IpPrefix("1.254.12.9/8"))); - assertTrue(new IpPrefix("1.2.3.4/21").containsPrefix(new IpPrefix("1.2.3.4/21"))); - assertTrue(new IpPrefix("1.2.3.4/32").containsPrefix(new IpPrefix("1.2.3.4/32"))); - - assertTrue(new IpPrefix("1.2.3.4/20").containsPrefix(new IpPrefix("1.2.3.0/24"))); - - assertFalse(new IpPrefix("1.2.3.4/32").containsPrefix(new IpPrefix("1.2.3.5/32"))); - assertFalse(new IpPrefix("1.2.3.4/8").containsPrefix(new IpPrefix("2.2.3.4/8"))); - assertFalse(new IpPrefix("0.0.0.0/16").containsPrefix(new IpPrefix("0.0.0.0/15"))); - assertFalse(new IpPrefix("100.0.0.0/8").containsPrefix(new IpPrefix("99.0.0.0/8"))); - - assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("::/0"))); - assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/1"))); - assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("3d8a:661:a0::770/8"))); - assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/8"))); - assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/64"))); - assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/113"))); - assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/128"))); - - assertTrue(new IpPrefix("2001:db8:f00::ace:d00d/64").containsPrefix( - new IpPrefix("2001:db8:f00::ace:d00d/64"))); - assertTrue(new IpPrefix("2001:db8:f00::ace:d00d/64").containsPrefix( - new IpPrefix("2001:db8:f00::ace:d00d/120"))); - assertFalse(new IpPrefix("2001:db8:f00::ace:d00d/64").containsPrefix( - new IpPrefix("2001:db8:f00::ace:d00d/32"))); - assertFalse(new IpPrefix("2001:db8:f00::ace:d00d/64").containsPrefix( - new IpPrefix("2006:db8:f00::ace:d00d/96"))); - - assertTrue(new IpPrefix("2001:db8:f00::ace:d00d/128").containsPrefix( - new IpPrefix("2001:db8:f00::ace:d00d/128"))); - assertTrue(new IpPrefix("2001:db8:f00::ace:d00d/100").containsPrefix( - new IpPrefix("2001:db8:f00::ace:ccaf/110"))); - - assertFalse(new IpPrefix("2001:db8:f00::ace:d00d/128").containsPrefix( - new IpPrefix("2001:db8:f00::ace:d00e/128"))); - assertFalse(new IpPrefix("::/30").containsPrefix(new IpPrefix("::/29"))); - } - - @Test - public void testHashCode() { - IpPrefix p = new IpPrefix(new byte[4], 0); - Random random = new Random(); - for (int i = 0; i < 100; i++) { - final IpPrefix oldP = p; - if (random.nextBoolean()) { - // IPv4. - byte[] b = new byte[4]; - random.nextBytes(b); - p = new IpPrefix(b, random.nextInt(33)); - } else { - // IPv6. - byte[] b = new byte[16]; - random.nextBytes(b); - p = new IpPrefix(b, random.nextInt(129)); - } - if (p.equals(oldP)) { - assertEquals(p.hashCode(), oldP.hashCode()); - } - if (p.hashCode() != oldP.hashCode()) { - assertNotEquals(p, oldP); - } - } - } - - @Test - public void testHashCodeIsNotConstant() { - IpPrefix[] prefixes = { - new IpPrefix("2001:db8:f00::ace:d00d/127"), - new IpPrefix("192.0.2.0/23"), - new IpPrefix("::/0"), - new IpPrefix("0.0.0.0/0"), - }; - for (int i = 0; i < prefixes.length; i++) { - for (int j = i + 1; j < prefixes.length; j++) { - assertNotEquals(prefixes[i].hashCode(), prefixes[j].hashCode()); - } - } - } - - @Test - public void testMappedAddressesAreBroken() { - // 192.0.2.0/24 != ::ffff:c000:0204/120, but because we use InetAddress, - // we are unable to comprehend that. - byte[] ipv6bytes = { - (byte) 0, (byte) 0, (byte) 0, (byte) 0, - (byte) 0, (byte) 0, (byte) 0, (byte) 0, - (byte) 0, (byte) 0, (byte) 0xff, (byte) 0xff, - (byte) 192, (byte) 0, (byte) 2, (byte) 0}; - IpPrefix p = new IpPrefix(ipv6bytes, 120); - assertEquals(16, p.getRawAddress().length); // Fine. - assertArrayEquals(ipv6bytes, p.getRawAddress()); // Fine. - - // Broken. - assertEquals("192.0.2.0/120", p.toString()); - assertEquals(InetAddress.parseNumericAddress("192.0.2.0"), p.getAddress()); - } - - @Test - public void testParceling() { - IpPrefix p; - - p = new IpPrefix("2001:4860:db8::/64"); - assertParcelingIsLossless(p); - assertTrue(p.isIPv6()); - - p = new IpPrefix("192.0.2.0/25"); - assertParcelingIsLossless(p); - assertTrue(p.isIPv4()); - - assertFieldCountEquals(2, IpPrefix.class); - } -} diff --git a/packages/Connectivity/tests/common/java/android/net/KeepalivePacketDataTest.kt b/packages/Connectivity/tests/common/java/android/net/KeepalivePacketDataTest.kt deleted file mode 100644 index f464ec6cf0e54..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/KeepalivePacketDataTest.kt +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.net - -import android.net.InvalidPacketException.ERROR_INVALID_IP_ADDRESS -import android.net.InvalidPacketException.ERROR_INVALID_PORT -import android.os.Build -import androidx.test.filters.SmallTest -import androidx.test.runner.AndroidJUnit4 -import com.android.testutils.DevSdkIgnoreRule -import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo -import java.net.InetAddress -import java.util.Arrays -import org.junit.Assert.assertEquals -import org.junit.Assert.assertTrue -import org.junit.Assert.fail -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -@SmallTest -class KeepalivePacketDataTest { - @Rule @JvmField - val ignoreRule: DevSdkIgnoreRule = DevSdkIgnoreRule() - - private val INVALID_PORT = 65537 - private val TEST_DST_PORT = 4244 - private val TEST_SRC_PORT = 4243 - - private val TESTBYTES = byteArrayOf(12, 31, 22, 44) - private val TEST_SRC_ADDRV4 = "198.168.0.2".address() - private val TEST_DST_ADDRV4 = "198.168.0.1".address() - private val TEST_ADDRV6 = "2001:db8::1".address() - - private fun String.address() = InetAddresses.parseNumericAddress(this) - - // Add for test because constructor of KeepalivePacketData is protected. - private inner class TestKeepalivePacketData( - srcAddress: InetAddress? = TEST_SRC_ADDRV4, - srcPort: Int = TEST_SRC_PORT, - dstAddress: InetAddress? = TEST_DST_ADDRV4, - dstPort: Int = TEST_DST_PORT, - data: ByteArray = TESTBYTES - ) : KeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, data) - - @Test - @IgnoreUpTo(Build.VERSION_CODES.Q) - fun testConstructor() { - var data: TestKeepalivePacketData - - try { - data = TestKeepalivePacketData(srcAddress = null) - fail("Null src address should cause exception") - } catch (e: InvalidPacketException) { - assertEquals(e.error, ERROR_INVALID_IP_ADDRESS) - } - - try { - data = TestKeepalivePacketData(dstAddress = null) - fail("Null dst address should cause exception") - } catch (e: InvalidPacketException) { - assertEquals(e.error, ERROR_INVALID_IP_ADDRESS) - } - - try { - data = TestKeepalivePacketData(dstAddress = TEST_ADDRV6) - fail("Ip family mismatched should cause exception") - } catch (e: InvalidPacketException) { - assertEquals(e.error, ERROR_INVALID_IP_ADDRESS) - } - - try { - data = TestKeepalivePacketData(srcPort = INVALID_PORT) - fail("Invalid srcPort should cause exception") - } catch (e: InvalidPacketException) { - assertEquals(e.error, ERROR_INVALID_PORT) - } - - try { - data = TestKeepalivePacketData(dstPort = INVALID_PORT) - fail("Invalid dstPort should cause exception") - } catch (e: InvalidPacketException) { - assertEquals(e.error, ERROR_INVALID_PORT) - } - } - - @Test - @IgnoreUpTo(Build.VERSION_CODES.Q) - fun testSrcAddress() = assertEquals(TEST_SRC_ADDRV4, TestKeepalivePacketData().srcAddress) - - @Test - @IgnoreUpTo(Build.VERSION_CODES.Q) - fun testDstAddress() = assertEquals(TEST_DST_ADDRV4, TestKeepalivePacketData().dstAddress) - - @Test - @IgnoreUpTo(Build.VERSION_CODES.Q) - fun testSrcPort() = assertEquals(TEST_SRC_PORT, TestKeepalivePacketData().srcPort) - - @Test - @IgnoreUpTo(Build.VERSION_CODES.Q) - fun testDstPort() = assertEquals(TEST_DST_PORT, TestKeepalivePacketData().dstPort) - - @Test - @IgnoreUpTo(Build.VERSION_CODES.Q) - fun testPacket() = assertTrue(Arrays.equals(TESTBYTES, TestKeepalivePacketData().packet)) -} \ No newline at end of file diff --git a/packages/Connectivity/tests/common/java/android/net/LinkAddressTest.java b/packages/Connectivity/tests/common/java/android/net/LinkAddressTest.java deleted file mode 100644 index 2cf3cf9c11da4..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/LinkAddressTest.java +++ /dev/null @@ -1,518 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static android.system.OsConstants.IFA_F_DADFAILED; -import static android.system.OsConstants.IFA_F_DEPRECATED; -import static android.system.OsConstants.IFA_F_OPTIMISTIC; -import static android.system.OsConstants.IFA_F_PERMANENT; -import static android.system.OsConstants.IFA_F_TEMPORARY; -import static android.system.OsConstants.IFA_F_TENTATIVE; -import static android.system.OsConstants.RT_SCOPE_HOST; -import static android.system.OsConstants.RT_SCOPE_LINK; -import static android.system.OsConstants.RT_SCOPE_SITE; -import static android.system.OsConstants.RT_SCOPE_UNIVERSE; - -import static com.android.testutils.MiscAsserts.assertEqualBothWays; -import static com.android.testutils.MiscAsserts.assertFieldCountEquals; -import static com.android.testutils.MiscAsserts.assertNotEqualEitherWay; -import static com.android.testutils.ParcelUtils.assertParcelingIsLossless; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import android.os.Build; -import android.os.SystemClock; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.testutils.DevSdkIgnoreRule; -import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter; -import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.InterfaceAddress; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.util.Arrays; -import java.util.List; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class LinkAddressTest { - @Rule - public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule(); - - private static final String V4 = "192.0.2.1"; - private static final String V6 = "2001:db8::1"; - private static final InetAddress V4_ADDRESS = InetAddresses.parseNumericAddress(V4); - private static final InetAddress V6_ADDRESS = InetAddresses.parseNumericAddress(V6); - - @Test - public void testConstants() { - // RT_SCOPE_UNIVERSE = 0, but all the other constants should be nonzero. - assertNotEquals(0, RT_SCOPE_HOST); - assertNotEquals(0, RT_SCOPE_LINK); - assertNotEquals(0, RT_SCOPE_SITE); - - assertNotEquals(0, IFA_F_DEPRECATED); - assertNotEquals(0, IFA_F_PERMANENT); - assertNotEquals(0, IFA_F_TENTATIVE); - } - - @Test - public void testConstructors() throws SocketException { - LinkAddress address; - - // Valid addresses work as expected. - address = new LinkAddress(V4_ADDRESS, 25); - assertEquals(V4_ADDRESS, address.getAddress()); - assertEquals(25, address.getPrefixLength()); - assertEquals(0, address.getFlags()); - assertEquals(RT_SCOPE_UNIVERSE, address.getScope()); - assertTrue(address.isIpv4()); - - address = new LinkAddress(V6_ADDRESS, 127); - assertEquals(V6_ADDRESS, address.getAddress()); - assertEquals(127, address.getPrefixLength()); - assertEquals(0, address.getFlags()); - assertEquals(RT_SCOPE_UNIVERSE, address.getScope()); - assertTrue(address.isIpv6()); - - // Nonsensical flags/scopes or combinations thereof are acceptable. - address = new LinkAddress(V6 + "/64", IFA_F_DEPRECATED | IFA_F_PERMANENT, RT_SCOPE_LINK); - assertEquals(V6_ADDRESS, address.getAddress()); - assertEquals(64, address.getPrefixLength()); - assertEquals(IFA_F_DEPRECATED | IFA_F_PERMANENT, address.getFlags()); - assertEquals(RT_SCOPE_LINK, address.getScope()); - assertTrue(address.isIpv6()); - - address = new LinkAddress(V4 + "/23", 123, 456); - assertEquals(V4_ADDRESS, address.getAddress()); - assertEquals(23, address.getPrefixLength()); - assertEquals(123, address.getFlags()); - assertEquals(456, address.getScope()); - assertTrue(address.isIpv4()); - - address = new LinkAddress("/64", 1 /* flags */, 2 /* scope */); - assertEquals(Inet6Address.LOOPBACK, address.getAddress()); - assertEquals(64, address.getPrefixLength()); - assertEquals(1, address.getFlags()); - assertEquals(2, address.getScope()); - assertTrue(address.isIpv6()); - - address = new LinkAddress("[2001:db8::123]/64", 3 /* flags */, 4 /* scope */); - assertEquals(InetAddresses.parseNumericAddress("2001:db8::123"), address.getAddress()); - assertEquals(64, address.getPrefixLength()); - assertEquals(3, address.getFlags()); - assertEquals(4, address.getScope()); - assertTrue(address.isIpv6()); - - // InterfaceAddress doesn't have a constructor. Fetch some from an interface. - List addrs = NetworkInterface.getByName("lo").getInterfaceAddresses(); - - // We expect to find 127.0.0.1/8 and ::1/128, in any order. - LinkAddress ipv4Loopback, ipv6Loopback; - assertEquals(2, addrs.size()); - if (addrs.get(0).getAddress() instanceof Inet4Address) { - ipv4Loopback = new LinkAddress(addrs.get(0)); - ipv6Loopback = new LinkAddress(addrs.get(1)); - } else { - ipv4Loopback = new LinkAddress(addrs.get(1)); - ipv6Loopback = new LinkAddress(addrs.get(0)); - } - - assertEquals(InetAddresses.parseNumericAddress("127.0.0.1"), ipv4Loopback.getAddress()); - assertEquals(8, ipv4Loopback.getPrefixLength()); - - assertEquals(InetAddresses.parseNumericAddress("::1"), ipv6Loopback.getAddress()); - assertEquals(128, ipv6Loopback.getPrefixLength()); - - // Null addresses are rejected. - try { - address = new LinkAddress(null, 24); - fail("Null InetAddress should cause IllegalArgumentException"); - } catch(IllegalArgumentException expected) {} - - try { - address = new LinkAddress((String) null, IFA_F_PERMANENT, RT_SCOPE_UNIVERSE); - fail("Null string should cause IllegalArgumentException"); - } catch(IllegalArgumentException expected) {} - - try { - address = new LinkAddress((InterfaceAddress) null); - fail("Null string should cause NullPointerException"); - } catch(NullPointerException expected) {} - - // Invalid prefix lengths are rejected. - try { - address = new LinkAddress(V4_ADDRESS, -1); - fail("Negative IPv4 prefix length should cause IllegalArgumentException"); - } catch(IllegalArgumentException expected) {} - - try { - address = new LinkAddress(V6_ADDRESS, -1); - fail("Negative IPv6 prefix length should cause IllegalArgumentException"); - } catch(IllegalArgumentException expected) {} - - try { - address = new LinkAddress(V4_ADDRESS, 33); - fail("/33 IPv4 prefix length should cause IllegalArgumentException"); - } catch(IllegalArgumentException expected) {} - - try { - address = new LinkAddress(V4 + "/33", IFA_F_PERMANENT, RT_SCOPE_UNIVERSE); - fail("/33 IPv4 prefix length should cause IllegalArgumentException"); - } catch(IllegalArgumentException expected) {} - - - try { - address = new LinkAddress(V6_ADDRESS, 129, IFA_F_PERMANENT, RT_SCOPE_UNIVERSE); - fail("/129 IPv6 prefix length should cause IllegalArgumentException"); - } catch(IllegalArgumentException expected) {} - - try { - address = new LinkAddress(V6 + "/129", IFA_F_PERMANENT, RT_SCOPE_UNIVERSE); - fail("/129 IPv6 prefix length should cause IllegalArgumentException"); - } catch(IllegalArgumentException expected) {} - - // Multicast addresses are rejected. - try { - address = new LinkAddress("224.0.0.2/32"); - fail("IPv4 multicast address should cause IllegalArgumentException"); - } catch(IllegalArgumentException expected) {} - - try { - address = new LinkAddress("ff02::1/128"); - fail("IPv6 multicast address should cause IllegalArgumentException"); - } catch(IllegalArgumentException expected) {} - } - - @Test - public void testAddressScopes() { - assertEquals(RT_SCOPE_HOST, new LinkAddress("::/128").getScope()); - assertEquals(RT_SCOPE_HOST, new LinkAddress("0.0.0.0/32").getScope()); - - assertEquals(RT_SCOPE_LINK, new LinkAddress("::1/128").getScope()); - assertEquals(RT_SCOPE_LINK, new LinkAddress("127.0.0.5/8").getScope()); - assertEquals(RT_SCOPE_LINK, new LinkAddress("fe80::ace:d00d/64").getScope()); - assertEquals(RT_SCOPE_LINK, new LinkAddress("169.254.5.12/16").getScope()); - - assertEquals(RT_SCOPE_SITE, new LinkAddress("fec0::dead/64").getScope()); - - assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("10.1.2.3/21").getScope()); - assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("192.0.2.1/25").getScope()); - assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("2001:db8::/64").getScope()); - assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("5000::/127").getScope()); - } - - private void assertIsSameAddressAs(LinkAddress l1, LinkAddress l2) { - assertTrue(l1 + " unexpectedly does not have same address as " + l2, - l1.isSameAddressAs(l2)); - assertTrue(l2 + " unexpectedly does not have same address as " + l1, - l2.isSameAddressAs(l1)); - } - - private void assertIsNotSameAddressAs(LinkAddress l1, LinkAddress l2) { - assertFalse(l1 + " unexpectedly has same address as " + l2, - l1.isSameAddressAs(l2)); - assertFalse(l2 + " unexpectedly has same address as " + l1, - l1.isSameAddressAs(l2)); - } - - @Test - public void testEqualsAndSameAddressAs() { - LinkAddress l1, l2, l3; - - l1 = new LinkAddress("2001:db8::1/64"); - l2 = new LinkAddress("2001:db8::1/64"); - assertEqualBothWays(l1, l2); - assertIsSameAddressAs(l1, l2); - - l2 = new LinkAddress("2001:db8::1/65"); - assertNotEqualEitherWay(l1, l2); - assertIsNotSameAddressAs(l1, l2); - - l2 = new LinkAddress("2001:db8::2/64"); - assertNotEqualEitherWay(l1, l2); - assertIsNotSameAddressAs(l1, l2); - - - l1 = new LinkAddress("192.0.2.1/24"); - l2 = new LinkAddress("192.0.2.1/24"); - assertEqualBothWays(l1, l2); - assertIsSameAddressAs(l1, l2); - - l2 = new LinkAddress("192.0.2.1/23"); - assertNotEqualEitherWay(l1, l2); - assertIsNotSameAddressAs(l1, l2); - - l2 = new LinkAddress("192.0.2.2/24"); - assertNotEqualEitherWay(l1, l2); - assertIsNotSameAddressAs(l1, l2); - - - // Check equals() and isSameAddressAs() on identical addresses with different flags. - l1 = new LinkAddress(V6_ADDRESS, 64); - l2 = new LinkAddress(V6_ADDRESS, 64, 0, RT_SCOPE_UNIVERSE); - assertEqualBothWays(l1, l2); - assertIsSameAddressAs(l1, l2); - - l2 = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED, RT_SCOPE_UNIVERSE); - assertNotEqualEitherWay(l1, l2); - assertIsSameAddressAs(l1, l2); - - // Check equals() and isSameAddressAs() on identical addresses with different scope. - l1 = new LinkAddress(V4_ADDRESS, 24); - l2 = new LinkAddress(V4_ADDRESS, 24, 0, RT_SCOPE_UNIVERSE); - assertEqualBothWays(l1, l2); - assertIsSameAddressAs(l1, l2); - - l2 = new LinkAddress(V4_ADDRESS, 24, 0, RT_SCOPE_HOST); - assertNotEqualEitherWay(l1, l2); - assertIsSameAddressAs(l1, l2); - - // Addresses with the same start or end bytes aren't equal between families. - l1 = new LinkAddress("32.1.13.184/24"); - l2 = new LinkAddress("2001:db8::1/24"); - l3 = new LinkAddress("::2001:db8/24"); - - byte[] ipv4Bytes = l1.getAddress().getAddress(); - byte[] l2FirstIPv6Bytes = Arrays.copyOf(l2.getAddress().getAddress(), 4); - byte[] l3LastIPv6Bytes = Arrays.copyOfRange(l3.getAddress().getAddress(), 12, 16); - assertTrue(Arrays.equals(ipv4Bytes, l2FirstIPv6Bytes)); - assertTrue(Arrays.equals(ipv4Bytes, l3LastIPv6Bytes)); - - assertNotEqualEitherWay(l1, l2); - assertIsNotSameAddressAs(l1, l2); - - assertNotEqualEitherWay(l1, l3); - assertIsNotSameAddressAs(l1, l3); - - // Because we use InetAddress, an IPv4 address is equal to its IPv4-mapped address. - // TODO: Investigate fixing this. - String addressString = V4 + "/24"; - l1 = new LinkAddress(addressString); - l2 = new LinkAddress("::ffff:" + addressString); - assertEqualBothWays(l1, l2); - assertIsSameAddressAs(l1, l2); - } - - @Test - public void testHashCode() { - LinkAddress l1, l2; - - l1 = new LinkAddress(V4_ADDRESS, 23); - l2 = new LinkAddress(V4_ADDRESS, 23, 0, RT_SCOPE_HOST); - assertNotEquals(l1.hashCode(), l2.hashCode()); - - l1 = new LinkAddress(V6_ADDRESS, 128); - l2 = new LinkAddress(V6_ADDRESS, 128, IFA_F_TENTATIVE, RT_SCOPE_UNIVERSE); - assertNotEquals(l1.hashCode(), l2.hashCode()); - } - - @Test - public void testParceling() { - LinkAddress l; - - l = new LinkAddress(V6_ADDRESS, 64, 123, 456); - assertParcelingIsLossless(l); - - l = new LinkAddress(V4 + "/28", IFA_F_PERMANENT, RT_SCOPE_LINK); - assertParcelingIsLossless(l); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testLifetimeParceling() { - final LinkAddress l = new LinkAddress(V6_ADDRESS, 64, 123, 456, 1L, 3600000L); - assertParcelingIsLossless(l); - } - - @Test @IgnoreAfter(Build.VERSION_CODES.Q) - public void testFieldCount_Q() { - assertFieldCountEquals(4, LinkAddress.class); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testFieldCount() { - // Make sure any new field is covered by the above parceling tests when changing this number - assertFieldCountEquals(6, LinkAddress.class); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testDeprecationTime() { - try { - new LinkAddress(V6_ADDRESS, 64, 0, 456, - LinkAddress.LIFETIME_UNKNOWN, 100000L); - fail("Only one time provided should cause exception"); - } catch (IllegalArgumentException expected) { } - - try { - new LinkAddress(V6_ADDRESS, 64, 0, 456, - 200000L, 100000L); - fail("deprecation time later than expiration time should cause exception"); - } catch (IllegalArgumentException expected) { } - - try { - new LinkAddress(V6_ADDRESS, 64, 0, 456, - -2, 100000L); - fail("negative deprecation time should cause exception"); - } catch (IllegalArgumentException expected) { } - - LinkAddress addr = new LinkAddress(V6_ADDRESS, 64, 0, 456, 100000L, 200000L); - assertEquals(100000L, addr.getDeprecationTime()); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testExpirationTime() { - try { - new LinkAddress(V6_ADDRESS, 64, 0, 456, - 200000L, LinkAddress.LIFETIME_UNKNOWN); - fail("Only one time provided should cause exception"); - } catch (IllegalArgumentException expected) { } - - try { - new LinkAddress(V6_ADDRESS, 64, 0, 456, - 100000L, -2); - fail("negative expiration time should cause exception"); - } catch (IllegalArgumentException expected) { } - - LinkAddress addr = new LinkAddress(V6_ADDRESS, 64, 0, 456, 100000L, 200000L); - assertEquals(200000L, addr.getExpirationTime()); - } - - @Test - public void testGetFlags() { - LinkAddress l = new LinkAddress(V6_ADDRESS, 64, 123, RT_SCOPE_HOST); - assertEquals(123, l.getFlags()); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testGetFlags_Deprecation() { - // Test if deprecated bit was added/remove automatically based on the provided deprecation - // time - LinkAddress l = new LinkAddress(V6_ADDRESS, 64, 0, RT_SCOPE_HOST, - 1L, LinkAddress.LIFETIME_PERMANENT); - // Check if the flag is added automatically. - assertTrue((l.getFlags() & IFA_F_DEPRECATED) != 0); - - l = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED, RT_SCOPE_HOST, - SystemClock.elapsedRealtime() + 100000L, LinkAddress.LIFETIME_PERMANENT); - // Check if the flag is removed automatically. - assertTrue((l.getFlags() & IFA_F_DEPRECATED) == 0); - - l = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED, RT_SCOPE_HOST, - LinkAddress.LIFETIME_PERMANENT, LinkAddress.LIFETIME_PERMANENT); - // Check if the permanent flag is added. - assertTrue((l.getFlags() & IFA_F_PERMANENT) != 0); - - l = new LinkAddress(V6_ADDRESS, 64, IFA_F_PERMANENT, RT_SCOPE_HOST, - 1000L, SystemClock.elapsedRealtime() + 100000L); - // Check if the permanent flag is removed - assertTrue((l.getFlags() & IFA_F_PERMANENT) == 0); - } - - private void assertGlobalPreferred(LinkAddress l, String msg) { - assertTrue(msg, l.isGlobalPreferred()); - } - - private void assertNotGlobalPreferred(LinkAddress l, String msg) { - assertFalse(msg, l.isGlobalPreferred()); - } - - @Test - public void testIsGlobalPreferred() { - LinkAddress l; - - l = new LinkAddress(V4_ADDRESS, 32, 0, RT_SCOPE_UNIVERSE); - assertGlobalPreferred(l, "v4,global,noflags"); - - l = new LinkAddress("10.10.1.7/23", 0, RT_SCOPE_UNIVERSE); - assertGlobalPreferred(l, "v4-rfc1918,global,noflags"); - - l = new LinkAddress("10.10.1.7/23", 0, RT_SCOPE_SITE); - assertNotGlobalPreferred(l, "v4-rfc1918,site-local,noflags"); - - l = new LinkAddress("127.0.0.7/8", 0, RT_SCOPE_HOST); - assertNotGlobalPreferred(l, "v4-localhost,node-local,noflags"); - - l = new LinkAddress(V6_ADDRESS, 64, 0, RT_SCOPE_UNIVERSE); - assertGlobalPreferred(l, "v6,global,noflags"); - - l = new LinkAddress(V6_ADDRESS, 64, IFA_F_PERMANENT, RT_SCOPE_UNIVERSE); - assertGlobalPreferred(l, "v6,global,permanent"); - - // IPv6 ULAs are not acceptable "global preferred" addresses. - l = new LinkAddress("fc12::1/64", 0, RT_SCOPE_UNIVERSE); - assertNotGlobalPreferred(l, "v6,ula1,noflags"); - - l = new LinkAddress("fd34::1/64", 0, RT_SCOPE_UNIVERSE); - assertNotGlobalPreferred(l, "v6,ula2,noflags"); - - l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_UNIVERSE); - assertGlobalPreferred(l, "v6,global,tempaddr"); - - l = new LinkAddress(V6_ADDRESS, 64, (IFA_F_TEMPORARY|IFA_F_DADFAILED), - RT_SCOPE_UNIVERSE); - assertNotGlobalPreferred(l, "v6,global,tempaddr+dadfailed"); - - l = new LinkAddress(V6_ADDRESS, 64, (IFA_F_TEMPORARY|IFA_F_DEPRECATED), - RT_SCOPE_UNIVERSE); - assertNotGlobalPreferred(l, "v6,global,tempaddr+deprecated"); - - l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_SITE); - assertNotGlobalPreferred(l, "v6,site-local,tempaddr"); - - l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_LINK); - assertNotGlobalPreferred(l, "v6,link-local,tempaddr"); - - l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_HOST); - assertNotGlobalPreferred(l, "v6,node-local,tempaddr"); - - l = new LinkAddress("::1/128", IFA_F_PERMANENT, RT_SCOPE_HOST); - assertNotGlobalPreferred(l, "v6-localhost,node-local,permanent"); - - l = new LinkAddress(V6_ADDRESS, 64, (IFA_F_TEMPORARY|IFA_F_TENTATIVE), - RT_SCOPE_UNIVERSE); - assertNotGlobalPreferred(l, "v6,global,tempaddr+tentative"); - - l = new LinkAddress(V6_ADDRESS, 64, - (IFA_F_TEMPORARY|IFA_F_TENTATIVE|IFA_F_OPTIMISTIC), - RT_SCOPE_UNIVERSE); - assertGlobalPreferred(l, "v6,global,tempaddr+optimistic"); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testIsGlobalPreferred_DeprecatedInFuture() { - final LinkAddress l = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED, - RT_SCOPE_UNIVERSE, SystemClock.elapsedRealtime() + 100000, - SystemClock.elapsedRealtime() + 200000); - // Although the deprecated bit is set, but the deprecation time is in the future, test - // if the flag is removed automatically. - assertGlobalPreferred(l, "v6,global,tempaddr+deprecated in the future"); - } -} diff --git a/packages/Connectivity/tests/common/java/android/net/LinkPropertiesTest.java b/packages/Connectivity/tests/common/java/android/net/LinkPropertiesTest.java deleted file mode 100644 index 550953d0612df..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/LinkPropertiesTest.java +++ /dev/null @@ -1,1271 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static android.net.RouteInfo.RTN_THROW; -import static android.net.RouteInfo.RTN_UNICAST; -import static android.net.RouteInfo.RTN_UNREACHABLE; - -import static com.android.testutils.ParcelUtils.assertParcelSane; -import static com.android.testutils.ParcelUtils.assertParcelingIsLossless; -import static com.android.testutils.ParcelUtils.parcelingRoundTrip; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import android.net.LinkProperties.ProvisioningChange; -import android.os.Build; -import android.system.OsConstants; -import android.util.ArraySet; - -import androidx.core.os.BuildCompat; -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.net.module.util.LinkPropertiesUtils.CompareResult; -import com.android.testutils.DevSdkIgnoreRule; -import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter; -import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Set; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class LinkPropertiesTest { - @Rule - public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule(); - - private static final InetAddress ADDRV4 = address("75.208.6.1"); - private static final InetAddress ADDRV6 = address("2001:0db8:85a3:0000:0000:8a2e:0370:7334"); - private static final InetAddress DNS1 = address("75.208.7.1"); - private static final InetAddress DNS2 = address("69.78.7.1"); - private static final InetAddress DNS6 = address("2001:4860:4860::8888"); - private static final InetAddress PRIVDNS1 = address("1.1.1.1"); - private static final InetAddress PRIVDNS2 = address("1.0.0.1"); - private static final InetAddress PRIVDNS6 = address("2606:4700:4700::1111"); - private static final InetAddress PCSCFV4 = address("10.77.25.37"); - private static final InetAddress PCSCFV6 = address("2001:0db8:85a3:0000:0000:8a2e:0370:1"); - private static final InetAddress GATEWAY1 = address("75.208.8.1"); - private static final InetAddress GATEWAY2 = address("69.78.8.1"); - private static final InetAddress GATEWAY61 = address("fe80::6:0000:613"); - private static final InetAddress GATEWAY62 = address("fe80::6:22%lo"); - private static final InetAddress TESTIPV4ADDR = address("192.168.47.42"); - private static final InetAddress TESTIPV6ADDR = address("fe80::7:33%43"); - private static final Inet4Address DHCPSERVER = (Inet4Address) address("192.0.2.1"); - private static final String NAME = "qmi0"; - private static final String DOMAINS = "google.com"; - private static final String PRIV_DNS_SERVER_NAME = "private.dns.com"; - private static final String TCP_BUFFER_SIZES = "524288,1048576,2097152,262144,524288,1048576"; - private static final int MTU = 1500; - private static final LinkAddress LINKADDRV4 = new LinkAddress(ADDRV4, 32); - private static final LinkAddress LINKADDRV6 = new LinkAddress(ADDRV6, 128); - private static final LinkAddress LINKADDRV6LINKLOCAL = new LinkAddress("fe80::1/64"); - private static final Uri CAPPORT_API_URL = Uri.parse("https://test.example.com/capportapi"); - - // CaptivePortalData cannot be in a constant as it does not exist on Q. - // The test runner also crashes when scanning for tests if it is a return type. - private static Object getCaptivePortalData() { - return new CaptivePortalData.Builder() - .setVenueInfoUrl(Uri.parse("https://test.example.com/venue")).build(); - } - - private static InetAddress address(String addrString) { - return InetAddresses.parseNumericAddress(addrString); - } - - private static boolean isAtLeastR() { - // BuildCompat.isAtLeastR is documented to return false on release SDKs (including R) - return Build.VERSION.SDK_INT > Build.VERSION_CODES.Q || BuildCompat.isAtLeastR(); - } - - private void checkEmpty(final LinkProperties lp) { - assertEquals(0, lp.getAllInterfaceNames().size()); - assertEquals(0, lp.getAllAddresses().size()); - assertEquals(0, lp.getDnsServers().size()); - assertEquals(0, lp.getValidatedPrivateDnsServers().size()); - assertEquals(0, lp.getPcscfServers().size()); - assertEquals(0, lp.getAllRoutes().size()); - assertEquals(0, lp.getAllLinkAddresses().size()); - assertEquals(0, lp.getStackedLinks().size()); - assertEquals(0, lp.getMtu()); - assertNull(lp.getPrivateDnsServerName()); - assertNull(lp.getDomains()); - assertNull(lp.getHttpProxy()); - assertNull(lp.getTcpBufferSizes()); - assertNull(lp.getNat64Prefix()); - assertFalse(lp.isProvisioned()); - assertFalse(lp.isIpv4Provisioned()); - assertFalse(lp.isIpv6Provisioned()); - assertFalse(lp.isPrivateDnsActive()); - - if (isAtLeastR()) { - assertNull(lp.getDhcpServerAddress()); - assertFalse(lp.isWakeOnLanSupported()); - assertNull(lp.getCaptivePortalApiUrl()); - assertNull(lp.getCaptivePortalData()); - } - } - - private LinkProperties makeTestObject() { - final LinkProperties lp = new LinkProperties(); - lp.setInterfaceName(NAME); - lp.addLinkAddress(LINKADDRV4); - lp.addLinkAddress(LINKADDRV6); - lp.addDnsServer(DNS1); - lp.addDnsServer(DNS2); - lp.addValidatedPrivateDnsServer(PRIVDNS1); - lp.addValidatedPrivateDnsServer(PRIVDNS2); - lp.setUsePrivateDns(true); - lp.setPrivateDnsServerName(PRIV_DNS_SERVER_NAME); - lp.addPcscfServer(PCSCFV6); - lp.setDomains(DOMAINS); - lp.addRoute(new RouteInfo(GATEWAY1)); - lp.addRoute(new RouteInfo(GATEWAY2)); - lp.setHttpProxy(ProxyInfo.buildDirectProxy("test", 8888)); - lp.setMtu(MTU); - lp.setTcpBufferSizes(TCP_BUFFER_SIZES); - lp.setNat64Prefix(new IpPrefix("2001:db8:0:64::/96")); - if (isAtLeastR()) { - lp.setDhcpServerAddress(DHCPSERVER); - lp.setWakeOnLanSupported(true); - lp.setCaptivePortalApiUrl(CAPPORT_API_URL); - lp.setCaptivePortalData((CaptivePortalData) getCaptivePortalData()); - } - return lp; - } - - public void assertLinkPropertiesEqual(LinkProperties source, LinkProperties target) { - // Check implementation of equals(), element by element. - assertTrue(source.isIdenticalInterfaceName(target)); - assertTrue(target.isIdenticalInterfaceName(source)); - - assertTrue(source.isIdenticalAddresses(target)); - assertTrue(target.isIdenticalAddresses(source)); - - assertTrue(source.isIdenticalDnses(target)); - assertTrue(target.isIdenticalDnses(source)); - - assertTrue(source.isIdenticalPrivateDns(target)); - assertTrue(target.isIdenticalPrivateDns(source)); - - assertTrue(source.isIdenticalValidatedPrivateDnses(target)); - assertTrue(target.isIdenticalValidatedPrivateDnses(source)); - - assertTrue(source.isIdenticalPcscfs(target)); - assertTrue(target.isIdenticalPcscfs(source)); - - assertTrue(source.isIdenticalRoutes(target)); - assertTrue(target.isIdenticalRoutes(source)); - - assertTrue(source.isIdenticalHttpProxy(target)); - assertTrue(target.isIdenticalHttpProxy(source)); - - assertTrue(source.isIdenticalStackedLinks(target)); - assertTrue(target.isIdenticalStackedLinks(source)); - - assertTrue(source.isIdenticalMtu(target)); - assertTrue(target.isIdenticalMtu(source)); - - assertTrue(source.isIdenticalTcpBufferSizes(target)); - assertTrue(target.isIdenticalTcpBufferSizes(source)); - - if (isAtLeastR()) { - assertTrue(source.isIdenticalDhcpServerAddress(target)); - assertTrue(source.isIdenticalDhcpServerAddress(source)); - - assertTrue(source.isIdenticalWakeOnLan(target)); - assertTrue(target.isIdenticalWakeOnLan(source)); - - assertTrue(source.isIdenticalCaptivePortalApiUrl(target)); - assertTrue(target.isIdenticalCaptivePortalApiUrl(source)); - - assertTrue(source.isIdenticalCaptivePortalData(target)); - assertTrue(target.isIdenticalCaptivePortalData(source)); - } - - // Check result of equals(). - assertTrue(source.equals(target)); - assertTrue(target.equals(source)); - - // Check hashCode. - assertEquals(source.hashCode(), target.hashCode()); - } - - @Test - public void testEqualsNull() { - LinkProperties source = new LinkProperties(); - LinkProperties target = new LinkProperties(); - - assertFalse(source == target); - assertLinkPropertiesEqual(source, target); - } - - @Test - public void testEqualsSameOrder() throws Exception { - LinkProperties source = new LinkProperties(); - source.setInterfaceName(NAME); - // set 2 link addresses - source.addLinkAddress(LINKADDRV4); - source.addLinkAddress(LINKADDRV6); - // set 2 dnses - source.addDnsServer(DNS1); - source.addDnsServer(DNS2); - // set 1 pcscf - source.addPcscfServer(PCSCFV6); - // set 2 gateways - source.addRoute(new RouteInfo(GATEWAY1)); - source.addRoute(new RouteInfo(GATEWAY2)); - source.setMtu(MTU); - - LinkProperties target = new LinkProperties(); - - // All fields are same - target.setInterfaceName(NAME); - target.addLinkAddress(LINKADDRV4); - target.addLinkAddress(LINKADDRV6); - target.addDnsServer(DNS1); - target.addDnsServer(DNS2); - target.addPcscfServer(PCSCFV6); - target.addRoute(new RouteInfo(GATEWAY1)); - target.addRoute(new RouteInfo(GATEWAY2)); - target.setMtu(MTU); - - assertLinkPropertiesEqual(source, target); - - target.clear(); - // change Interface Name - target.setInterfaceName("qmi1"); - target.addLinkAddress(LINKADDRV4); - target.addLinkAddress(LINKADDRV6); - target.addDnsServer(DNS1); - target.addDnsServer(DNS2); - target.addPcscfServer(PCSCFV6); - target.addRoute(new RouteInfo(GATEWAY1)); - target.addRoute(new RouteInfo(GATEWAY2)); - target.setMtu(MTU); - assertFalse(source.equals(target)); - - target.clear(); - target.setInterfaceName(NAME); - // change link addresses - target.addLinkAddress(new LinkAddress(address("75.208.6.2"), 32)); - target.addLinkAddress(LINKADDRV6); - target.addDnsServer(DNS1); - target.addDnsServer(DNS2); - target.addPcscfServer(PCSCFV6); - target.addRoute(new RouteInfo(GATEWAY1)); - target.addRoute(new RouteInfo(GATEWAY2)); - target.setMtu(MTU); - assertFalse(source.equals(target)); - - target.clear(); - target.setInterfaceName(NAME); - target.addLinkAddress(LINKADDRV4); - target.addLinkAddress(LINKADDRV6); - // change dnses - target.addDnsServer(address("75.208.7.2")); - target.addDnsServer(DNS2); - target.addPcscfServer(PCSCFV6); - target.addRoute(new RouteInfo(GATEWAY1)); - target.addRoute(new RouteInfo(GATEWAY2)); - target.setMtu(MTU); - assertFalse(source.equals(target)); - - target.clear(); - target.setInterfaceName(NAME); - target.addLinkAddress(LINKADDRV4); - target.addLinkAddress(LINKADDRV6); - target.addDnsServer(address("75.208.7.2")); - target.addDnsServer(DNS2); - // change pcscf - target.addPcscfServer(address("2001::1")); - target.addRoute(new RouteInfo(GATEWAY1)); - target.addRoute(new RouteInfo(GATEWAY2)); - target.setMtu(MTU); - assertFalse(source.equals(target)); - - target.clear(); - target.setInterfaceName(NAME); - target.addLinkAddress(LINKADDRV4); - target.addLinkAddress(LINKADDRV6); - target.addDnsServer(DNS1); - target.addDnsServer(DNS2); - // change gateway - target.addRoute(new RouteInfo(address("75.208.8.2"))); - target.setMtu(MTU); - target.addRoute(new RouteInfo(GATEWAY2)); - assertFalse(source.equals(target)); - - target.clear(); - target.setInterfaceName(NAME); - target.addLinkAddress(LINKADDRV4); - target.addLinkAddress(LINKADDRV6); - target.addDnsServer(DNS1); - target.addDnsServer(DNS2); - target.addRoute(new RouteInfo(GATEWAY1)); - target.addRoute(new RouteInfo(GATEWAY2)); - // change mtu - target.setMtu(1440); - assertFalse(source.equals(target)); - } - - @Test - public void testEqualsDifferentOrder() throws Exception { - LinkProperties source = new LinkProperties(); - source.setInterfaceName(NAME); - // set 2 link addresses - source.addLinkAddress(LINKADDRV4); - source.addLinkAddress(LINKADDRV6); - // set 2 dnses - source.addDnsServer(DNS1); - source.addDnsServer(DNS2); - // set 2 gateways - source.addRoute(new RouteInfo(LINKADDRV4, GATEWAY1)); - source.addRoute(new RouteInfo(GATEWAY2)); - source.setMtu(MTU); - - LinkProperties target = new LinkProperties(); - // Exchange order - target.setInterfaceName(NAME); - target.addLinkAddress(LINKADDRV6); - target.addLinkAddress(LINKADDRV4); - target.addDnsServer(DNS2); - target.addDnsServer(DNS1); - target.addRoute(new RouteInfo(GATEWAY2)); - target.addRoute(new RouteInfo(LINKADDRV4, GATEWAY1)); - target.setMtu(MTU); - - assertLinkPropertiesEqual(source, target); - } - - @Test - public void testEqualsDuplicated() throws Exception { - LinkProperties source = new LinkProperties(); - // set 3 link addresses, eg, [A, A, B] - source.addLinkAddress(LINKADDRV4); - source.addLinkAddress(LINKADDRV4); - source.addLinkAddress(LINKADDRV6); - - LinkProperties target = new LinkProperties(); - // set 3 link addresses, eg, [A, B, B] - target.addLinkAddress(LINKADDRV4); - target.addLinkAddress(LINKADDRV6); - target.addLinkAddress(LINKADDRV6); - - assertLinkPropertiesEqual(source, target); - } - - private void assertAllRoutesHaveInterface(String iface, LinkProperties lp) { - for (RouteInfo r : lp.getRoutes()) { - assertEquals(iface, r.getInterface()); - } - } - - private void assertAllRoutesNotHaveInterface(String iface, LinkProperties lp) { - for (RouteInfo r : lp.getRoutes()) { - assertNotEquals(iface, r.getInterface()); - } - } - - @Test - public void testRouteInterfaces() { - LinkAddress prefix1 = new LinkAddress(address("2001:db8:1::"), 48); - LinkAddress prefix2 = new LinkAddress(address("2001:db8:2::"), 48); - InetAddress address = ADDRV6; - - // Add a route with no interface to a LinkProperties with no interface. No errors. - LinkProperties lp = new LinkProperties(); - RouteInfo r = new RouteInfo(prefix1, address, null); - assertTrue(lp.addRoute(r)); - assertEquals(1, lp.getRoutes().size()); - assertAllRoutesHaveInterface(null, lp); - - // Adding the same route twice has no effect. - assertFalse(lp.addRoute(r)); - assertEquals(1, lp.getRoutes().size()); - - // Add a route with an interface. Expect an exception. - r = new RouteInfo(prefix2, address, "wlan0"); - try { - lp.addRoute(r); - fail("Adding wlan0 route to LP with no interface, expect exception"); - } catch (IllegalArgumentException expected) {} - - // Change the interface name. All the routes should change their interface name too. - lp.setInterfaceName("rmnet0"); - assertAllRoutesHaveInterface("rmnet0", lp); - assertAllRoutesNotHaveInterface(null, lp); - assertAllRoutesNotHaveInterface("wlan0", lp); - - // Now add a route with the wrong interface. This causes an exception too. - try { - lp.addRoute(r); - fail("Adding wlan0 route to rmnet0 LP, expect exception"); - } catch (IllegalArgumentException expected) {} - - // If the interface name matches, the route is added. - r = new RouteInfo(prefix2, null, "wlan0"); - lp.setInterfaceName("wlan0"); - lp.addRoute(r); - assertEquals(2, lp.getRoutes().size()); - assertAllRoutesHaveInterface("wlan0", lp); - assertAllRoutesNotHaveInterface("rmnet0", lp); - - // Routes with null interfaces are converted to wlan0. - r = RouteInfo.makeHostRoute(ADDRV6, null); - lp.addRoute(r); - assertEquals(3, lp.getRoutes().size()); - assertAllRoutesHaveInterface("wlan0", lp); - - // Check routes are updated correctly when calling setInterfaceName. - LinkProperties lp2 = new LinkProperties(lp); - assertAllRoutesHaveInterface("wlan0", lp2); - final CompareResult cr1 = - new CompareResult<>(lp.getAllRoutes(), lp2.getAllRoutes()); - assertEquals(0, cr1.added.size()); - assertEquals(0, cr1.removed.size()); - - lp2.setInterfaceName("p2p0"); - assertAllRoutesHaveInterface("p2p0", lp2); - assertAllRoutesNotHaveInterface("wlan0", lp2); - final CompareResult cr2 = - new CompareResult<>(lp.getAllRoutes(), lp2.getAllRoutes()); - assertEquals(3, cr2.added.size()); - assertEquals(3, cr2.removed.size()); - - // Remove route with incorrect interface, no route removed. - lp.removeRoute(new RouteInfo(prefix2, null, null)); - assertEquals(3, lp.getRoutes().size()); - - // Check remove works when interface is correct. - lp.removeRoute(new RouteInfo(prefix2, null, "wlan0")); - assertEquals(2, lp.getRoutes().size()); - assertAllRoutesHaveInterface("wlan0", lp); - assertAllRoutesNotHaveInterface("p2p0", lp); - } - - @Test - public void testStackedInterfaces() { - LinkProperties rmnet0 = new LinkProperties(); - rmnet0.setInterfaceName("rmnet0"); - rmnet0.addLinkAddress(LINKADDRV6); - - LinkProperties clat4 = new LinkProperties(); - clat4.setInterfaceName("clat4"); - clat4.addLinkAddress(LINKADDRV4); - - assertEquals(0, rmnet0.getStackedLinks().size()); - assertEquals(1, rmnet0.getAddresses().size()); - assertEquals(1, rmnet0.getLinkAddresses().size()); - assertEquals(1, rmnet0.getAllAddresses().size()); - assertEquals(1, rmnet0.getAllLinkAddresses().size()); - assertEquals(1, rmnet0.getAllInterfaceNames().size()); - assertEquals("rmnet0", rmnet0.getAllInterfaceNames().get(0)); - - rmnet0.addStackedLink(clat4); - assertEquals(1, rmnet0.getStackedLinks().size()); - assertEquals(1, rmnet0.getAddresses().size()); - assertEquals(1, rmnet0.getLinkAddresses().size()); - assertEquals(2, rmnet0.getAllAddresses().size()); - assertEquals(2, rmnet0.getAllLinkAddresses().size()); - assertEquals(2, rmnet0.getAllInterfaceNames().size()); - assertEquals("rmnet0", rmnet0.getAllInterfaceNames().get(0)); - assertEquals("clat4", rmnet0.getAllInterfaceNames().get(1)); - - rmnet0.addStackedLink(clat4); - assertEquals(1, rmnet0.getStackedLinks().size()); - assertEquals(1, rmnet0.getAddresses().size()); - assertEquals(1, rmnet0.getLinkAddresses().size()); - assertEquals(2, rmnet0.getAllAddresses().size()); - assertEquals(2, rmnet0.getAllLinkAddresses().size()); - assertEquals(2, rmnet0.getAllInterfaceNames().size()); - assertEquals("rmnet0", rmnet0.getAllInterfaceNames().get(0)); - assertEquals("clat4", rmnet0.getAllInterfaceNames().get(1)); - - assertEquals(0, clat4.getStackedLinks().size()); - - // Modify an item in the returned collection to see what happens. - for (LinkProperties link : rmnet0.getStackedLinks()) { - if (link.getInterfaceName().equals("clat4")) { - link.setInterfaceName("newname"); - } - } - for (LinkProperties link : rmnet0.getStackedLinks()) { - assertFalse("newname".equals(link.getInterfaceName())); - } - - assertTrue(rmnet0.removeStackedLink("clat4")); - assertEquals(0, rmnet0.getStackedLinks().size()); - assertEquals(1, rmnet0.getAddresses().size()); - assertEquals(1, rmnet0.getLinkAddresses().size()); - assertEquals(1, rmnet0.getAllAddresses().size()); - assertEquals(1, rmnet0.getAllLinkAddresses().size()); - assertEquals(1, rmnet0.getAllInterfaceNames().size()); - assertEquals("rmnet0", rmnet0.getAllInterfaceNames().get(0)); - - assertFalse(rmnet0.removeStackedLink("clat4")); - } - - private LinkAddress getFirstLinkAddress(LinkProperties lp) { - return lp.getLinkAddresses().iterator().next(); - } - - @Test - public void testAddressMethods() { - LinkProperties lp = new LinkProperties(); - - // No addresses. - assertFalse(lp.hasIpv4Address()); - assertFalse(lp.hasGlobalIpv6Address()); - - // Addresses on stacked links don't count. - LinkProperties stacked = new LinkProperties(); - stacked.setInterfaceName("stacked"); - lp.addStackedLink(stacked); - stacked.addLinkAddress(LINKADDRV4); - stacked.addLinkAddress(LINKADDRV6); - assertTrue(stacked.hasIpv4Address()); - assertTrue(stacked.hasGlobalIpv6Address()); - assertFalse(lp.hasIpv4Address()); - assertFalse(lp.hasGlobalIpv6Address()); - lp.removeStackedLink("stacked"); - assertFalse(lp.hasIpv4Address()); - assertFalse(lp.hasGlobalIpv6Address()); - - // Addresses on the base link. - // Check the return values of hasIpvXAddress and ensure the add/remove methods return true - // iff something changes. - assertEquals(0, lp.getLinkAddresses().size()); - assertTrue(lp.addLinkAddress(LINKADDRV6)); - assertEquals(1, lp.getLinkAddresses().size()); - assertFalse(lp.hasIpv4Address()); - assertTrue(lp.hasGlobalIpv6Address()); - - assertTrue(lp.removeLinkAddress(LINKADDRV6)); - assertEquals(0, lp.getLinkAddresses().size()); - - assertTrue(lp.addLinkAddress(LINKADDRV6LINKLOCAL)); - assertEquals(1, lp.getLinkAddresses().size()); - assertFalse(lp.hasGlobalIpv6Address()); - - assertTrue(lp.addLinkAddress(LINKADDRV4)); - assertEquals(2, lp.getLinkAddresses().size()); - assertTrue(lp.hasIpv4Address()); - assertFalse(lp.hasGlobalIpv6Address()); - - assertTrue(lp.addLinkAddress(LINKADDRV6)); - assertEquals(3, lp.getLinkAddresses().size()); - assertTrue(lp.hasIpv4Address()); - assertTrue(lp.hasGlobalIpv6Address()); - - assertTrue(lp.removeLinkAddress(LINKADDRV6LINKLOCAL)); - assertEquals(2, lp.getLinkAddresses().size()); - assertTrue(lp.hasIpv4Address()); - assertTrue(lp.hasGlobalIpv6Address()); - - // Adding an address twice has no effect. - // Removing an address that's not present has no effect. - assertFalse(lp.addLinkAddress(LINKADDRV4)); - assertEquals(2, lp.getLinkAddresses().size()); - assertTrue(lp.hasIpv4Address()); - assertTrue(lp.removeLinkAddress(LINKADDRV4)); - assertEquals(1, lp.getLinkAddresses().size()); - assertFalse(lp.hasIpv4Address()); - assertFalse(lp.removeLinkAddress(LINKADDRV4)); - assertEquals(1, lp.getLinkAddresses().size()); - - // Adding an address that's already present but with different properties causes the - // existing address to be updated and returns true. - // Start with only LINKADDRV6. - assertEquals(1, lp.getLinkAddresses().size()); - assertEquals(LINKADDRV6, getFirstLinkAddress(lp)); - - // Create a LinkAddress object for the same address, but with different flags. - LinkAddress deprecated = new LinkAddress(ADDRV6, 128, - OsConstants.IFA_F_DEPRECATED, OsConstants.RT_SCOPE_UNIVERSE); - assertTrue(deprecated.isSameAddressAs(LINKADDRV6)); - assertFalse(deprecated.equals(LINKADDRV6)); - - // Check that adding it updates the existing address instead of adding a new one. - assertTrue(lp.addLinkAddress(deprecated)); - assertEquals(1, lp.getLinkAddresses().size()); - assertEquals(deprecated, getFirstLinkAddress(lp)); - assertFalse(LINKADDRV6.equals(getFirstLinkAddress(lp))); - - // Removing LINKADDRV6 removes deprecated, because removing addresses ignores properties. - assertTrue(lp.removeLinkAddress(LINKADDRV6)); - assertEquals(0, lp.getLinkAddresses().size()); - } - - @Test - public void testLinkAddresses() { - final LinkProperties lp = new LinkProperties(); - lp.addLinkAddress(LINKADDRV4); - lp.addLinkAddress(LINKADDRV6); - - final LinkProperties lp2 = new LinkProperties(); - lp2.addLinkAddress(LINKADDRV6); - - final LinkProperties lp3 = new LinkProperties(); - final List linkAddresses = Arrays.asList(LINKADDRV4); - lp3.setLinkAddresses(linkAddresses); - - assertFalse(lp.equals(lp2)); - assertFalse(lp2.equals(lp3)); - - lp.removeLinkAddress(LINKADDRV4); - assertTrue(lp.equals(lp2)); - - lp2.setLinkAddresses(lp3.getLinkAddresses()); - assertTrue(lp2.equals(lp3)); - } - - @Test - public void testNat64Prefix() throws Exception { - LinkProperties lp = new LinkProperties(); - lp.addLinkAddress(LINKADDRV4); - lp.addLinkAddress(LINKADDRV6); - - assertNull(lp.getNat64Prefix()); - - IpPrefix p = new IpPrefix("64:ff9b::/96"); - lp.setNat64Prefix(p); - assertEquals(p, lp.getNat64Prefix()); - - p = new IpPrefix("2001:db8:a:b:1:2:3::/96"); - lp.setNat64Prefix(p); - assertEquals(p, lp.getNat64Prefix()); - - p = new IpPrefix("2001:db8:a:b:1:2::/80"); - try { - lp.setNat64Prefix(p); - } catch (IllegalArgumentException expected) { - } - - p = new IpPrefix("64:ff9b::/64"); - try { - lp.setNat64Prefix(p); - } catch (IllegalArgumentException expected) { - } - - assertEquals(new IpPrefix("2001:db8:a:b:1:2:3::/96"), lp.getNat64Prefix()); - - lp.setNat64Prefix(null); - assertNull(lp.getNat64Prefix()); - } - - @Test - public void testIsProvisioned() { - LinkProperties lp4 = new LinkProperties(); - assertFalse("v4only:empty", lp4.isProvisioned()); - lp4.addLinkAddress(LINKADDRV4); - assertFalse("v4only:addr-only", lp4.isProvisioned()); - lp4.addDnsServer(DNS1); - assertFalse("v4only:addr+dns", lp4.isProvisioned()); - lp4.addRoute(new RouteInfo(GATEWAY1)); - assertTrue("v4only:addr+dns+route", lp4.isProvisioned()); - assertTrue("v4only:addr+dns+route", lp4.isIpv4Provisioned()); - assertFalse("v4only:addr+dns+route", lp4.isIpv6Provisioned()); - - LinkProperties lp6 = new LinkProperties(); - assertFalse("v6only:empty", lp6.isProvisioned()); - lp6.addLinkAddress(LINKADDRV6LINKLOCAL); - assertFalse("v6only:fe80-only", lp6.isProvisioned()); - lp6.addDnsServer(DNS6); - assertFalse("v6only:fe80+dns", lp6.isProvisioned()); - lp6.addRoute(new RouteInfo(GATEWAY61)); - assertFalse("v6only:fe80+dns+route", lp6.isProvisioned()); - lp6.addLinkAddress(LINKADDRV6); - assertTrue("v6only:fe80+global+dns+route", lp6.isIpv6Provisioned()); - assertTrue("v6only:fe80+global+dns+route", lp6.isProvisioned()); - lp6.removeLinkAddress(LINKADDRV6LINKLOCAL); - assertFalse("v6only:global+dns+route", lp6.isIpv4Provisioned()); - assertTrue("v6only:global+dns+route", lp6.isIpv6Provisioned()); - assertTrue("v6only:global+dns+route", lp6.isProvisioned()); - - LinkProperties lp46 = new LinkProperties(); - lp46.addLinkAddress(LINKADDRV4); - lp46.addLinkAddress(LINKADDRV6); - lp46.addDnsServer(DNS1); - lp46.addDnsServer(DNS6); - assertFalse("dualstack:missing-routes", lp46.isProvisioned()); - lp46.addRoute(new RouteInfo(GATEWAY1)); - assertTrue("dualstack:v4-provisioned", lp46.isIpv4Provisioned()); - assertFalse("dualstack:v4-provisioned", lp46.isIpv6Provisioned()); - assertTrue("dualstack:v4-provisioned", lp46.isProvisioned()); - lp46.addRoute(new RouteInfo(GATEWAY61)); - assertTrue("dualstack:both-provisioned", lp46.isIpv4Provisioned()); - assertTrue("dualstack:both-provisioned", lp46.isIpv6Provisioned()); - assertTrue("dualstack:both-provisioned", lp46.isProvisioned()); - - // A link with an IPv6 address and default route, but IPv4 DNS server. - LinkProperties mixed = new LinkProperties(); - mixed.addLinkAddress(LINKADDRV6); - mixed.addDnsServer(DNS1); - mixed.addRoute(new RouteInfo(GATEWAY61)); - assertFalse("mixed:addr6+route6+dns4", mixed.isIpv4Provisioned()); - assertFalse("mixed:addr6+route6+dns4", mixed.isIpv6Provisioned()); - assertFalse("mixed:addr6+route6+dns4", mixed.isProvisioned()); - } - - @Test - public void testCompareProvisioning() { - LinkProperties v4lp = new LinkProperties(); - v4lp.addLinkAddress(LINKADDRV4); - v4lp.addRoute(new RouteInfo(GATEWAY1)); - v4lp.addDnsServer(DNS1); - assertTrue(v4lp.isProvisioned()); - - LinkProperties v4r = new LinkProperties(v4lp); - v4r.removeDnsServer(DNS1); - assertFalse(v4r.isProvisioned()); - - assertEquals(ProvisioningChange.STILL_NOT_PROVISIONED, - LinkProperties.compareProvisioning(v4r, v4r)); - assertEquals(ProvisioningChange.LOST_PROVISIONING, - LinkProperties.compareProvisioning(v4lp, v4r)); - assertEquals(ProvisioningChange.GAINED_PROVISIONING, - LinkProperties.compareProvisioning(v4r, v4lp)); - assertEquals(ProvisioningChange.STILL_PROVISIONED, - LinkProperties.compareProvisioning(v4lp, v4lp)); - - // Check that losing IPv4 provisioning on a dualstack network is - // seen as a total loss of provisioning. - LinkProperties v6lp = new LinkProperties(); - v6lp.addLinkAddress(LINKADDRV6); - v6lp.addRoute(new RouteInfo(GATEWAY61)); - v6lp.addDnsServer(DNS6); - assertFalse(v6lp.isIpv4Provisioned()); - assertTrue(v6lp.isIpv6Provisioned()); - assertTrue(v6lp.isProvisioned()); - - LinkProperties v46lp = new LinkProperties(v6lp); - v46lp.addLinkAddress(LINKADDRV4); - v46lp.addRoute(new RouteInfo(GATEWAY1)); - v46lp.addDnsServer(DNS1); - assertTrue(v46lp.isIpv4Provisioned()); - assertTrue(v46lp.isIpv6Provisioned()); - assertTrue(v46lp.isProvisioned()); - - assertEquals(ProvisioningChange.STILL_PROVISIONED, - LinkProperties.compareProvisioning(v4lp, v46lp)); - assertEquals(ProvisioningChange.STILL_PROVISIONED, - LinkProperties.compareProvisioning(v6lp, v46lp)); - assertEquals(ProvisioningChange.LOST_PROVISIONING, - LinkProperties.compareProvisioning(v46lp, v6lp)); - assertEquals(ProvisioningChange.LOST_PROVISIONING, - LinkProperties.compareProvisioning(v46lp, v4lp)); - - // Check that losing and gaining a secondary router does not change - // the provisioning status. - LinkProperties v6lp2 = new LinkProperties(v6lp); - v6lp2.addRoute(new RouteInfo(GATEWAY62)); - assertTrue(v6lp2.isProvisioned()); - - assertEquals(ProvisioningChange.STILL_PROVISIONED, - LinkProperties.compareProvisioning(v6lp2, v6lp)); - assertEquals(ProvisioningChange.STILL_PROVISIONED, - LinkProperties.compareProvisioning(v6lp, v6lp2)); - } - - @Test - public void testIsReachable() { - final LinkProperties v4lp = new LinkProperties(); - assertFalse(v4lp.isReachable(DNS1)); - assertFalse(v4lp.isReachable(DNS2)); - - // Add an on-link route, making the on-link DNS server reachable, - // but there is still no IPv4 address. - assertTrue(v4lp.addRoute(new RouteInfo(new IpPrefix(address("75.208.0.0"), 16)))); - assertFalse(v4lp.isReachable(DNS1)); - assertFalse(v4lp.isReachable(DNS2)); - - // Adding an IPv4 address (right now, any IPv4 address) means we use - // the routes to compute likely reachability. - assertTrue(v4lp.addLinkAddress(new LinkAddress(ADDRV4, 16))); - assertTrue(v4lp.isReachable(DNS1)); - assertFalse(v4lp.isReachable(DNS2)); - - // Adding a default route makes the off-link DNS server reachable. - assertTrue(v4lp.addRoute(new RouteInfo(GATEWAY1))); - assertTrue(v4lp.isReachable(DNS1)); - assertTrue(v4lp.isReachable(DNS2)); - - final LinkProperties v6lp = new LinkProperties(); - final InetAddress kLinkLocalDns = address("fe80::6:1"); - final InetAddress kLinkLocalDnsWithScope = address("fe80::6:2%43"); - final InetAddress kOnLinkDns = address("2001:db8:85a3::53"); - assertFalse(v6lp.isReachable(kLinkLocalDns)); - assertFalse(v6lp.isReachable(kLinkLocalDnsWithScope)); - assertFalse(v6lp.isReachable(kOnLinkDns)); - assertFalse(v6lp.isReachable(DNS6)); - - // Add a link-local route, making the link-local DNS servers reachable. Because - // we assume the presence of an IPv6 link-local address, link-local DNS servers - // are considered reachable, but only those with a non-zero scope identifier. - assertTrue(v6lp.addRoute(new RouteInfo(new IpPrefix(address("fe80::"), 64)))); - assertFalse(v6lp.isReachable(kLinkLocalDns)); - assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope)); - assertFalse(v6lp.isReachable(kOnLinkDns)); - assertFalse(v6lp.isReachable(DNS6)); - - // Add a link-local address--nothing changes. - assertTrue(v6lp.addLinkAddress(LINKADDRV6LINKLOCAL)); - assertFalse(v6lp.isReachable(kLinkLocalDns)); - assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope)); - assertFalse(v6lp.isReachable(kOnLinkDns)); - assertFalse(v6lp.isReachable(DNS6)); - - // Add a global route on link, but no global address yet. DNS servers reachable - // via a route that doesn't require a gateway: give them the benefit of the - // doubt and hope the link-local source address suffices for communication. - assertTrue(v6lp.addRoute(new RouteInfo(new IpPrefix(address("2001:db8:85a3::"), 64)))); - assertFalse(v6lp.isReachable(kLinkLocalDns)); - assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope)); - assertTrue(v6lp.isReachable(kOnLinkDns)); - assertFalse(v6lp.isReachable(DNS6)); - - // Add a global address; the on-link global address DNS server is (still) - // presumed reachable. - assertTrue(v6lp.addLinkAddress(new LinkAddress(ADDRV6, 64))); - assertFalse(v6lp.isReachable(kLinkLocalDns)); - assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope)); - assertTrue(v6lp.isReachable(kOnLinkDns)); - assertFalse(v6lp.isReachable(DNS6)); - - // Adding a default route makes the off-link DNS server reachable. - assertTrue(v6lp.addRoute(new RouteInfo(GATEWAY62))); - assertFalse(v6lp.isReachable(kLinkLocalDns)); - assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope)); - assertTrue(v6lp.isReachable(kOnLinkDns)); - assertTrue(v6lp.isReachable(DNS6)); - - // Check isReachable on stacked links. This requires that the source IP address be assigned - // on the interface returned by the route lookup. - LinkProperties stacked = new LinkProperties(); - - // Can't add a stacked link without an interface name. - stacked.setInterfaceName("v4-test0"); - v6lp.addStackedLink(stacked); - - InetAddress stackedAddress = address("192.0.0.4"); - LinkAddress stackedLinkAddress = new LinkAddress(stackedAddress, 32); - assertFalse(v6lp.isReachable(stackedAddress)); - stacked.addLinkAddress(stackedLinkAddress); - assertFalse(v6lp.isReachable(stackedAddress)); - stacked.addRoute(new RouteInfo(stackedLinkAddress)); - assertTrue(stacked.isReachable(stackedAddress)); - assertTrue(v6lp.isReachable(stackedAddress)); - - assertFalse(v6lp.isReachable(DNS1)); - stacked.addRoute(new RouteInfo((IpPrefix) null, stackedAddress)); - assertTrue(v6lp.isReachable(DNS1)); - } - - @Test - public void testLinkPropertiesEnsureDirectlyConnectedRoutes() { - // IPv4 case: no route added initially - LinkProperties rmnet0 = new LinkProperties(); - rmnet0.setInterfaceName("rmnet0"); - rmnet0.addLinkAddress(new LinkAddress("10.0.0.2/8")); - RouteInfo directRoute0 = new RouteInfo(new IpPrefix("10.0.0.0/8"), null, - rmnet0.getInterfaceName()); - - // Since no routes is added explicitly, getAllRoutes() should return empty. - assertTrue(rmnet0.getAllRoutes().isEmpty()); - rmnet0.ensureDirectlyConnectedRoutes(); - // ensureDirectlyConnectedRoutes() should have added the missing local route. - assertEqualRoutes(Collections.singletonList(directRoute0), rmnet0.getAllRoutes()); - - // IPv4 case: both direct and default routes added initially - LinkProperties rmnet1 = new LinkProperties(); - rmnet1.setInterfaceName("rmnet1"); - rmnet1.addLinkAddress(new LinkAddress("10.0.0.3/8")); - RouteInfo defaultRoute1 = new RouteInfo((IpPrefix) null, address("10.0.0.1"), - rmnet1.getInterfaceName()); - RouteInfo directRoute1 = new RouteInfo(new IpPrefix("10.0.0.0/8"), null, - rmnet1.getInterfaceName()); - rmnet1.addRoute(defaultRoute1); - rmnet1.addRoute(directRoute1); - - // Check added routes - assertEqualRoutes(Arrays.asList(defaultRoute1, directRoute1), rmnet1.getAllRoutes()); - // ensureDirectlyConnectedRoutes() shouldn't change the routes since direct connected - // route is already part of the configuration. - rmnet1.ensureDirectlyConnectedRoutes(); - assertEqualRoutes(Arrays.asList(defaultRoute1, directRoute1), rmnet1.getAllRoutes()); - - // IPv6 case: only default routes added initially - LinkProperties rmnet2 = new LinkProperties(); - rmnet2.setInterfaceName("rmnet2"); - rmnet2.addLinkAddress(new LinkAddress("fe80::cafe/64")); - rmnet2.addLinkAddress(new LinkAddress("2001:db8::2/64")); - RouteInfo defaultRoute2 = new RouteInfo((IpPrefix) null, address("2001:db8::1"), - rmnet2.getInterfaceName()); - RouteInfo directRoute2 = new RouteInfo(new IpPrefix("2001:db8::/64"), null, - rmnet2.getInterfaceName()); - RouteInfo linkLocalRoute2 = new RouteInfo(new IpPrefix("fe80::/64"), null, - rmnet2.getInterfaceName()); - rmnet2.addRoute(defaultRoute2); - - assertEqualRoutes(Arrays.asList(defaultRoute2), rmnet2.getAllRoutes()); - rmnet2.ensureDirectlyConnectedRoutes(); - assertEqualRoutes(Arrays.asList(defaultRoute2, directRoute2, linkLocalRoute2), - rmnet2.getAllRoutes()); - - // Corner case: no interface name - LinkProperties rmnet3 = new LinkProperties(); - rmnet3.addLinkAddress(new LinkAddress("192.168.0.2/24")); - RouteInfo directRoute3 = new RouteInfo(new IpPrefix("192.168.0.0/24"), null, - rmnet3.getInterfaceName()); - - assertTrue(rmnet3.getAllRoutes().isEmpty()); - rmnet3.ensureDirectlyConnectedRoutes(); - assertEqualRoutes(Collections.singletonList(directRoute3), rmnet3.getAllRoutes()); - } - - private void assertEqualRoutes(Collection expected, Collection actual) { - Set expectedSet = new ArraySet<>(expected); - Set actualSet = new ArraySet<>(actual); - // Duplicated entries in actual routes are considered failures - assertEquals(actual.size(), actualSet.size()); - - assertEquals(expectedSet, actualSet); - } - - private static LinkProperties makeLinkPropertiesForParceling() { - LinkProperties source = new LinkProperties(); - source.setInterfaceName(NAME); - - source.addLinkAddress(LINKADDRV4); - source.addLinkAddress(LINKADDRV6); - - source.addDnsServer(DNS1); - source.addDnsServer(DNS2); - source.addDnsServer(GATEWAY62); - - source.addPcscfServer(TESTIPV4ADDR); - source.addPcscfServer(TESTIPV6ADDR); - - source.setUsePrivateDns(true); - source.setPrivateDnsServerName(PRIV_DNS_SERVER_NAME); - - source.setDomains(DOMAINS); - - source.addRoute(new RouteInfo(GATEWAY1)); - source.addRoute(new RouteInfo(GATEWAY2)); - - source.addValidatedPrivateDnsServer(DNS6); - source.addValidatedPrivateDnsServer(GATEWAY61); - source.addValidatedPrivateDnsServer(TESTIPV6ADDR); - - source.setHttpProxy(ProxyInfo.buildDirectProxy("test", 8888)); - - source.setMtu(MTU); - - source.setTcpBufferSizes(TCP_BUFFER_SIZES); - - source.setNat64Prefix(new IpPrefix("2001:db8:1:2:64:64::/96")); - - final LinkProperties stacked = new LinkProperties(); - stacked.setInterfaceName("test-stacked"); - source.addStackedLink(stacked); - - return source; - } - - @Test @IgnoreAfter(Build.VERSION_CODES.Q) - public void testLinkPropertiesParcelable_Q() throws Exception { - final LinkProperties source = makeLinkPropertiesForParceling(); - assertParcelSane(source, 14 /* fieldCount */); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testLinkPropertiesParcelable() throws Exception { - final LinkProperties source = makeLinkPropertiesForParceling(); - - source.setWakeOnLanSupported(true); - source.setCaptivePortalApiUrl(CAPPORT_API_URL); - source.setCaptivePortalData((CaptivePortalData) getCaptivePortalData()); - source.setDhcpServerAddress((Inet4Address) GATEWAY1); - assertParcelSane(new LinkProperties(source, true /* parcelSensitiveFields */), - 18 /* fieldCount */); - - // Verify that without using a sensitiveFieldsParcelingCopy, sensitive fields are cleared. - final LinkProperties sanitized = new LinkProperties(source); - sanitized.setCaptivePortalApiUrl(null); - sanitized.setCaptivePortalData(null); - assertEquals(sanitized, parcelingRoundTrip(source)); - } - - // Parceling of the scope was broken until Q-QPR2 - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testLinkLocalDnsServerParceling() throws Exception { - final String strAddress = "fe80::1%lo"; - final LinkProperties lp = new LinkProperties(); - lp.addDnsServer(address(strAddress)); - final LinkProperties unparceled = parcelingRoundTrip(lp); - // Inet6Address#equals does not test for the scope id - assertEquals(strAddress, unparceled.getDnsServers().get(0).getHostAddress()); - } - - @Test - public void testParcelUninitialized() throws Exception { - LinkProperties empty = new LinkProperties(); - assertParcelingIsLossless(empty); - } - - @Test - public void testConstructor() { - LinkProperties lp = new LinkProperties(); - checkEmpty(lp); - assertLinkPropertiesEqual(lp, new LinkProperties(lp)); - assertLinkPropertiesEqual(lp, new LinkProperties()); - - lp = makeTestObject(); - assertLinkPropertiesEqual(lp, new LinkProperties(lp)); - } - - @Test - public void testDnsServers() { - final LinkProperties lp = new LinkProperties(); - final List dnsServers = Arrays.asList(DNS1, DNS2); - lp.setDnsServers(dnsServers); - assertEquals(2, lp.getDnsServers().size()); - assertEquals(DNS1, lp.getDnsServers().get(0)); - assertEquals(DNS2, lp.getDnsServers().get(1)); - - lp.removeDnsServer(DNS1); - assertEquals(1, lp.getDnsServers().size()); - assertEquals(DNS2, lp.getDnsServers().get(0)); - - lp.addDnsServer(DNS6); - assertEquals(2, lp.getDnsServers().size()); - assertEquals(DNS2, lp.getDnsServers().get(0)); - assertEquals(DNS6, lp.getDnsServers().get(1)); - } - - @Test - public void testValidatedPrivateDnsServers() { - final LinkProperties lp = new LinkProperties(); - final List privDnsServers = Arrays.asList(PRIVDNS1, PRIVDNS2); - lp.setValidatedPrivateDnsServers(privDnsServers); - assertEquals(2, lp.getValidatedPrivateDnsServers().size()); - assertEquals(PRIVDNS1, lp.getValidatedPrivateDnsServers().get(0)); - assertEquals(PRIVDNS2, lp.getValidatedPrivateDnsServers().get(1)); - - lp.removeValidatedPrivateDnsServer(PRIVDNS1); - assertEquals(1, lp.getValidatedPrivateDnsServers().size()); - assertEquals(PRIVDNS2, lp.getValidatedPrivateDnsServers().get(0)); - - lp.addValidatedPrivateDnsServer(PRIVDNS6); - assertEquals(2, lp.getValidatedPrivateDnsServers().size()); - assertEquals(PRIVDNS2, lp.getValidatedPrivateDnsServers().get(0)); - assertEquals(PRIVDNS6, lp.getValidatedPrivateDnsServers().get(1)); - } - - @Test - public void testPcscfServers() { - final LinkProperties lp = new LinkProperties(); - final List pcscfServers = Arrays.asList(PCSCFV4); - lp.setPcscfServers(pcscfServers); - assertEquals(1, lp.getPcscfServers().size()); - assertEquals(PCSCFV4, lp.getPcscfServers().get(0)); - - lp.removePcscfServer(PCSCFV4); - assertEquals(0, lp.getPcscfServers().size()); - - lp.addPcscfServer(PCSCFV6); - assertEquals(1, lp.getPcscfServers().size()); - assertEquals(PCSCFV6, lp.getPcscfServers().get(0)); - } - - @Test - public void testTcpBufferSizes() { - final LinkProperties lp = makeTestObject(); - assertEquals(TCP_BUFFER_SIZES, lp.getTcpBufferSizes()); - - lp.setTcpBufferSizes(null); - assertNull(lp.getTcpBufferSizes()); - } - - @Test - public void testHasIpv6DefaultRoute() { - final LinkProperties lp = makeTestObject(); - assertFalse(lp.hasIPv6DefaultRoute()); - - lp.addRoute(new RouteInfo(GATEWAY61)); - assertTrue(lp.hasIPv6DefaultRoute()); - } - - @Test - public void testHttpProxy() { - final LinkProperties lp = makeTestObject(); - assertTrue(lp.getHttpProxy().equals(ProxyInfo.buildDirectProxy("test", 8888))); - } - - @Test - public void testPrivateDnsServerName() { - final LinkProperties lp = makeTestObject(); - assertEquals(PRIV_DNS_SERVER_NAME, lp.getPrivateDnsServerName()); - - lp.setPrivateDnsServerName(null); - assertNull(lp.getPrivateDnsServerName()); - } - - @Test - public void testUsePrivateDns() { - final LinkProperties lp = makeTestObject(); - assertTrue(lp.isPrivateDnsActive()); - - lp.clear(); - assertFalse(lp.isPrivateDnsActive()); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testDhcpServerAddress() { - final LinkProperties lp = makeTestObject(); - assertEquals(DHCPSERVER, lp.getDhcpServerAddress()); - - lp.clear(); - assertNull(lp.getDhcpServerAddress()); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testWakeOnLanSupported() { - final LinkProperties lp = makeTestObject(); - assertTrue(lp.isWakeOnLanSupported()); - - lp.clear(); - assertFalse(lp.isWakeOnLanSupported()); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testCaptivePortalApiUrl() { - final LinkProperties lp = makeTestObject(); - assertEquals(CAPPORT_API_URL, lp.getCaptivePortalApiUrl()); - - lp.clear(); - assertNull(lp.getCaptivePortalApiUrl()); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testCaptivePortalData() { - final LinkProperties lp = makeTestObject(); - assertEquals(getCaptivePortalData(), lp.getCaptivePortalData()); - - lp.clear(); - assertNull(lp.getCaptivePortalData()); - } - - private LinkProperties makeIpv4LinkProperties() { - final LinkProperties linkProperties = new LinkProperties(); - linkProperties.setInterfaceName(NAME); - linkProperties.addLinkAddress(LINKADDRV4); - linkProperties.addDnsServer(DNS1); - linkProperties.addRoute(new RouteInfo(GATEWAY1)); - linkProperties.addRoute(new RouteInfo(GATEWAY2)); - return linkProperties; - } - - private LinkProperties makeIpv6LinkProperties() { - final LinkProperties linkProperties = new LinkProperties(); - linkProperties.setInterfaceName(NAME); - linkProperties.addLinkAddress(LINKADDRV6); - linkProperties.addDnsServer(DNS6); - linkProperties.addRoute(new RouteInfo(GATEWAY61)); - linkProperties.addRoute(new RouteInfo(GATEWAY62)); - return linkProperties; - } - - @Test - public void testHasIpv4DefaultRoute() { - final LinkProperties Ipv4 = makeIpv4LinkProperties(); - assertTrue(Ipv4.hasIpv4DefaultRoute()); - final LinkProperties Ipv6 = makeIpv6LinkProperties(); - assertFalse(Ipv6.hasIpv4DefaultRoute()); - } - - @Test - public void testHasIpv4DnsServer() { - final LinkProperties Ipv4 = makeIpv4LinkProperties(); - assertTrue(Ipv4.hasIpv4DnsServer()); - final LinkProperties Ipv6 = makeIpv6LinkProperties(); - assertFalse(Ipv6.hasIpv4DnsServer()); - } - - @Test - public void testHasIpv6DnsServer() { - final LinkProperties Ipv4 = makeIpv4LinkProperties(); - assertFalse(Ipv4.hasIpv6DnsServer()); - final LinkProperties Ipv6 = makeIpv6LinkProperties(); - assertTrue(Ipv6.hasIpv6DnsServer()); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testHasIpv4UnreachableDefaultRoute() { - final LinkProperties lp = makeTestObject(); - assertFalse(lp.hasIpv4UnreachableDefaultRoute()); - assertFalse(lp.hasIpv6UnreachableDefaultRoute()); - - lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE)); - assertTrue(lp.hasIpv4UnreachableDefaultRoute()); - assertFalse(lp.hasIpv6UnreachableDefaultRoute()); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testHasIpv6UnreachableDefaultRoute() { - final LinkProperties lp = makeTestObject(); - assertFalse(lp.hasIpv6UnreachableDefaultRoute()); - assertFalse(lp.hasIpv4UnreachableDefaultRoute()); - - lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE)); - assertTrue(lp.hasIpv6UnreachableDefaultRoute()); - assertFalse(lp.hasIpv4UnreachableDefaultRoute()); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testRouteAddWithSameKey() throws Exception { - LinkProperties lp = new LinkProperties(); - lp.setInterfaceName("wlan0"); - final IpPrefix v6 = new IpPrefix("64:ff9b::/96"); - lp.addRoute(new RouteInfo(v6, address("fe80::1"), "wlan0", RTN_UNICAST, 1280)); - assertEquals(1, lp.getRoutes().size()); - lp.addRoute(new RouteInfo(v6, address("fe80::1"), "wlan0", RTN_UNICAST, 1500)); - assertEquals(1, lp.getRoutes().size()); - final IpPrefix v4 = new IpPrefix("192.0.2.128/25"); - lp.addRoute(new RouteInfo(v4, address("192.0.2.1"), "wlan0", RTN_UNICAST, 1460)); - assertEquals(2, lp.getRoutes().size()); - lp.addRoute(new RouteInfo(v4, address("192.0.2.1"), "wlan0", RTN_THROW, 1460)); - assertEquals(2, lp.getRoutes().size()); - } -} diff --git a/packages/Connectivity/tests/common/java/android/net/MatchAllNetworkSpecifierTest.kt b/packages/Connectivity/tests/common/java/android/net/MatchAllNetworkSpecifierTest.kt deleted file mode 100644 index a5e44d59fcabf..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/MatchAllNetworkSpecifierTest.kt +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net - -import android.net.wifi.aware.DiscoverySession -import android.net.wifi.aware.PeerHandle -import android.net.wifi.aware.WifiAwareNetworkSpecifier -import android.os.Build -import androidx.test.filters.SmallTest -import androidx.test.runner.AndroidJUnit4 - -import com.android.testutils.assertParcelSane -import com.android.testutils.DevSdkIgnoreRule -import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter -import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo - -import java.lang.IllegalStateException - -import org.junit.Assert.assertFalse -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.Mockito - -@RunWith(AndroidJUnit4::class) -@SmallTest -class MatchAllNetworkSpecifierTest { - @Rule @JvmField - val ignoreRule: DevSdkIgnoreRule = DevSdkIgnoreRule() - - private val specifier = MatchAllNetworkSpecifier() - private val discoverySession = Mockito.mock(DiscoverySession::class.java) - private val peerHandle = Mockito.mock(PeerHandle::class.java) - private val wifiAwareNetworkSpecifier = WifiAwareNetworkSpecifier.Builder(discoverySession, - peerHandle).build() - - @Test - fun testParcel() { - assertParcelSane(MatchAllNetworkSpecifier(), 0) - } - - @Test - @IgnoreUpTo(Build.VERSION_CODES.Q) - @IgnoreAfter(Build.VERSION_CODES.R) - // Only run this test on Android R. - // The method - satisfiedBy() has changed to canBeSatisfiedBy() starting from Android R, so the - // method - canBeSatisfiedBy() cannot be found when running this test on Android Q. - fun testCanBeSatisfiedBy_OnlyForR() { - // MatchAllNetworkSpecifier didn't follow its parent class to change the satisfiedBy() to - // canBeSatisfiedBy(), so if a caller calls MatchAllNetworkSpecifier#canBeSatisfiedBy(), the - // NetworkSpecifier#canBeSatisfiedBy() will be called actually, and false will be returned. - // Although it's not meeting the expectation, the behavior still needs to be verified. - assertFalse(specifier.canBeSatisfiedBy(wifiAwareNetworkSpecifier)) - } - - @Test(expected = IllegalStateException::class) - @IgnoreUpTo(Build.VERSION_CODES.R) - fun testCanBeSatisfiedBy() { - specifier.canBeSatisfiedBy(wifiAwareNetworkSpecifier) - } -} diff --git a/packages/Connectivity/tests/common/java/android/net/NattKeepalivePacketDataTest.kt b/packages/Connectivity/tests/common/java/android/net/NattKeepalivePacketDataTest.kt deleted file mode 100644 index 46f39dd016fd2..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/NattKeepalivePacketDataTest.kt +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net - -import android.net.InvalidPacketException.ERROR_INVALID_IP_ADDRESS -import android.net.InvalidPacketException.ERROR_INVALID_PORT -import android.net.NattSocketKeepalive.NATT_PORT -import android.os.Build -import androidx.test.filters.SmallTest -import androidx.test.runner.AndroidJUnit4 -import com.android.testutils.assertEqualBothWays -import com.android.testutils.assertFieldCountEquals -import com.android.testutils.assertParcelSane -import com.android.testutils.DevSdkIgnoreRule -import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo -import com.android.testutils.parcelingRoundTrip -import java.net.InetAddress -import org.junit.Assert.assertEquals -import org.junit.Assert.assertNotEquals -import org.junit.Assert.fail -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -@SmallTest -class NattKeepalivePacketDataTest { - @Rule @JvmField - val ignoreRule: DevSdkIgnoreRule = DevSdkIgnoreRule() - - /* Refer to the definition in {@code NattKeepalivePacketData} */ - private val IPV4_HEADER_LENGTH = 20 - private val UDP_HEADER_LENGTH = 8 - - private val TEST_PORT = 4243 - private val TEST_PORT2 = 4244 - private val TEST_SRC_ADDRV4 = "198.168.0.2".address() - private val TEST_DST_ADDRV4 = "198.168.0.1".address() - private val TEST_ADDRV6 = "2001:db8::1".address() - - private fun String.address() = InetAddresses.parseNumericAddress(this) - private fun nattKeepalivePacket( - srcAddress: InetAddress? = TEST_SRC_ADDRV4, - srcPort: Int = TEST_PORT, - dstAddress: InetAddress? = TEST_DST_ADDRV4, - dstPort: Int = NATT_PORT - ) = NattKeepalivePacketData.nattKeepalivePacket(srcAddress, srcPort, dstAddress, dstPort) - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - fun testConstructor() { - try { - nattKeepalivePacket(dstPort = TEST_PORT) - fail("Dst port is not NATT port should cause exception") - } catch (e: InvalidPacketException) { - assertEquals(e.error, ERROR_INVALID_PORT) - } - - try { - nattKeepalivePacket(srcAddress = TEST_ADDRV6) - fail("A v6 srcAddress should cause exception") - } catch (e: InvalidPacketException) { - assertEquals(e.error, ERROR_INVALID_IP_ADDRESS) - } - - try { - nattKeepalivePacket(dstAddress = TEST_ADDRV6) - fail("A v6 dstAddress should cause exception") - } catch (e: InvalidPacketException) { - assertEquals(e.error, ERROR_INVALID_IP_ADDRESS) - } - - try { - parcelingRoundTrip( - NattKeepalivePacketData(TEST_SRC_ADDRV4, TEST_PORT, TEST_DST_ADDRV4, TEST_PORT, - byteArrayOf(12, 31, 22, 44))) - fail("Invalid data should cause exception") - } catch (e: IllegalArgumentException) { } - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - fun testParcel() { - assertParcelSane(nattKeepalivePacket(), 0) - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - fun testEquals() { - assertEqualBothWays(nattKeepalivePacket(), nattKeepalivePacket()) - assertNotEquals(nattKeepalivePacket(dstAddress = TEST_SRC_ADDRV4), nattKeepalivePacket()) - assertNotEquals(nattKeepalivePacket(srcAddress = TEST_DST_ADDRV4), nattKeepalivePacket()) - // Test src port only because dst port have to be NATT_PORT - assertNotEquals(nattKeepalivePacket(srcPort = TEST_PORT2), nattKeepalivePacket()) - // Make sure the parceling test is updated if fields are added in the base class. - assertFieldCountEquals(5, KeepalivePacketData::class.java) - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - fun testHashCode() { - assertEquals(nattKeepalivePacket().hashCode(), nattKeepalivePacket().hashCode()) - } -} \ No newline at end of file diff --git a/packages/Connectivity/tests/common/java/android/net/NetworkAgentConfigTest.kt b/packages/Connectivity/tests/common/java/android/net/NetworkAgentConfigTest.kt deleted file mode 100644 index 2b45b3d69ce9f..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/NetworkAgentConfigTest.kt +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net - -import android.os.Build -import androidx.test.filters.SmallTest -import androidx.test.runner.AndroidJUnit4 -import com.android.modules.utils.build.SdkLevel.isAtLeastS -import com.android.testutils.DevSdkIgnoreRule -import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo -import com.android.testutils.assertParcelSane -import org.junit.Assert.assertEquals -import org.junit.Assert.assertFalse -import org.junit.Assert.assertTrue -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -@SmallTest -class NetworkAgentConfigTest { - @Rule @JvmField - val ignoreRule = DevSdkIgnoreRule() - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - fun testParcelNetworkAgentConfig() { - val config = NetworkAgentConfig.Builder().apply { - setExplicitlySelected(true) - setLegacyType(ConnectivityManager.TYPE_ETHERNET) - setSubscriberId("MySubId") - setPartialConnectivityAcceptable(false) - setUnvalidatedConnectivityAcceptable(true) - if (isAtLeastS()) { - setBypassableVpn(true) - } - }.build() - if (isAtLeastS()) { - // From S, the config will have 12 items - assertParcelSane(config, 12) - } else { - // For R or below, the config will have 10 items - assertParcelSane(config, 10) - } - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - fun testBuilder() { - val config = NetworkAgentConfig.Builder().apply { - setExplicitlySelected(true) - setLegacyType(ConnectivityManager.TYPE_ETHERNET) - setSubscriberId("MySubId") - setPartialConnectivityAcceptable(false) - setUnvalidatedConnectivityAcceptable(true) - setLegacyTypeName("TEST_NETWORK") - if (isAtLeastS()) { - setNat64DetectionEnabled(false) - setProvisioningNotificationEnabled(false) - setBypassableVpn(true) - } - }.build() - - assertTrue(config.isExplicitlySelected()) - assertEquals(ConnectivityManager.TYPE_ETHERNET, config.getLegacyType()) - assertEquals("MySubId", config.getSubscriberId()) - assertFalse(config.isPartialConnectivityAcceptable()) - assertTrue(config.isUnvalidatedConnectivityAcceptable()) - assertEquals("TEST_NETWORK", config.getLegacyTypeName()) - if (isAtLeastS()) { - assertFalse(config.isNat64DetectionEnabled()) - assertFalse(config.isProvisioningNotificationEnabled()) - assertTrue(config.isBypassableVpn()) - } else { - assertTrue(config.isNat64DetectionEnabled()) - assertTrue(config.isProvisioningNotificationEnabled()) - } - } -} diff --git a/packages/Connectivity/tests/common/java/android/net/NetworkCapabilitiesTest.java b/packages/Connectivity/tests/common/java/android/net/NetworkCapabilitiesTest.java deleted file mode 100644 index 9537786055565..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/NetworkCapabilitiesTest.java +++ /dev/null @@ -1,1170 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static android.net.NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED; -import static android.net.NetworkCapabilities.MAX_TRANSPORT; -import static android.net.NetworkCapabilities.MIN_TRANSPORT; -import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL; -import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS; -import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS; -import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND; -import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; -import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS; -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_ROAMING; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; -import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID; -import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE; -import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY; -import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P; -import static android.net.NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION; -import static android.net.NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS; -import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS; -import static android.net.NetworkCapabilities.SIGNAL_STRENGTH_UNSPECIFIED; -import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; -import static android.net.NetworkCapabilities.TRANSPORT_TEST; -import static android.net.NetworkCapabilities.TRANSPORT_VPN; -import static android.net.NetworkCapabilities.TRANSPORT_WIFI; -import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE; -import static android.os.Process.INVALID_UID; - -import static com.android.modules.utils.build.SdkLevel.isAtLeastR; -import static com.android.modules.utils.build.SdkLevel.isAtLeastS; -import static com.android.net.module.util.NetworkCapabilitiesUtils.TRANSPORT_USB; -import static com.android.testutils.MiscAsserts.assertEmpty; -import static com.android.testutils.MiscAsserts.assertThrows; -import static com.android.testutils.ParcelUtils.assertParcelSane; -import static com.android.testutils.ParcelUtils.assertParcelingIsLossless; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.junit.Assume.assumeTrue; - -import android.net.wifi.aware.DiscoverySession; -import android.net.wifi.aware.PeerHandle; -import android.net.wifi.aware.WifiAwareNetworkSpecifier; -import android.os.Build; -import android.test.suitebuilder.annotation.SmallTest; -import android.util.ArraySet; -import android.util.Range; - -import androidx.test.runner.AndroidJUnit4; - -import com.android.testutils.CompatUtil; -import com.android.testutils.DevSdkIgnoreRule; -import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mockito; - -import java.util.Arrays; -import java.util.Set; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class NetworkCapabilitiesTest { - private static final String TEST_SSID = "TEST_SSID"; - private static final String DIFFERENT_TEST_SSID = "DIFFERENT_TEST_SSID"; - private static final int TEST_SUBID1 = 1; - private static final int TEST_SUBID2 = 2; - private static final int TEST_SUBID3 = 3; - - @Rule - public DevSdkIgnoreRule mDevSdkIgnoreRule = new DevSdkIgnoreRule(); - - private DiscoverySession mDiscoverySession = Mockito.mock(DiscoverySession.class); - private PeerHandle mPeerHandle = Mockito.mock(PeerHandle.class); - - @Test - public void testMaybeMarkCapabilitiesRestricted() { - // check that internet does not get restricted - NetworkCapabilities netCap = new NetworkCapabilities(); - netCap.addCapability(NET_CAPABILITY_INTERNET); - netCap.maybeMarkCapabilitiesRestricted(); - assertTrue(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); - - // metered-ness shouldn't matter - netCap = new NetworkCapabilities(); - netCap.addCapability(NET_CAPABILITY_INTERNET); - netCap.addCapability(NET_CAPABILITY_NOT_METERED); - netCap.maybeMarkCapabilitiesRestricted(); - assertTrue(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); - netCap = new NetworkCapabilities(); - netCap.addCapability(NET_CAPABILITY_INTERNET); - netCap.removeCapability(NET_CAPABILITY_NOT_METERED); - netCap.maybeMarkCapabilitiesRestricted(); - assertTrue(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); - - // add EIMS - bundled with unrestricted means it's unrestricted - netCap = new NetworkCapabilities(); - netCap.addCapability(NET_CAPABILITY_INTERNET); - netCap.addCapability(NET_CAPABILITY_EIMS); - netCap.addCapability(NET_CAPABILITY_NOT_METERED); - netCap.maybeMarkCapabilitiesRestricted(); - assertTrue(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); - netCap = new NetworkCapabilities(); - netCap.addCapability(NET_CAPABILITY_INTERNET); - netCap.addCapability(NET_CAPABILITY_EIMS); - netCap.removeCapability(NET_CAPABILITY_NOT_METERED); - netCap.maybeMarkCapabilitiesRestricted(); - assertTrue(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); - - // just a restricted cap should be restricted regardless of meteredness - netCap = new NetworkCapabilities(); - netCap.addCapability(NET_CAPABILITY_EIMS); - netCap.addCapability(NET_CAPABILITY_NOT_METERED); - netCap.maybeMarkCapabilitiesRestricted(); - assertFalse(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); - netCap = new NetworkCapabilities(); - netCap.addCapability(NET_CAPABILITY_EIMS); - netCap.removeCapability(NET_CAPABILITY_NOT_METERED); - netCap.maybeMarkCapabilitiesRestricted(); - assertFalse(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); - - // try 2 restricted caps - netCap = new NetworkCapabilities(); - netCap.addCapability(NET_CAPABILITY_CBS); - netCap.addCapability(NET_CAPABILITY_EIMS); - netCap.addCapability(NET_CAPABILITY_NOT_METERED); - netCap.maybeMarkCapabilitiesRestricted(); - assertFalse(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); - netCap = new NetworkCapabilities(); - netCap.addCapability(NET_CAPABILITY_CBS); - netCap.addCapability(NET_CAPABILITY_EIMS); - netCap.removeCapability(NET_CAPABILITY_NOT_METERED); - netCap.maybeMarkCapabilitiesRestricted(); - assertFalse(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); - } - - @Test - public void testDescribeImmutableDifferences() { - NetworkCapabilities nc1; - NetworkCapabilities nc2; - - // Transports changing - nc1 = new NetworkCapabilities().addTransportType(TRANSPORT_CELLULAR); - nc2 = new NetworkCapabilities().addTransportType(TRANSPORT_WIFI); - assertNotEquals("", nc1.describeImmutableDifferences(nc2)); - assertEquals("", nc1.describeImmutableDifferences(nc1)); - - // Mutable capability changing - nc1 = new NetworkCapabilities().addCapability(NET_CAPABILITY_VALIDATED); - nc2 = new NetworkCapabilities(); - assertEquals("", nc1.describeImmutableDifferences(nc2)); - assertEquals("", nc1.describeImmutableDifferences(nc1)); - - // NOT_METERED changing (http://b/63326103) - nc1 = new NetworkCapabilities() - .addCapability(NET_CAPABILITY_NOT_METERED) - .addCapability(NET_CAPABILITY_INTERNET); - nc2 = new NetworkCapabilities().addCapability(NET_CAPABILITY_INTERNET); - assertEquals("", nc1.describeImmutableDifferences(nc2)); - assertEquals("", nc1.describeImmutableDifferences(nc1)); - - // Immutable capability changing - nc1 = new NetworkCapabilities() - .addCapability(NET_CAPABILITY_INTERNET) - .removeCapability(NET_CAPABILITY_NOT_RESTRICTED); - nc2 = new NetworkCapabilities().addCapability(NET_CAPABILITY_INTERNET); - assertNotEquals("", nc1.describeImmutableDifferences(nc2)); - assertEquals("", nc1.describeImmutableDifferences(nc1)); - - // Specifier changing - nc1 = new NetworkCapabilities().addTransportType(TRANSPORT_WIFI); - nc2 = new NetworkCapabilities() - .addTransportType(TRANSPORT_WIFI) - .setNetworkSpecifier(CompatUtil.makeEthernetNetworkSpecifier("eth42")); - assertNotEquals("", nc1.describeImmutableDifferences(nc2)); - assertEquals("", nc1.describeImmutableDifferences(nc1)); - } - - @Test - public void testLinkBandwidthUtils() { - assertEquals(LINK_BANDWIDTH_UNSPECIFIED, NetworkCapabilities - .minBandwidth(LINK_BANDWIDTH_UNSPECIFIED, LINK_BANDWIDTH_UNSPECIFIED)); - assertEquals(10, NetworkCapabilities - .minBandwidth(LINK_BANDWIDTH_UNSPECIFIED, 10)); - assertEquals(10, NetworkCapabilities - .minBandwidth(10, LINK_BANDWIDTH_UNSPECIFIED)); - assertEquals(10, NetworkCapabilities - .minBandwidth(10, 20)); - - assertEquals(LINK_BANDWIDTH_UNSPECIFIED, NetworkCapabilities - .maxBandwidth(LINK_BANDWIDTH_UNSPECIFIED, LINK_BANDWIDTH_UNSPECIFIED)); - assertEquals(10, NetworkCapabilities - .maxBandwidth(LINK_BANDWIDTH_UNSPECIFIED, 10)); - assertEquals(10, NetworkCapabilities - .maxBandwidth(10, LINK_BANDWIDTH_UNSPECIFIED)); - assertEquals(20, NetworkCapabilities - .maxBandwidth(10, 20)); - } - - @Test - public void testSetUids() { - final NetworkCapabilities netCap = new NetworkCapabilities(); - // Null uids match all UIDs - netCap.setUids(null); - assertTrue(netCap.appliesToUid(10)); - assertTrue(netCap.appliesToUid(200)); - assertTrue(netCap.appliesToUid(3000)); - assertTrue(netCap.appliesToUid(10010)); - assertTrue(netCap.appliesToUidRange(new UidRange(50, 100))); - assertTrue(netCap.appliesToUidRange(new UidRange(70, 72))); - assertTrue(netCap.appliesToUidRange(new UidRange(3500, 3912))); - assertTrue(netCap.appliesToUidRange(new UidRange(1, 100000))); - - if (isAtLeastS()) { - final Set> uids = new ArraySet<>(); - uids.add(uidRange(50, 100)); - uids.add(uidRange(3000, 4000)); - netCap.setUids(uids); - assertTrue(netCap.appliesToUid(50)); - assertTrue(netCap.appliesToUid(80)); - assertTrue(netCap.appliesToUid(100)); - assertTrue(netCap.appliesToUid(3000)); - assertTrue(netCap.appliesToUid(3001)); - assertFalse(netCap.appliesToUid(10)); - assertFalse(netCap.appliesToUid(25)); - assertFalse(netCap.appliesToUid(49)); - assertFalse(netCap.appliesToUid(101)); - assertFalse(netCap.appliesToUid(2000)); - assertFalse(netCap.appliesToUid(100000)); - - assertTrue(netCap.appliesToUidRange(new UidRange(50, 100))); - assertTrue(netCap.appliesToUidRange(new UidRange(70, 72))); - assertTrue(netCap.appliesToUidRange(new UidRange(3500, 3912))); - assertFalse(netCap.appliesToUidRange(new UidRange(1, 100))); - assertFalse(netCap.appliesToUidRange(new UidRange(49, 100))); - assertFalse(netCap.appliesToUidRange(new UidRange(1, 10))); - assertFalse(netCap.appliesToUidRange(new UidRange(60, 101))); - assertFalse(netCap.appliesToUidRange(new UidRange(60, 3400))); - - NetworkCapabilities netCap2 = new NetworkCapabilities(); - // A new netcap object has null UIDs, so anything will satisfy it. - assertTrue(netCap2.satisfiedByUids(netCap)); - // Still not equal though. - assertFalse(netCap2.equalsUids(netCap)); - netCap2.setUids(uids); - assertTrue(netCap2.satisfiedByUids(netCap)); - assertTrue(netCap.equalsUids(netCap2)); - assertTrue(netCap2.equalsUids(netCap)); - - uids.add(uidRange(600, 700)); - netCap2.setUids(uids); - assertFalse(netCap2.satisfiedByUids(netCap)); - assertFalse(netCap.appliesToUid(650)); - assertTrue(netCap2.appliesToUid(650)); - netCap.combineCapabilities(netCap2); - assertTrue(netCap2.satisfiedByUids(netCap)); - assertTrue(netCap.appliesToUid(650)); - assertFalse(netCap.appliesToUid(500)); - - assertTrue(new NetworkCapabilities().satisfiedByUids(netCap)); - netCap.combineCapabilities(new NetworkCapabilities()); - assertTrue(netCap.appliesToUid(500)); - assertTrue(netCap.appliesToUidRange(new UidRange(1, 100000))); - assertFalse(netCap2.appliesToUid(500)); - assertFalse(netCap2.appliesToUidRange(new UidRange(1, 100000))); - assertTrue(new NetworkCapabilities().satisfiedByUids(netCap)); - - // Null uids satisfies everything. - netCap.setUids(null); - assertTrue(netCap2.satisfiedByUids(netCap)); - assertTrue(netCap.satisfiedByUids(netCap2)); - netCap2.setUids(null); - assertTrue(netCap2.satisfiedByUids(netCap)); - assertTrue(netCap.satisfiedByUids(netCap2)); - } - } - - @Test - public void testParcelNetworkCapabilities() { - final Set> uids = new ArraySet<>(); - uids.add(uidRange(50, 100)); - uids.add(uidRange(3000, 4000)); - final NetworkCapabilities netCap = new NetworkCapabilities() - .addCapability(NET_CAPABILITY_INTERNET) - .addCapability(NET_CAPABILITY_EIMS) - .addCapability(NET_CAPABILITY_NOT_METERED); - if (isAtLeastS()) { - netCap.setSubscriptionIds(Set.of(TEST_SUBID1, TEST_SUBID2)); - netCap.setUids(uids); - } - if (isAtLeastR()) { - netCap.setOwnerUid(123); - netCap.setAdministratorUids(new int[] {5, 11}); - } - assertParcelingIsLossless(netCap); - netCap.setSSID(TEST_SSID); - testParcelSane(netCap); - } - - @Test - public void testParcelNetworkCapabilitiesWithRequestorUidAndPackageName() { - final NetworkCapabilities netCap = new NetworkCapabilities() - .addCapability(NET_CAPABILITY_INTERNET) - .addCapability(NET_CAPABILITY_EIMS) - .addCapability(NET_CAPABILITY_NOT_METERED); - if (isAtLeastR()) { - netCap.setRequestorPackageName("com.android.test"); - netCap.setRequestorUid(9304); - } - assertParcelingIsLossless(netCap); - netCap.setSSID(TEST_SSID); - testParcelSane(netCap); - } - - private void testParcelSane(NetworkCapabilities cap) { - if (isAtLeastS()) { - assertParcelSane(cap, 16); - } else if (isAtLeastR()) { - assertParcelSane(cap, 15); - } else { - assertParcelSane(cap, 11); - } - } - - private static NetworkCapabilities createNetworkCapabilitiesWithTransportInfo() { - return new NetworkCapabilities() - .addCapability(NET_CAPABILITY_INTERNET) - .addCapability(NET_CAPABILITY_EIMS) - .addCapability(NET_CAPABILITY_NOT_METERED) - .setSSID(TEST_SSID) - .setTransportInfo(new TestTransportInfo()) - .setRequestorPackageName("com.android.test") - .setRequestorUid(9304); - } - - @Test - public void testNetworkCapabilitiesCopyWithNoRedactions() { - assumeTrue(isAtLeastS()); - - final NetworkCapabilities netCap = createNetworkCapabilitiesWithTransportInfo(); - final NetworkCapabilities netCapWithNoRedactions = - new NetworkCapabilities(netCap, NetworkCapabilities.REDACT_NONE); - TestTransportInfo testTransportInfo = - (TestTransportInfo) netCapWithNoRedactions.getTransportInfo(); - assertFalse(testTransportInfo.locationRedacted); - assertFalse(testTransportInfo.localMacAddressRedacted); - assertFalse(testTransportInfo.settingsRedacted); - } - - @Test - public void testNetworkCapabilitiesCopyWithoutLocationSensitiveFields() { - assumeTrue(isAtLeastS()); - - final NetworkCapabilities netCap = createNetworkCapabilitiesWithTransportInfo(); - final NetworkCapabilities netCapWithNoRedactions = - new NetworkCapabilities(netCap, REDACT_FOR_ACCESS_FINE_LOCATION); - TestTransportInfo testTransportInfo = - (TestTransportInfo) netCapWithNoRedactions.getTransportInfo(); - assertTrue(testTransportInfo.locationRedacted); - assertFalse(testTransportInfo.localMacAddressRedacted); - assertFalse(testTransportInfo.settingsRedacted); - } - - @Test - public void testOemPaid() { - NetworkCapabilities nc = new NetworkCapabilities(); - // By default OEM_PAID is neither in the required or forbidden lists and the network is not - // restricted. - if (isAtLeastS()) { - assertFalse(nc.hasForbiddenCapability(NET_CAPABILITY_OEM_PAID)); - } - assertFalse(nc.hasCapability(NET_CAPABILITY_OEM_PAID)); - nc.maybeMarkCapabilitiesRestricted(); - assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); - - // Adding OEM_PAID to capability list should make network restricted. - nc.addCapability(NET_CAPABILITY_OEM_PAID); - nc.addCapability(NET_CAPABILITY_INTERNET); // Combine with unrestricted capability. - nc.maybeMarkCapabilitiesRestricted(); - assertTrue(nc.hasCapability(NET_CAPABILITY_OEM_PAID)); - assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); - - // Now let's make request for OEM_PAID network. - NetworkCapabilities nr = new NetworkCapabilities(); - nr.addCapability(NET_CAPABILITY_OEM_PAID); - nr.maybeMarkCapabilitiesRestricted(); - assertTrue(nr.satisfiedByNetworkCapabilities(nc)); - - // Request fails for network with the default capabilities. - assertFalse(nr.satisfiedByNetworkCapabilities(new NetworkCapabilities())); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.R) - public void testOemPrivate() { - NetworkCapabilities nc = new NetworkCapabilities(); - // By default OEM_PRIVATE is neither in the required or forbidden lists and the network is - // not restricted. - assertFalse(nc.hasForbiddenCapability(NET_CAPABILITY_OEM_PRIVATE)); - assertFalse(nc.hasCapability(NET_CAPABILITY_OEM_PRIVATE)); - nc.maybeMarkCapabilitiesRestricted(); - assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); - - // Adding OEM_PRIVATE to capability list should make network restricted. - nc.addCapability(NET_CAPABILITY_OEM_PRIVATE); - nc.addCapability(NET_CAPABILITY_INTERNET); // Combine with unrestricted capability. - nc.maybeMarkCapabilitiesRestricted(); - assertTrue(nc.hasCapability(NET_CAPABILITY_OEM_PRIVATE)); - assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); - - // Now let's make request for OEM_PRIVATE network. - NetworkCapabilities nr = new NetworkCapabilities(); - nr.addCapability(NET_CAPABILITY_OEM_PRIVATE); - nr.maybeMarkCapabilitiesRestricted(); - assertTrue(nr.satisfiedByNetworkCapabilities(nc)); - - // Request fails for network with the default capabilities. - assertFalse(nr.satisfiedByNetworkCapabilities(new NetworkCapabilities())); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.R) - public void testForbiddenCapabilities() { - NetworkCapabilities network = new NetworkCapabilities(); - - NetworkCapabilities request = new NetworkCapabilities(); - assertTrue("Request: " + request + ", Network:" + network, - request.satisfiedByNetworkCapabilities(network)); - - // Requesting absence of capabilities that network doesn't have. Request should satisfy. - request.addForbiddenCapability(NET_CAPABILITY_WIFI_P2P); - request.addForbiddenCapability(NET_CAPABILITY_NOT_METERED); - assertTrue(request.satisfiedByNetworkCapabilities(network)); - assertArrayEquals(new int[]{NET_CAPABILITY_WIFI_P2P, - NET_CAPABILITY_NOT_METERED}, - request.getForbiddenCapabilities()); - - // This is a default capability, just want to make sure its there because we use it below. - assertTrue(network.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); - - // Verify that adding forbidden capability will effectively remove it from capability list. - request.addForbiddenCapability(NET_CAPABILITY_NOT_RESTRICTED); - assertTrue(request.hasForbiddenCapability(NET_CAPABILITY_NOT_RESTRICTED)); - assertFalse(request.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); - - // Now this request won't be satisfied because network contains NOT_RESTRICTED. - assertFalse(request.satisfiedByNetworkCapabilities(network)); - network.removeCapability(NET_CAPABILITY_NOT_RESTRICTED); - assertTrue(request.satisfiedByNetworkCapabilities(network)); - - // Verify that adding capability will effectively remove it from forbidden list - request.addCapability(NET_CAPABILITY_NOT_RESTRICTED); - assertTrue(request.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); - assertFalse(request.hasForbiddenCapability(NET_CAPABILITY_NOT_RESTRICTED)); - - assertFalse(request.satisfiedByNetworkCapabilities(network)); - network.addCapability(NET_CAPABILITY_NOT_RESTRICTED); - assertTrue(request.satisfiedByNetworkCapabilities(network)); - } - - @Test - public void testConnectivityManagedCapabilities() { - NetworkCapabilities nc = new NetworkCapabilities(); - assertFalse(nc.hasConnectivityManagedCapability()); - // Check every single system managed capability. - nc.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL); - assertTrue(nc.hasConnectivityManagedCapability()); - nc.removeCapability(NET_CAPABILITY_CAPTIVE_PORTAL); - nc.addCapability(NET_CAPABILITY_FOREGROUND); - assertTrue(nc.hasConnectivityManagedCapability()); - nc.removeCapability(NET_CAPABILITY_FOREGROUND); - nc.addCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY); - assertTrue(nc.hasConnectivityManagedCapability()); - nc.removeCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY); - nc.addCapability(NET_CAPABILITY_VALIDATED); - assertTrue(nc.hasConnectivityManagedCapability()); - } - - @Test - public void testEqualsNetCapabilities() { - NetworkCapabilities nc1 = new NetworkCapabilities(); - NetworkCapabilities nc2 = new NetworkCapabilities(); - assertTrue(nc1.equalsNetCapabilities(nc2)); - assertEquals(nc1, nc2); - - nc1.addCapability(NET_CAPABILITY_MMS); - assertFalse(nc1.equalsNetCapabilities(nc2)); - assertNotEquals(nc1, nc2); - nc2.addCapability(NET_CAPABILITY_MMS); - assertTrue(nc1.equalsNetCapabilities(nc2)); - assertEquals(nc1, nc2); - - if (isAtLeastS()) { - nc1.addForbiddenCapability(NET_CAPABILITY_INTERNET); - assertFalse(nc1.equalsNetCapabilities(nc2)); - nc2.addForbiddenCapability(NET_CAPABILITY_INTERNET); - assertTrue(nc1.equalsNetCapabilities(nc2)); - - // Remove a required capability doesn't affect forbidden capabilities. - // This is a behaviour change from R to S. - nc1.removeCapability(NET_CAPABILITY_INTERNET); - assertTrue(nc1.equalsNetCapabilities(nc2)); - - nc1.removeForbiddenCapability(NET_CAPABILITY_INTERNET); - assertFalse(nc1.equalsNetCapabilities(nc2)); - nc2.removeForbiddenCapability(NET_CAPABILITY_INTERNET); - assertTrue(nc1.equalsNetCapabilities(nc2)); - } - } - - @Test - public void testSSID() { - NetworkCapabilities nc1 = new NetworkCapabilities(); - NetworkCapabilities nc2 = new NetworkCapabilities(); - assertTrue(nc2.satisfiedBySSID(nc1)); - - nc1.setSSID(TEST_SSID); - assertTrue(nc2.satisfiedBySSID(nc1)); - nc2.setSSID("different " + TEST_SSID); - assertFalse(nc2.satisfiedBySSID(nc1)); - - assertTrue(nc1.satisfiedByImmutableNetworkCapabilities(nc2)); - assertFalse(nc1.satisfiedByNetworkCapabilities(nc2)); - } - - private ArraySet> uidRanges(int from, int to) { - final ArraySet> range = new ArraySet<>(1); - range.add(uidRange(from, to)); - return range; - } - - private Range uidRange(int from, int to) { - return new Range(from, to); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testSetAdministratorUids() { - NetworkCapabilities nc = - new NetworkCapabilities().setAdministratorUids(new int[] {2, 1, 3}); - - assertArrayEquals(new int[] {1, 2, 3}, nc.getAdministratorUids()); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testSetAdministratorUidsWithDuplicates() { - try { - new NetworkCapabilities().setAdministratorUids(new int[] {1, 1}); - fail("Expected IllegalArgumentException for duplicate uids"); - } catch (IllegalArgumentException expected) { - } - } - - @Test - public void testCombineCapabilities() { - NetworkCapabilities nc1 = new NetworkCapabilities(); - NetworkCapabilities nc2 = new NetworkCapabilities(); - - if (isAtLeastS()) { - nc1.addForbiddenCapability(NET_CAPABILITY_CAPTIVE_PORTAL); - } - nc1.addCapability(NET_CAPABILITY_NOT_ROAMING); - assertNotEquals(nc1, nc2); - nc2.combineCapabilities(nc1); - assertEquals(nc1, nc2); - assertTrue(nc2.hasCapability(NET_CAPABILITY_NOT_ROAMING)); - if (isAtLeastS()) { - assertTrue(nc2.hasForbiddenCapability(NET_CAPABILITY_CAPTIVE_PORTAL)); - } - - if (isAtLeastS()) { - // This will effectively move NOT_ROAMING capability from required to forbidden for nc1. - nc1.addForbiddenCapability(NET_CAPABILITY_NOT_ROAMING); - // It is not allowed to have the same capability in both wanted and forbidden list. - assertThrows(IllegalArgumentException.class, () -> nc2.combineCapabilities(nc1)); - // Remove forbidden capability to continue other tests. - nc1.removeForbiddenCapability(NET_CAPABILITY_NOT_ROAMING); - } - - nc1.setSSID(TEST_SSID); - nc2.combineCapabilities(nc1); - if (isAtLeastR()) { - assertTrue(TEST_SSID.equals(nc2.getSsid())); - } - - // Because they now have the same SSID, the following call should not throw - nc2.combineCapabilities(nc1); - - nc1.setSSID(DIFFERENT_TEST_SSID); - try { - nc2.combineCapabilities(nc1); - fail("Expected IllegalStateException: can't combine different SSIDs"); - } catch (IllegalStateException expected) {} - nc1.setSSID(TEST_SSID); - - if (isAtLeastS()) { - nc1.setUids(uidRanges(10, 13)); - assertNotEquals(nc1, nc2); - nc2.combineCapabilities(nc1); // Everything + 10~13 is still everything. - assertNotEquals(nc1, nc2); - nc1.combineCapabilities(nc2); // 10~13 + everything is everything. - assertEquals(nc1, nc2); - nc1.setUids(uidRanges(10, 13)); - nc2.setUids(uidRanges(20, 23)); - assertNotEquals(nc1, nc2); - nc1.combineCapabilities(nc2); - assertTrue(nc1.appliesToUid(12)); - assertFalse(nc2.appliesToUid(12)); - assertTrue(nc1.appliesToUid(22)); - assertTrue(nc2.appliesToUid(22)); - - // Verify the subscription id list can be combined only when they are equal. - nc1.setSubscriptionIds(Set.of(TEST_SUBID1, TEST_SUBID2)); - nc2.setSubscriptionIds(Set.of(TEST_SUBID2)); - assertThrows(IllegalStateException.class, () -> nc2.combineCapabilities(nc1)); - - nc2.setSubscriptionIds(Set.of()); - assertThrows(IllegalStateException.class, () -> nc2.combineCapabilities(nc1)); - - nc2.setSubscriptionIds(Set.of(TEST_SUBID2, TEST_SUBID1)); - nc2.combineCapabilities(nc1); - assertEquals(Set.of(TEST_SUBID2, TEST_SUBID1), nc2.getSubscriptionIds()); - } - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testCombineCapabilities_AdministratorUids() { - final NetworkCapabilities nc1 = new NetworkCapabilities(); - final NetworkCapabilities nc2 = new NetworkCapabilities(); - - final int[] adminUids = {3, 6, 12}; - nc1.setAdministratorUids(adminUids); - nc2.combineCapabilities(nc1); - assertTrue(nc2.equalsAdministratorUids(nc1)); - assertArrayEquals(nc2.getAdministratorUids(), adminUids); - - final int[] adminUidsOtherOrder = {3, 12, 6}; - nc1.setAdministratorUids(adminUidsOtherOrder); - assertTrue(nc2.equalsAdministratorUids(nc1)); - - final int[] adminUids2 = {11, 1, 12, 3, 6}; - nc1.setAdministratorUids(adminUids2); - assertFalse(nc2.equalsAdministratorUids(nc1)); - assertFalse(Arrays.equals(nc2.getAdministratorUids(), adminUids2)); - try { - nc2.combineCapabilities(nc1); - fail("Shouldn't be able to combine different lists of admin UIDs"); - } catch (IllegalStateException expected) { } - } - - @Test - public void testSetCapabilities() { - final int[] REQUIRED_CAPABILITIES = new int[] { - NET_CAPABILITY_INTERNET, NET_CAPABILITY_NOT_VPN }; - - NetworkCapabilities nc1 = new NetworkCapabilities(); - NetworkCapabilities nc2 = new NetworkCapabilities(); - - nc1.setCapabilities(REQUIRED_CAPABILITIES); - assertArrayEquals(REQUIRED_CAPABILITIES, nc1.getCapabilities()); - - // Verify that setting and adding capabilities leads to the same object state. - nc2.clearAll(); - for (int cap : REQUIRED_CAPABILITIES) { - nc2.addCapability(cap); - } - assertEquals(nc1, nc2); - - if (isAtLeastS()) { - final int[] forbiddenCapabilities = new int[]{ - NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_NOT_RESTRICTED }; - - nc1.setCapabilities(REQUIRED_CAPABILITIES, forbiddenCapabilities); - assertArrayEquals(REQUIRED_CAPABILITIES, nc1.getCapabilities()); - assertArrayEquals(forbiddenCapabilities, nc1.getForbiddenCapabilities()); - - nc2.clearAll(); - for (int cap : REQUIRED_CAPABILITIES) { - nc2.addCapability(cap); - } - for (int cap : forbiddenCapabilities) { - nc2.addForbiddenCapability(cap); - } - assertEquals(nc1, nc2); - } - } - - @Test - public void testSetNetworkSpecifierOnMultiTransportNc() { - // Sequence 1: Transport + Transport + NetworkSpecifier - NetworkCapabilities nc1 = new NetworkCapabilities(); - nc1.addTransportType(TRANSPORT_CELLULAR).addTransportType(TRANSPORT_WIFI); - try { - nc1.setNetworkSpecifier(CompatUtil.makeEthernetNetworkSpecifier("eth0")); - fail("Cannot set NetworkSpecifier on a NetworkCapability with multiple transports!"); - } catch (IllegalStateException expected) { - // empty - } - - // Sequence 2: Transport + NetworkSpecifier + Transport - NetworkCapabilities nc2 = new NetworkCapabilities(); - nc2.addTransportType(TRANSPORT_CELLULAR).setNetworkSpecifier( - CompatUtil.makeEthernetNetworkSpecifier("testtap3")); - try { - nc2.addTransportType(TRANSPORT_WIFI); - fail("Cannot set a second TransportType of a network which has a NetworkSpecifier!"); - } catch (IllegalStateException expected) { - // empty - } - } - - @Test - public void testSetTransportInfoOnMultiTransportNc() { - // Sequence 1: Transport + Transport + TransportInfo - NetworkCapabilities nc1 = new NetworkCapabilities(); - nc1.addTransportType(TRANSPORT_CELLULAR).addTransportType(TRANSPORT_WIFI) - .setTransportInfo(new TestTransportInfo()); - - // Sequence 2: Transport + NetworkSpecifier + Transport - NetworkCapabilities nc2 = new NetworkCapabilities(); - nc2.addTransportType(TRANSPORT_CELLULAR).setTransportInfo(new TestTransportInfo()) - .addTransportType(TRANSPORT_WIFI); - } - - @Test - public void testCombineTransportInfo() { - NetworkCapabilities nc1 = new NetworkCapabilities(); - nc1.setTransportInfo(new TestTransportInfo()); - - NetworkCapabilities nc2 = new NetworkCapabilities(); - // new TransportInfo so that object is not #equals to nc1's TransportInfo (that's where - // combine fails) - nc2.setTransportInfo(new TestTransportInfo()); - - try { - nc1.combineCapabilities(nc2); - fail("Should not be able to combine NetworkCabilities which contain TransportInfos"); - } catch (IllegalStateException expected) { - // empty - } - - // verify that can combine with identical TransportInfo objects - NetworkCapabilities nc3 = new NetworkCapabilities(); - nc3.setTransportInfo(nc1.getTransportInfo()); - nc1.combineCapabilities(nc3); - } - - @Test - public void testSet() { - NetworkCapabilities nc1 = new NetworkCapabilities(); - NetworkCapabilities nc2 = new NetworkCapabilities(); - - if (isAtLeastS()) { - nc1.addForbiddenCapability(NET_CAPABILITY_CAPTIVE_PORTAL); - } - nc1.addCapability(NET_CAPABILITY_NOT_ROAMING); - assertNotEquals(nc1, nc2); - nc2.set(nc1); - assertEquals(nc1, nc2); - assertTrue(nc2.hasCapability(NET_CAPABILITY_NOT_ROAMING)); - if (isAtLeastS()) { - assertTrue(nc2.hasForbiddenCapability(NET_CAPABILITY_CAPTIVE_PORTAL)); - } - - if (isAtLeastS()) { - // This will effectively move NOT_ROAMING capability from required to forbidden for nc1. - nc1.addForbiddenCapability(NET_CAPABILITY_NOT_ROAMING); - } - nc1.setSSID(TEST_SSID); - nc2.set(nc1); - assertEquals(nc1, nc2); - if (isAtLeastS()) { - // Contrary to combineCapabilities, set() will have removed the NOT_ROAMING capability - // from nc2. - assertFalse(nc2.hasCapability(NET_CAPABILITY_NOT_ROAMING)); - assertTrue(nc2.hasForbiddenCapability(NET_CAPABILITY_NOT_ROAMING)); - } - - if (isAtLeastR()) { - assertTrue(TEST_SSID.equals(nc2.getSsid())); - } - - nc1.setSSID(DIFFERENT_TEST_SSID); - nc2.set(nc1); - assertEquals(nc1, nc2); - if (isAtLeastR()) { - assertTrue(DIFFERENT_TEST_SSID.equals(nc2.getSsid())); - } - if (isAtLeastS()) { - nc1.setUids(uidRanges(10, 13)); - } else { - nc1.setUids(null); - } - nc2.set(nc1); // Overwrites, as opposed to combineCapabilities - assertEquals(nc1, nc2); - - if (isAtLeastS()) { - assertThrows(NullPointerException.class, () -> nc1.setSubscriptionIds(null)); - nc1.setSubscriptionIds(Set.of()); - nc2.set(nc1); - assertEquals(nc1, nc2); - - nc1.setSubscriptionIds(Set.of(TEST_SUBID1)); - nc2.set(nc1); - assertEquals(nc1, nc2); - - nc2.setSubscriptionIds(Set.of(TEST_SUBID2, TEST_SUBID1)); - nc2.set(nc1); - assertEquals(nc1, nc2); - - nc2.setSubscriptionIds(Set.of(TEST_SUBID3, TEST_SUBID2)); - assertNotEquals(nc1, nc2); - } - } - - @Test - public void testGetTransportTypes() { - final NetworkCapabilities nc = new NetworkCapabilities(); - nc.addTransportType(TRANSPORT_CELLULAR); - nc.addTransportType(TRANSPORT_WIFI); - nc.addTransportType(TRANSPORT_VPN); - nc.addTransportType(TRANSPORT_TEST); - - final int[] transportTypes = nc.getTransportTypes(); - assertEquals(4, transportTypes.length); - assertEquals(TRANSPORT_CELLULAR, transportTypes[0]); - assertEquals(TRANSPORT_WIFI, transportTypes[1]); - assertEquals(TRANSPORT_VPN, transportTypes[2]); - assertEquals(TRANSPORT_TEST, transportTypes[3]); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testTelephonyNetworkSpecifier() { - final TelephonyNetworkSpecifier specifier = new TelephonyNetworkSpecifier(1); - final NetworkCapabilities nc1 = new NetworkCapabilities.Builder() - .addTransportType(TRANSPORT_WIFI) - .setNetworkSpecifier(specifier) - .build(); - assertEquals(specifier, nc1.getNetworkSpecifier()); - try { - final NetworkCapabilities nc2 = new NetworkCapabilities.Builder() - .setNetworkSpecifier(specifier) - .build(); - fail("Must have a single transport type. Without transport type or multiple transport" - + " types is invalid."); - } catch (IllegalStateException expected) { } - } - - @Test - public void testWifiAwareNetworkSpecifier() { - final NetworkCapabilities nc = new NetworkCapabilities() - .addTransportType(TRANSPORT_WIFI_AWARE); - // If NetworkSpecifier is not set, the default value is null. - assertNull(nc.getNetworkSpecifier()); - final WifiAwareNetworkSpecifier specifier = new WifiAwareNetworkSpecifier.Builder( - mDiscoverySession, mPeerHandle).build(); - nc.setNetworkSpecifier(specifier); - assertEquals(specifier, nc.getNetworkSpecifier()); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testAdministratorUidsAndOwnerUid() { - // Test default owner uid. - // If the owner uid is not set, the default value should be Process.INVALID_UID. - final NetworkCapabilities nc1 = new NetworkCapabilities.Builder().build(); - assertEquals(INVALID_UID, nc1.getOwnerUid()); - // Test setAdministratorUids and getAdministratorUids. - final int[] administratorUids = {1001, 10001}; - final NetworkCapabilities nc2 = new NetworkCapabilities.Builder() - .setAdministratorUids(administratorUids) - .build(); - assertTrue(Arrays.equals(administratorUids, nc2.getAdministratorUids())); - // Test setOwnerUid and getOwnerUid. - // The owner UID must be included in administrator UIDs, or throw IllegalStateException. - try { - final NetworkCapabilities nc3 = new NetworkCapabilities.Builder() - .setOwnerUid(1001) - .build(); - fail("The owner UID must be included in administrator UIDs."); - } catch (IllegalStateException expected) { } - final NetworkCapabilities nc4 = new NetworkCapabilities.Builder() - .setAdministratorUids(administratorUids) - .setOwnerUid(1001) - .build(); - assertEquals(1001, nc4.getOwnerUid()); - try { - final NetworkCapabilities nc5 = new NetworkCapabilities.Builder() - .setAdministratorUids(null) - .build(); - fail("Should not set null into setAdministratorUids"); - } catch (NullPointerException expected) { } - } - - private static NetworkCapabilities capsWithSubIds(Integer ... subIds) { - // Since the NetworkRequest would put NOT_VCN_MANAGED capabilities in general, for - // every NetworkCapabilities that simulates networks needs to add it too in order to - // satisfy these requests. - final NetworkCapabilities nc = new NetworkCapabilities.Builder() - .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) - .setSubscriptionIds(new ArraySet<>(subIds)).build(); - assertEquals(new ArraySet<>(subIds), nc.getSubscriptionIds()); - return nc; - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.R) - public void testSubIds() throws Exception { - final NetworkCapabilities ncWithoutId = capsWithSubIds(); - final NetworkCapabilities ncWithId = capsWithSubIds(TEST_SUBID1); - final NetworkCapabilities ncWithOtherIds = capsWithSubIds(TEST_SUBID1, TEST_SUBID3); - final NetworkCapabilities ncWithoutRequestedIds = capsWithSubIds(TEST_SUBID3); - - final NetworkRequest requestWithoutId = new NetworkRequest.Builder().build(); - assertEmpty(requestWithoutId.networkCapabilities.getSubscriptionIds()); - final NetworkRequest requestWithIds = new NetworkRequest.Builder() - .setSubscriptionIds(Set.of(TEST_SUBID1, TEST_SUBID2)).build(); - assertEquals(Set.of(TEST_SUBID1, TEST_SUBID2), - requestWithIds.networkCapabilities.getSubscriptionIds()); - - assertFalse(requestWithIds.canBeSatisfiedBy(ncWithoutId)); - assertTrue(requestWithIds.canBeSatisfiedBy(ncWithOtherIds)); - assertFalse(requestWithIds.canBeSatisfiedBy(ncWithoutRequestedIds)); - assertTrue(requestWithIds.canBeSatisfiedBy(ncWithId)); - assertTrue(requestWithoutId.canBeSatisfiedBy(ncWithoutId)); - assertTrue(requestWithoutId.canBeSatisfiedBy(ncWithId)); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.R) - public void testEqualsSubIds() throws Exception { - assertEquals(capsWithSubIds(), capsWithSubIds()); - assertNotEquals(capsWithSubIds(), capsWithSubIds(TEST_SUBID1)); - assertEquals(capsWithSubIds(TEST_SUBID1), capsWithSubIds(TEST_SUBID1)); - assertNotEquals(capsWithSubIds(TEST_SUBID1), capsWithSubIds(TEST_SUBID2)); - assertNotEquals(capsWithSubIds(TEST_SUBID1), capsWithSubIds(TEST_SUBID2, TEST_SUBID1)); - assertEquals(capsWithSubIds(TEST_SUBID1, TEST_SUBID2), - capsWithSubIds(TEST_SUBID2, TEST_SUBID1)); - } - - @Test - public void testLinkBandwidthKbps() { - final NetworkCapabilities nc = new NetworkCapabilities(); - // The default value of LinkDown/UpstreamBandwidthKbps should be LINK_BANDWIDTH_UNSPECIFIED. - assertEquals(LINK_BANDWIDTH_UNSPECIFIED, nc.getLinkDownstreamBandwidthKbps()); - assertEquals(LINK_BANDWIDTH_UNSPECIFIED, nc.getLinkUpstreamBandwidthKbps()); - nc.setLinkDownstreamBandwidthKbps(512); - nc.setLinkUpstreamBandwidthKbps(128); - assertEquals(512, nc.getLinkDownstreamBandwidthKbps()); - assertNotEquals(128, nc.getLinkDownstreamBandwidthKbps()); - assertEquals(128, nc.getLinkUpstreamBandwidthKbps()); - assertNotEquals(512, nc.getLinkUpstreamBandwidthKbps()); - } - - private int getMaxTransport() { - if (!isAtLeastS() && MAX_TRANSPORT == TRANSPORT_USB) return MAX_TRANSPORT - 1; - return MAX_TRANSPORT; - } - - @Test - public void testSignalStrength() { - final NetworkCapabilities nc = new NetworkCapabilities(); - // The default value of signal strength should be SIGNAL_STRENGTH_UNSPECIFIED. - assertEquals(SIGNAL_STRENGTH_UNSPECIFIED, nc.getSignalStrength()); - nc.setSignalStrength(-80); - assertEquals(-80, nc.getSignalStrength()); - assertNotEquals(-50, nc.getSignalStrength()); - } - - private void assertNoTransport(NetworkCapabilities nc) { - for (int i = MIN_TRANSPORT; i <= getMaxTransport(); i++) { - assertFalse(nc.hasTransport(i)); - } - } - - // Checks that all transport types from MIN_TRANSPORT to maxTransportType are set and all - // transport types from maxTransportType + 1 to MAX_TRANSPORT are not set when positiveSequence - // is true. If positiveSequence is false, then the check sequence is opposite. - private void checkCurrentTransportTypes(NetworkCapabilities nc, int maxTransportType, - boolean positiveSequence) { - for (int i = MIN_TRANSPORT; i <= maxTransportType; i++) { - if (positiveSequence) { - assertTrue(nc.hasTransport(i)); - } else { - assertFalse(nc.hasTransport(i)); - } - } - for (int i = getMaxTransport(); i > maxTransportType; i--) { - if (positiveSequence) { - assertFalse(nc.hasTransport(i)); - } else { - assertTrue(nc.hasTransport(i)); - } - } - } - - @Test - public void testMultipleTransportTypes() { - final NetworkCapabilities nc = new NetworkCapabilities(); - assertNoTransport(nc); - // Test adding multiple transport types. - for (int i = MIN_TRANSPORT; i <= getMaxTransport(); i++) { - nc.addTransportType(i); - checkCurrentTransportTypes(nc, i, true /* positiveSequence */); - } - // Test removing multiple transport types. - for (int i = MIN_TRANSPORT; i <= getMaxTransport(); i++) { - nc.removeTransportType(i); - checkCurrentTransportTypes(nc, i, false /* positiveSequence */); - } - assertNoTransport(nc); - nc.addTransportType(TRANSPORT_WIFI); - assertTrue(nc.hasTransport(TRANSPORT_WIFI)); - assertFalse(nc.hasTransport(TRANSPORT_VPN)); - nc.addTransportType(TRANSPORT_VPN); - assertTrue(nc.hasTransport(TRANSPORT_WIFI)); - assertTrue(nc.hasTransport(TRANSPORT_VPN)); - nc.removeTransportType(TRANSPORT_WIFI); - assertFalse(nc.hasTransport(TRANSPORT_WIFI)); - assertTrue(nc.hasTransport(TRANSPORT_VPN)); - nc.removeTransportType(TRANSPORT_VPN); - assertFalse(nc.hasTransport(TRANSPORT_WIFI)); - assertFalse(nc.hasTransport(TRANSPORT_VPN)); - assertNoTransport(nc); - } - - @Test - public void testAddAndRemoveTransportType() { - final NetworkCapabilities nc = new NetworkCapabilities(); - try { - nc.addTransportType(-1); - fail("Should not set invalid transport type into addTransportType"); - } catch (IllegalArgumentException expected) { } - try { - nc.removeTransportType(-1); - fail("Should not set invalid transport type into removeTransportType"); - } catch (IllegalArgumentException e) { } - } - - /** - * Test TransportInfo to verify redaction mechanism. - */ - private static class TestTransportInfo implements TransportInfo { - public final boolean locationRedacted; - public final boolean localMacAddressRedacted; - public final boolean settingsRedacted; - - TestTransportInfo() { - locationRedacted = false; - localMacAddressRedacted = false; - settingsRedacted = false; - } - - TestTransportInfo(boolean locationRedacted, - boolean localMacAddressRedacted, - boolean settingsRedacted) { - this.locationRedacted = locationRedacted; - this.localMacAddressRedacted = - localMacAddressRedacted; - this.settingsRedacted = settingsRedacted; - } - - @Override - public TransportInfo makeCopy(@NetworkCapabilities.RedactionType long redactions) { - return new TestTransportInfo( - (redactions & NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION) != 0, - (redactions & REDACT_FOR_LOCAL_MAC_ADDRESS) != 0, - (redactions & REDACT_FOR_NETWORK_SETTINGS) != 0 - ); - } - - @Override - public @NetworkCapabilities.RedactionType long getApplicableRedactions() { - return REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS - | REDACT_FOR_NETWORK_SETTINGS; - } - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testBuilder() { - final int ownerUid = 1001; - final int signalStrength = -80; - final int requestUid = 10100; - final int[] administratorUids = {ownerUid, 10001}; - final TelephonyNetworkSpecifier specifier = new TelephonyNetworkSpecifier(1); - final TransportInfo transportInfo = new TransportInfo() {}; - final String ssid = "TEST_SSID"; - final String packageName = "com.google.test.networkcapabilities"; - final NetworkCapabilities nc = new NetworkCapabilities.Builder() - .addTransportType(TRANSPORT_WIFI) - .addTransportType(TRANSPORT_CELLULAR) - .removeTransportType(TRANSPORT_CELLULAR) - .addCapability(NET_CAPABILITY_EIMS) - .addCapability(NET_CAPABILITY_CBS) - .removeCapability(NET_CAPABILITY_CBS) - .setAdministratorUids(administratorUids) - .setOwnerUid(ownerUid) - .setLinkDownstreamBandwidthKbps(512) - .setLinkUpstreamBandwidthKbps(128) - .setNetworkSpecifier(specifier) - .setTransportInfo(transportInfo) - .setSignalStrength(signalStrength) - .setSsid(ssid) - .setRequestorUid(requestUid) - .setRequestorPackageName(packageName) - .build(); - assertEquals(1, nc.getTransportTypes().length); - assertEquals(TRANSPORT_WIFI, nc.getTransportTypes()[0]); - assertTrue(nc.hasCapability(NET_CAPABILITY_EIMS)); - assertFalse(nc.hasCapability(NET_CAPABILITY_CBS)); - assertTrue(Arrays.equals(administratorUids, nc.getAdministratorUids())); - assertEquals(ownerUid, nc.getOwnerUid()); - assertEquals(512, nc.getLinkDownstreamBandwidthKbps()); - assertNotEquals(128, nc.getLinkDownstreamBandwidthKbps()); - assertEquals(128, nc.getLinkUpstreamBandwidthKbps()); - assertNotEquals(512, nc.getLinkUpstreamBandwidthKbps()); - assertEquals(specifier, nc.getNetworkSpecifier()); - assertEquals(transportInfo, nc.getTransportInfo()); - assertEquals(signalStrength, nc.getSignalStrength()); - assertNotEquals(-50, nc.getSignalStrength()); - assertEquals(ssid, nc.getSsid()); - assertEquals(requestUid, nc.getRequestorUid()); - assertEquals(packageName, nc.getRequestorPackageName()); - // Cannot assign null into NetworkCapabilities.Builder - try { - final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder(null); - fail("Should not set null into NetworkCapabilities.Builder"); - } catch (NullPointerException expected) { } - assertEquals(nc, new NetworkCapabilities.Builder(nc).build()); - - if (isAtLeastS()) { - final NetworkCapabilities nc2 = new NetworkCapabilities.Builder() - .setSubscriptionIds(Set.of(TEST_SUBID1)).build(); - assertEquals(Set.of(TEST_SUBID1), nc2.getSubscriptionIds()); - } - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.R) - public void testBuilderWithoutDefaultCap() { - final NetworkCapabilities nc = - NetworkCapabilities.Builder.withoutDefaultCapabilities().build(); - assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); - assertFalse(nc.hasCapability(NET_CAPABILITY_TRUSTED)); - assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_VPN)); - // Ensure test case fails if new net cap is added into default cap but no update here. - assertEquals(0, nc.getCapabilities().length); - } -} diff --git a/packages/Connectivity/tests/common/java/android/net/NetworkProviderTest.kt b/packages/Connectivity/tests/common/java/android/net/NetworkProviderTest.kt deleted file mode 100644 index 7424157bea74e..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/NetworkProviderTest.kt +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net - -import android.app.Instrumentation -import android.content.Context -import android.net.NetworkCapabilities.TRANSPORT_TEST -import android.net.NetworkProviderTest.TestNetworkCallback.CallbackEntry.OnUnavailable -import android.net.NetworkProviderTest.TestNetworkProvider.CallbackEntry.OnNetworkRequestWithdrawn -import android.net.NetworkProviderTest.TestNetworkProvider.CallbackEntry.OnNetworkRequested -import android.os.Build -import android.os.HandlerThread -import android.os.Looper -import androidx.test.InstrumentationRegistry -import com.android.net.module.util.ArrayTrackRecord -import com.android.testutils.CompatUtil -import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo -import com.android.testutils.DevSdkIgnoreRunner -import com.android.testutils.isDevSdkInRange -import org.junit.After -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.Mockito.doReturn -import org.mockito.Mockito.mock -import org.mockito.Mockito.verifyNoMoreInteractions -import java.util.UUID -import kotlin.test.assertEquals -import kotlin.test.assertNotEquals - -private const val DEFAULT_TIMEOUT_MS = 5000L -private val instrumentation: Instrumentation - get() = InstrumentationRegistry.getInstrumentation() -private val context: Context get() = InstrumentationRegistry.getContext() -private val PROVIDER_NAME = "NetworkProviderTest" - -@RunWith(DevSdkIgnoreRunner::class) -@IgnoreUpTo(Build.VERSION_CODES.Q) -class NetworkProviderTest { - private val mCm = context.getSystemService(ConnectivityManager::class.java) - private val mHandlerThread = HandlerThread("${javaClass.simpleName} handler thread") - - @Before - fun setUp() { - instrumentation.getUiAutomation().adoptShellPermissionIdentity() - mHandlerThread.start() - } - - @After - fun tearDown() { - mHandlerThread.quitSafely() - instrumentation.getUiAutomation().dropShellPermissionIdentity() - } - - private class TestNetworkProvider(context: Context, looper: Looper) : - NetworkProvider(context, looper, PROVIDER_NAME) { - private val seenEvents = ArrayTrackRecord().newReadHead() - - sealed class CallbackEntry { - data class OnNetworkRequested( - val request: NetworkRequest, - val score: Int, - val id: Int - ) : CallbackEntry() - data class OnNetworkRequestWithdrawn(val request: NetworkRequest) : CallbackEntry() - } - - override fun onNetworkRequested(request: NetworkRequest, score: Int, id: Int) { - seenEvents.add(OnNetworkRequested(request, score, id)) - } - - override fun onNetworkRequestWithdrawn(request: NetworkRequest) { - seenEvents.add(OnNetworkRequestWithdrawn(request)) - } - - inline fun expectCallback( - crossinline predicate: (T) -> Boolean - ) = seenEvents.poll(DEFAULT_TIMEOUT_MS) { it is T && predicate(it) } - } - - private fun createNetworkProvider(ctx: Context = context): TestNetworkProvider { - return TestNetworkProvider(ctx, mHandlerThread.looper) - } - - @Test - fun testOnNetworkRequested() { - val provider = createNetworkProvider() - assertEquals(provider.getProviderId(), NetworkProvider.ID_NONE) - mCm.registerNetworkProvider(provider) - assertNotEquals(provider.getProviderId(), NetworkProvider.ID_NONE) - - val specifier = CompatUtil.makeTestNetworkSpecifier( - UUID.randomUUID().toString()) - val nr: NetworkRequest = NetworkRequest.Builder() - .addTransportType(TRANSPORT_TEST) - .setNetworkSpecifier(specifier) - .build() - val cb = ConnectivityManager.NetworkCallback() - mCm.requestNetwork(nr, cb) - provider.expectCallback() { callback -> - callback.request.getNetworkSpecifier() == specifier && - callback.request.hasTransport(TRANSPORT_TEST) - } - - val initialScore = 40 - val updatedScore = 60 - val nc = NetworkCapabilities().apply { - addTransportType(NetworkCapabilities.TRANSPORT_TEST) - removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) - removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED) - addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING) - addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) - setNetworkSpecifier(specifier) - } - val lp = LinkProperties() - val config = NetworkAgentConfig.Builder().build() - val agent = object : NetworkAgent(context, mHandlerThread.looper, "TestAgent", nc, lp, - initialScore, config, provider) {} - - provider.expectCallback() { callback -> - callback.request.getNetworkSpecifier() == specifier && - callback.score == initialScore && - callback.id == agent.providerId - } - - agent.sendNetworkScore(updatedScore) - provider.expectCallback() { callback -> - callback.request.getNetworkSpecifier() == specifier && - callback.score == updatedScore && - callback.id == agent.providerId - } - - mCm.unregisterNetworkCallback(cb) - provider.expectCallback() { callback -> - callback.request.getNetworkSpecifier() == specifier && - callback.request.hasTransport(TRANSPORT_TEST) - } - mCm.unregisterNetworkProvider(provider) - // Provider id should be ID_NONE after unregister network provider - assertEquals(provider.getProviderId(), NetworkProvider.ID_NONE) - // unregisterNetworkProvider should not crash even if it's called on an - // already unregistered provider. - mCm.unregisterNetworkProvider(provider) - } - - private class TestNetworkCallback : ConnectivityManager.NetworkCallback() { - private val seenEvents = ArrayTrackRecord().newReadHead() - sealed class CallbackEntry { - object OnUnavailable : CallbackEntry() - } - - override fun onUnavailable() { - seenEvents.add(OnUnavailable) - } - - inline fun expectCallback( - crossinline predicate: (T) -> Boolean - ) = seenEvents.poll(DEFAULT_TIMEOUT_MS) { it is T && predicate(it) } - } - - @Test - fun testDeclareNetworkRequestUnfulfillable() { - val mockContext = mock(Context::class.java) - doReturn(mCm).`when`(mockContext).getSystemService(Context.CONNECTIVITY_SERVICE) - val provider = createNetworkProvider(mockContext) - // ConnectivityManager not required at creation time after R - if (!isDevSdkInRange(0, Build.VERSION_CODES.R)) { - verifyNoMoreInteractions(mockContext) - } - - mCm.registerNetworkProvider(provider) - - val specifier = CompatUtil.makeTestNetworkSpecifier( - UUID.randomUUID().toString()) - val nr: NetworkRequest = NetworkRequest.Builder() - .addTransportType(TRANSPORT_TEST) - .setNetworkSpecifier(specifier) - .build() - - val cb = TestNetworkCallback() - mCm.requestNetwork(nr, cb) - provider.declareNetworkRequestUnfulfillable(nr) - cb.expectCallback() { nr.getNetworkSpecifier() == specifier } - mCm.unregisterNetworkProvider(provider) - } -} diff --git a/packages/Connectivity/tests/common/java/android/net/NetworkSpecifierTest.kt b/packages/Connectivity/tests/common/java/android/net/NetworkSpecifierTest.kt deleted file mode 100644 index f3409f53596f8..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/NetworkSpecifierTest.kt +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.net - -import android.os.Build -import androidx.test.filters.SmallTest -import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo -import com.android.testutils.DevSdkIgnoreRunner -import kotlin.test.assertTrue -import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertNotEquals -import org.junit.Test -import org.junit.runner.RunWith - -@SmallTest -@RunWith(DevSdkIgnoreRunner::class) -@IgnoreUpTo(Build.VERSION_CODES.Q) -class NetworkSpecifierTest { - private class TestNetworkSpecifier( - val intData: Int = 123, - val stringData: String = "init" - ) : NetworkSpecifier() { - override fun canBeSatisfiedBy(other: NetworkSpecifier?): Boolean = - other != null && - other is TestNetworkSpecifier && - other.intData >= intData && - stringData.equals(other.stringData) - - override fun redact(): NetworkSpecifier = TestNetworkSpecifier(intData, "redact") - } - - @Test - fun testRedact() { - val ns: TestNetworkSpecifier = TestNetworkSpecifier() - val redactNs = ns.redact() - assertTrue(redactNs is TestNetworkSpecifier) - assertEquals(ns.intData, redactNs.intData) - assertNotEquals(ns.stringData, redactNs.stringData) - assertTrue("redact".equals(redactNs.stringData)) - } - - @Test - fun testcanBeSatisfiedBy() { - val target: TestNetworkSpecifier = TestNetworkSpecifier() - assertFalse(target.canBeSatisfiedBy(null)) - assertTrue(target.canBeSatisfiedBy(TestNetworkSpecifier())) - val otherNs = TelephonyNetworkSpecifier.Builder().setSubscriptionId(123).build() - assertFalse(target.canBeSatisfiedBy(otherNs)) - assertTrue(target.canBeSatisfiedBy(TestNetworkSpecifier(intData = 999))) - assertFalse(target.canBeSatisfiedBy(TestNetworkSpecifier(intData = 1))) - assertFalse(target.canBeSatisfiedBy(TestNetworkSpecifier(stringData = "diff"))) - } -} \ No newline at end of file diff --git a/packages/Connectivity/tests/common/java/android/net/NetworkStackTest.java b/packages/Connectivity/tests/common/java/android/net/NetworkStackTest.java deleted file mode 100644 index f8f9c72374ad3..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/NetworkStackTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.net; - -import static org.junit.Assert.assertEquals; - -import android.os.Build; -import android.os.IBinder; - -import androidx.test.runner.AndroidJUnit4; - -import com.android.testutils.DevSdkIgnoreRule; -import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -@RunWith(AndroidJUnit4.class) -public class NetworkStackTest { - @Rule - public DevSdkIgnoreRule mDevSdkIgnoreRule = new DevSdkIgnoreRule(); - - @Mock private IBinder mConnectorBinder; - - @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testGetService() { - NetworkStack.setServiceForTest(mConnectorBinder); - assertEquals(NetworkStack.getService(), mConnectorBinder); - } -} diff --git a/packages/Connectivity/tests/common/java/android/net/NetworkStateSnapshotTest.kt b/packages/Connectivity/tests/common/java/android/net/NetworkStateSnapshotTest.kt deleted file mode 100644 index 0ca4d9551f393..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/NetworkStateSnapshotTest.kt +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net - -import android.net.ConnectivityManager.TYPE_NONE -import android.net.ConnectivityManager.TYPE_WIFI -import android.net.InetAddresses.parseNumericAddress -import android.net.NetworkCapabilities.TRANSPORT_WIFI -import android.os.Build -import androidx.test.filters.SmallTest -import com.android.testutils.DevSdkIgnoreRule -import com.android.testutils.DevSdkIgnoreRunner -import com.android.testutils.assertParcelSane -import org.junit.Test -import org.junit.runner.RunWith -import java.net.Inet4Address -import java.net.Inet6Address - -private const val TEST_IMSI = "imsi1" -private const val TEST_SSID = "SSID1" -private const val TEST_NETID = 123 - -private val TEST_IPV4_GATEWAY = parseNumericAddress("192.168.222.3") as Inet4Address -private val TEST_IPV6_GATEWAY = parseNumericAddress("2001:db8::1") as Inet6Address -private val TEST_IPV4_LINKADDR = LinkAddress("192.168.222.123/24") -private val TEST_IPV6_LINKADDR = LinkAddress("2001:db8::123/64") -private val TEST_IFACE = "fake0" -private val TEST_LINK_PROPERTIES = LinkProperties().apply { - interfaceName = TEST_IFACE - addLinkAddress(TEST_IPV4_LINKADDR) - addLinkAddress(TEST_IPV6_LINKADDR) - - // Add default routes - addRoute(RouteInfo(IpPrefix(parseNumericAddress("0.0.0.0"), 0), TEST_IPV4_GATEWAY)) - addRoute(RouteInfo(IpPrefix(parseNumericAddress("::"), 0), TEST_IPV6_GATEWAY)) -} - -private val TEST_CAPABILITIES = NetworkCapabilities().apply { - addTransportType(TRANSPORT_WIFI) - setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, false) - setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true) - setSSID(TEST_SSID) -} - -@SmallTest -@RunWith(DevSdkIgnoreRunner::class) -@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R) -class NetworkStateSnapshotTest { - - @Test - fun testParcelUnparcel() { - val emptySnapshot = NetworkStateSnapshot(Network(TEST_NETID), NetworkCapabilities(), - LinkProperties(), null, TYPE_NONE) - val snapshot = NetworkStateSnapshot( - Network(TEST_NETID), TEST_CAPABILITIES, TEST_LINK_PROPERTIES, TEST_IMSI, TYPE_WIFI) - assertParcelSane(emptySnapshot, 5) - assertParcelSane(snapshot, 5) - } -} diff --git a/packages/Connectivity/tests/common/java/android/net/NetworkTest.java b/packages/Connectivity/tests/common/java/android/net/NetworkTest.java deleted file mode 100644 index 7423c733c6ebd..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/NetworkTest.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import android.os.Build; -import android.platform.test.annotations.AppModeFull; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.testutils.DevSdkIgnoreRule; -import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter; -import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.io.File; -import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.net.DatagramSocket; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.SocketException; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class NetworkTest { - final Network mNetwork = new Network(99); - - @Rule - public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule(); - - @Test - public void testBindSocketOfInvalidFdThrows() throws Exception { - - final FileDescriptor fd = new FileDescriptor(); - assertFalse(fd.valid()); - - try { - mNetwork.bindSocket(fd); - fail("SocketException not thrown"); - } catch (SocketException expected) {} - } - - @Test - public void testBindSocketOfNonSocketFdThrows() throws Exception { - final File devNull = new File("/dev/null"); - assertTrue(devNull.canRead()); - - final FileInputStream fis = new FileInputStream(devNull); - assertTrue(null != fis.getFD()); - assertTrue(fis.getFD().valid()); - - try { - mNetwork.bindSocket(fis.getFD()); - fail("SocketException not thrown"); - } catch (SocketException expected) {} - } - - @Test - @AppModeFull(reason = "Socket cannot bind in instant app mode") - public void testBindSocketOfConnectedDatagramSocketThrows() throws Exception { - final DatagramSocket mDgramSocket = new DatagramSocket(0, (InetAddress) Inet6Address.ANY); - mDgramSocket.connect((InetAddress) Inet6Address.LOOPBACK, 53); - assertTrue(mDgramSocket.isConnected()); - - try { - mNetwork.bindSocket(mDgramSocket); - fail("SocketException not thrown"); - } catch (SocketException expected) {} - } - - @Test - public void testBindSocketOfLocalSocketThrows() throws Exception { - final LocalSocket mLocalClient = new LocalSocket(); - mLocalClient.bind(new LocalSocketAddress("testClient")); - assertTrue(mLocalClient.getFileDescriptor().valid()); - - try { - mNetwork.bindSocket(mLocalClient.getFileDescriptor()); - fail("SocketException not thrown"); - } catch (SocketException expected) {} - - final LocalServerSocket mLocalServer = new LocalServerSocket("testServer"); - mLocalClient.connect(mLocalServer.getLocalSocketAddress()); - assertTrue(mLocalClient.isConnected()); - - try { - mNetwork.bindSocket(mLocalClient.getFileDescriptor()); - fail("SocketException not thrown"); - } catch (SocketException expected) {} - } - - @Test - public void testZeroIsObviousForDebugging() { - Network zero = new Network(0); - assertEquals(0, zero.hashCode()); - assertEquals(0, zero.getNetworkHandle()); - assertEquals("0", zero.toString()); - } - - @Test - public void testGetNetworkHandle() { - Network one = new Network(1); - Network two = new Network(2); - Network three = new Network(3); - - // None of the hashcodes are zero. - assertNotEquals(0, one.hashCode()); - assertNotEquals(0, two.hashCode()); - assertNotEquals(0, three.hashCode()); - - // All the hashcodes are distinct. - assertNotEquals(one.hashCode(), two.hashCode()); - assertNotEquals(one.hashCode(), three.hashCode()); - assertNotEquals(two.hashCode(), three.hashCode()); - - // None of the handles are zero. - assertNotEquals(0, one.getNetworkHandle()); - assertNotEquals(0, two.getNetworkHandle()); - assertNotEquals(0, three.getNetworkHandle()); - - // All the handles are distinct. - assertNotEquals(one.getNetworkHandle(), two.getNetworkHandle()); - assertNotEquals(one.getNetworkHandle(), three.getNetworkHandle()); - assertNotEquals(two.getNetworkHandle(), three.getNetworkHandle()); - - // The handles are not equal to the hashcodes. - assertNotEquals(one.hashCode(), one.getNetworkHandle()); - assertNotEquals(two.hashCode(), two.getNetworkHandle()); - assertNotEquals(three.hashCode(), three.getNetworkHandle()); - - // Adjust as necessary to test an implementation's specific constants. - // When running with runtest, "adb logcat -s TestRunner" can be useful. - assertEquals(7700664333L, one.getNetworkHandle()); - assertEquals(11995631629L, two.getNetworkHandle()); - assertEquals(16290598925L, three.getNetworkHandle()); - } - - // getNetId() did not exist in Q - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testGetNetId() { - assertEquals(1234, new Network(1234).getNetId()); - assertEquals(2345, new Network(2345, true).getNetId()); - } - - @Test - public void testFromNetworkHandle() { - final Network network = new Network(1234); - assertEquals(network.netId, Network.fromNetworkHandle(network.getNetworkHandle()).netId); - } - - // Parsing private DNS bypassing handle was not supported until S - @Test @IgnoreUpTo(Build.VERSION_CODES.R) - public void testFromNetworkHandlePrivateDnsBypass_S() { - final Network network = new Network(1234, true); - - final Network recreatedNetwork = Network.fromNetworkHandle(network.getNetworkHandle()); - assertEquals(network.netId, recreatedNetwork.netId); - assertEquals(network.getNetIdForResolv(), recreatedNetwork.getNetIdForResolv()); - } - - @Test @IgnoreAfter(Build.VERSION_CODES.R) - public void testFromNetworkHandlePrivateDnsBypass_R() { - final Network network = new Network(1234, true); - - final Network recreatedNetwork = Network.fromNetworkHandle(network.getNetworkHandle()); - assertEquals(network.netId, recreatedNetwork.netId); - // Until R included, fromNetworkHandle would not parse the private DNS bypass flag - assertEquals(network.netId, recreatedNetwork.getNetIdForResolv()); - } - - @Test - public void testGetPrivateDnsBypassingCopy() { - final Network copy = mNetwork.getPrivateDnsBypassingCopy(); - assertEquals(mNetwork.netId, copy.netId); - assertNotEquals(copy.netId, copy.getNetIdForResolv()); - assertNotEquals(mNetwork.getNetIdForResolv(), copy.getNetIdForResolv()); - } -} diff --git a/packages/Connectivity/tests/common/java/android/net/OemNetworkPreferencesTest.java b/packages/Connectivity/tests/common/java/android/net/OemNetworkPreferencesTest.java deleted file mode 100644 index fd29a9539de8e..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/OemNetworkPreferencesTest.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static com.android.testutils.MiscAsserts.assertThrows; -import static com.android.testutils.ParcelUtils.assertParcelSane; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import android.os.Build; - -import androidx.test.filters.SmallTest; - -import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; -import com.android.testutils.DevSdkIgnoreRunner; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.Map; - -@IgnoreUpTo(Build.VERSION_CODES.R) -@RunWith(DevSdkIgnoreRunner.class) -@SmallTest -public class OemNetworkPreferencesTest { - - private static final int TEST_PREF = OemNetworkPreferences.OEM_NETWORK_PREFERENCE_UNINITIALIZED; - private static final String TEST_PACKAGE = "com.google.apps.contacts"; - - private final OemNetworkPreferences.Builder mBuilder = new OemNetworkPreferences.Builder(); - - @Test - public void testBuilderAddNetworkPreferenceRequiresNonNullPackageName() { - assertThrows(NullPointerException.class, - () -> mBuilder.addNetworkPreference(null, TEST_PREF)); - } - - @Test - public void testBuilderRemoveNetworkPreferenceRequiresNonNullPackageName() { - assertThrows(NullPointerException.class, - () -> mBuilder.clearNetworkPreference(null)); - } - - @Test - public void testGetNetworkPreferenceReturnsCorrectValue() { - final int expectedNumberOfMappings = 1; - mBuilder.addNetworkPreference(TEST_PACKAGE, TEST_PREF); - - final Map networkPreferences = - mBuilder.build().getNetworkPreferences(); - - assertEquals(expectedNumberOfMappings, networkPreferences.size()); - assertTrue(networkPreferences.containsKey(TEST_PACKAGE)); - } - - @Test - public void testGetNetworkPreferenceReturnsUnmodifiableValue() { - final String newPackage = "new.com.google.apps.contacts"; - mBuilder.addNetworkPreference(TEST_PACKAGE, TEST_PREF); - - final Map networkPreferences = - mBuilder.build().getNetworkPreferences(); - - assertThrows(UnsupportedOperationException.class, - () -> networkPreferences.put(newPackage, TEST_PREF)); - - assertThrows(UnsupportedOperationException.class, - () -> networkPreferences.remove(TEST_PACKAGE)); - - } - - @Test - public void testToStringReturnsCorrectValue() { - mBuilder.addNetworkPreference(TEST_PACKAGE, TEST_PREF); - - final String networkPreferencesString = mBuilder.build().getNetworkPreferences().toString(); - - assertTrue(networkPreferencesString.contains(Integer.toString(TEST_PREF))); - assertTrue(networkPreferencesString.contains(TEST_PACKAGE)); - } - - @Test - public void testOemNetworkPreferencesParcelable() { - mBuilder.addNetworkPreference(TEST_PACKAGE, TEST_PREF); - - final OemNetworkPreferences prefs = mBuilder.build(); - - assertParcelSane(prefs, 1 /* fieldCount */); - } - - @Test - public void testAddNetworkPreferenceOverwritesPriorPreference() { - final int newPref = OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID; - mBuilder.addNetworkPreference(TEST_PACKAGE, TEST_PREF); - Map networkPreferences = - mBuilder.build().getNetworkPreferences(); - - assertTrue(networkPreferences.containsKey(TEST_PACKAGE)); - assertEquals(networkPreferences.get(TEST_PACKAGE).intValue(), TEST_PREF); - - mBuilder.addNetworkPreference(TEST_PACKAGE, newPref); - networkPreferences = mBuilder.build().getNetworkPreferences(); - - assertTrue(networkPreferences.containsKey(TEST_PACKAGE)); - assertEquals(networkPreferences.get(TEST_PACKAGE).intValue(), newPref); - } - - @Test - public void testRemoveNetworkPreferenceRemovesValue() { - mBuilder.addNetworkPreference(TEST_PACKAGE, TEST_PREF); - Map networkPreferences = - mBuilder.build().getNetworkPreferences(); - - assertTrue(networkPreferences.containsKey(TEST_PACKAGE)); - - mBuilder.clearNetworkPreference(TEST_PACKAGE); - networkPreferences = mBuilder.build().getNetworkPreferences(); - - assertFalse(networkPreferences.containsKey(TEST_PACKAGE)); - } - - @Test - public void testConstructorByOemNetworkPreferencesSetsValue() { - mBuilder.addNetworkPreference(TEST_PACKAGE, TEST_PREF); - OemNetworkPreferences networkPreference = mBuilder.build(); - - final Map networkPreferences = - new OemNetworkPreferences - .Builder(networkPreference) - .build() - .getNetworkPreferences(); - - assertTrue(networkPreferences.containsKey(TEST_PACKAGE)); - assertEquals(networkPreferences.get(TEST_PACKAGE).intValue(), TEST_PREF); - } -} diff --git a/packages/Connectivity/tests/common/java/android/net/RouteInfoTest.java b/packages/Connectivity/tests/common/java/android/net/RouteInfoTest.java deleted file mode 100644 index 71689f9197264..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/RouteInfoTest.java +++ /dev/null @@ -1,434 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static android.net.RouteInfo.RTN_UNREACHABLE; - -import static com.android.testutils.MiscAsserts.assertEqualBothWays; -import static com.android.testutils.MiscAsserts.assertFieldCountEquals; -import static com.android.testutils.MiscAsserts.assertNotEqualEitherWay; -import static com.android.testutils.ParcelUtils.assertParcelingIsLossless; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import android.os.Build; - -import androidx.core.os.BuildCompat; -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.testutils.DevSdkIgnoreRule; -import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter; -import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class RouteInfoTest { - @Rule - public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule(); - - private static final int INVALID_ROUTE_TYPE = -1; - - private InetAddress Address(String addr) { - return InetAddresses.parseNumericAddress(addr); - } - - private IpPrefix Prefix(String prefix) { - return new IpPrefix(prefix); - } - - private static boolean isAtLeastR() { - // BuildCompat.isAtLeastR is documented to return false on release SDKs (including R) - return Build.VERSION.SDK_INT > Build.VERSION_CODES.Q || BuildCompat.isAtLeastR(); - } - - @Test - public void testConstructor() { - RouteInfo r; - // Invalid input. - try { - r = new RouteInfo((IpPrefix) null, null, "rmnet0"); - fail("Expected RuntimeException: destination and gateway null"); - } catch (RuntimeException e) { } - - try { - r = new RouteInfo(Prefix("2001:db8:ace::/49"), Address("2001:db8::1"), "rmnet0", - INVALID_ROUTE_TYPE); - fail("Invalid route type should cause exception"); - } catch (IllegalArgumentException e) { } - - try { - r = new RouteInfo(Prefix("2001:db8:ace::/49"), Address("192.0.2.1"), "rmnet0", - RTN_UNREACHABLE); - fail("Address family mismatch should cause exception"); - } catch (IllegalArgumentException e) { } - - try { - r = new RouteInfo(Prefix("0.0.0.0/0"), Address("2001:db8::1"), "rmnet0", - RTN_UNREACHABLE); - fail("Address family mismatch should cause exception"); - } catch (IllegalArgumentException e) { } - - // Null destination is default route. - r = new RouteInfo((IpPrefix) null, Address("2001:db8::1"), null); - assertEquals(Prefix("::/0"), r.getDestination()); - assertEquals(Address("2001:db8::1"), r.getGateway()); - assertNull(r.getInterface()); - - r = new RouteInfo((IpPrefix) null, Address("192.0.2.1"), "wlan0"); - assertEquals(Prefix("0.0.0.0/0"), r.getDestination()); - assertEquals(Address("192.0.2.1"), r.getGateway()); - assertEquals("wlan0", r.getInterface()); - - // Null gateway sets gateway to unspecified address (why?). - r = new RouteInfo(Prefix("2001:db8:beef:cafe::/48"), null, "lo"); - assertEquals(Prefix("2001:db8:beef::/48"), r.getDestination()); - assertEquals(Address("::"), r.getGateway()); - assertEquals("lo", r.getInterface()); - - r = new RouteInfo(Prefix("192.0.2.5/24"), null); - assertEquals(Prefix("192.0.2.0/24"), r.getDestination()); - assertEquals(Address("0.0.0.0"), r.getGateway()); - assertNull(r.getInterface()); - } - - @Test - public void testMatches() { - class PatchedRouteInfo { - private final RouteInfo mRouteInfo; - - public PatchedRouteInfo(IpPrefix destination, InetAddress gateway, String iface) { - mRouteInfo = new RouteInfo(destination, gateway, iface); - } - - public boolean matches(InetAddress destination) { - return mRouteInfo.matches(destination); - } - } - - PatchedRouteInfo r; - - r = new PatchedRouteInfo(Prefix("2001:db8:f00::ace:d00d/127"), null, "rmnet0"); - assertTrue(r.matches(Address("2001:db8:f00::ace:d00c"))); - assertTrue(r.matches(Address("2001:db8:f00::ace:d00d"))); - assertFalse(r.matches(Address("2001:db8:f00::ace:d00e"))); - assertFalse(r.matches(Address("2001:db8:f00::bad:d00d"))); - assertFalse(r.matches(Address("2001:4868:4860::8888"))); - assertFalse(r.matches(Address("8.8.8.8"))); - - r = new PatchedRouteInfo(Prefix("192.0.2.0/23"), null, "wlan0"); - assertTrue(r.matches(Address("192.0.2.43"))); - assertTrue(r.matches(Address("192.0.3.21"))); - assertFalse(r.matches(Address("192.0.0.21"))); - assertFalse(r.matches(Address("8.8.8.8"))); - - PatchedRouteInfo ipv6Default = new PatchedRouteInfo(Prefix("::/0"), null, "rmnet0"); - assertTrue(ipv6Default.matches(Address("2001:db8::f00"))); - assertFalse(ipv6Default.matches(Address("192.0.2.1"))); - - PatchedRouteInfo ipv4Default = new PatchedRouteInfo(Prefix("0.0.0.0/0"), null, "rmnet0"); - assertTrue(ipv4Default.matches(Address("255.255.255.255"))); - assertTrue(ipv4Default.matches(Address("192.0.2.1"))); - assertFalse(ipv4Default.matches(Address("2001:db8::f00"))); - } - - @Test - public void testEquals() { - // IPv4 - RouteInfo r1 = new RouteInfo(Prefix("2001:db8:ace::/48"), Address("2001:db8::1"), "wlan0"); - RouteInfo r2 = new RouteInfo(Prefix("2001:db8:ace::/48"), Address("2001:db8::1"), "wlan0"); - assertEqualBothWays(r1, r2); - - RouteInfo r3 = new RouteInfo(Prefix("2001:db8:ace::/49"), Address("2001:db8::1"), "wlan0"); - RouteInfo r4 = new RouteInfo(Prefix("2001:db8:ace::/48"), Address("2001:db8::2"), "wlan0"); - RouteInfo r5 = new RouteInfo(Prefix("2001:db8:ace::/48"), Address("2001:db8::1"), "rmnet0"); - assertNotEqualEitherWay(r1, r3); - assertNotEqualEitherWay(r1, r4); - assertNotEqualEitherWay(r1, r5); - - // IPv6 - r1 = new RouteInfo(Prefix("192.0.2.0/25"), Address("192.0.2.1"), "wlan0"); - r2 = new RouteInfo(Prefix("192.0.2.0/25"), Address("192.0.2.1"), "wlan0"); - assertEqualBothWays(r1, r2); - - r3 = new RouteInfo(Prefix("192.0.2.0/24"), Address("192.0.2.1"), "wlan0"); - r4 = new RouteInfo(Prefix("192.0.2.0/25"), Address("192.0.2.2"), "wlan0"); - r5 = new RouteInfo(Prefix("192.0.2.0/25"), Address("192.0.2.1"), "rmnet0"); - assertNotEqualEitherWay(r1, r3); - assertNotEqualEitherWay(r1, r4); - assertNotEqualEitherWay(r1, r5); - - // Interfaces (but not destinations or gateways) can be null. - r1 = new RouteInfo(Prefix("192.0.2.0/25"), Address("192.0.2.1"), null); - r2 = new RouteInfo(Prefix("192.0.2.0/25"), Address("192.0.2.1"), null); - r3 = new RouteInfo(Prefix("192.0.2.0/24"), Address("192.0.2.1"), "wlan0"); - assertEqualBothWays(r1, r2); - assertNotEqualEitherWay(r1, r3); - } - - @Test - public void testHostAndDefaultRoutes() { - RouteInfo r; - - r = new RouteInfo(Prefix("0.0.0.0/0"), Address("0.0.0.0"), "wlan0"); - assertFalse(r.isHostRoute()); - assertTrue(r.isDefaultRoute()); - assertTrue(r.isIPv4Default()); - assertFalse(r.isIPv6Default()); - if (isAtLeastR()) { - assertFalse(r.isIPv4UnreachableDefault()); - assertFalse(r.isIPv6UnreachableDefault()); - } - - r = new RouteInfo(Prefix("::/0"), Address("::"), "wlan0"); - assertFalse(r.isHostRoute()); - assertTrue(r.isDefaultRoute()); - assertFalse(r.isIPv4Default()); - assertTrue(r.isIPv6Default()); - if (isAtLeastR()) { - assertFalse(r.isIPv4UnreachableDefault()); - assertFalse(r.isIPv6UnreachableDefault()); - } - - r = new RouteInfo(Prefix("192.0.2.0/24"), null, "wlan0"); - assertFalse(r.isHostRoute()); - assertFalse(r.isDefaultRoute()); - assertFalse(r.isIPv4Default()); - assertFalse(r.isIPv6Default()); - if (isAtLeastR()) { - assertFalse(r.isIPv4UnreachableDefault()); - assertFalse(r.isIPv6UnreachableDefault()); - } - - r = new RouteInfo(Prefix("2001:db8::/48"), null, "wlan0"); - assertFalse(r.isHostRoute()); - assertFalse(r.isDefaultRoute()); - assertFalse(r.isIPv4Default()); - assertFalse(r.isIPv6Default()); - if (isAtLeastR()) { - assertFalse(r.isIPv4UnreachableDefault()); - assertFalse(r.isIPv6UnreachableDefault()); - } - - r = new RouteInfo(Prefix("192.0.2.0/32"), Address("0.0.0.0"), "wlan0"); - assertTrue(r.isHostRoute()); - assertFalse(r.isDefaultRoute()); - assertFalse(r.isIPv4Default()); - assertFalse(r.isIPv6Default()); - if (isAtLeastR()) { - assertFalse(r.isIPv4UnreachableDefault()); - assertFalse(r.isIPv6UnreachableDefault()); - } - - r = new RouteInfo(Prefix("2001:db8::/128"), Address("::"), "wlan0"); - assertTrue(r.isHostRoute()); - assertFalse(r.isDefaultRoute()); - assertFalse(r.isIPv4Default()); - assertFalse(r.isIPv6Default()); - if (isAtLeastR()) { - assertFalse(r.isIPv4UnreachableDefault()); - assertFalse(r.isIPv6UnreachableDefault()); - } - - r = new RouteInfo(Prefix("192.0.2.0/32"), null, "wlan0"); - assertTrue(r.isHostRoute()); - assertFalse(r.isDefaultRoute()); - assertFalse(r.isIPv4Default()); - assertFalse(r.isIPv6Default()); - if (isAtLeastR()) { - assertFalse(r.isIPv4UnreachableDefault()); - assertFalse(r.isIPv6UnreachableDefault()); - } - - r = new RouteInfo(Prefix("2001:db8::/128"), null, "wlan0"); - assertTrue(r.isHostRoute()); - assertFalse(r.isDefaultRoute()); - assertFalse(r.isIPv4Default()); - assertFalse(r.isIPv6Default()); - if (isAtLeastR()) { - assertFalse(r.isIPv4UnreachableDefault()); - assertFalse(r.isIPv6UnreachableDefault()); - } - - r = new RouteInfo(Prefix("::/128"), Address("fe80::"), "wlan0"); - assertTrue(r.isHostRoute()); - assertFalse(r.isDefaultRoute()); - assertFalse(r.isIPv4Default()); - assertFalse(r.isIPv6Default()); - if (isAtLeastR()) { - assertFalse(r.isIPv4UnreachableDefault()); - assertFalse(r.isIPv6UnreachableDefault()); - } - - r = new RouteInfo(Prefix("0.0.0.0/32"), Address("192.0.2.1"), "wlan0"); - assertTrue(r.isHostRoute()); - assertFalse(r.isDefaultRoute()); - assertFalse(r.isIPv4Default()); - assertFalse(r.isIPv6Default()); - if (isAtLeastR()) { - assertFalse(r.isIPv4UnreachableDefault()); - assertFalse(r.isIPv6UnreachableDefault()); - } - - r = new RouteInfo(Prefix("0.0.0.0/32"), Address("192.0.2.1"), "wlan0"); - assertTrue(r.isHostRoute()); - assertFalse(r.isDefaultRoute()); - assertFalse(r.isIPv4Default()); - assertFalse(r.isIPv6Default()); - if (isAtLeastR()) { - assertFalse(r.isIPv4UnreachableDefault()); - assertFalse(r.isIPv6UnreachableDefault()); - } - - r = new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE); - assertFalse(r.isHostRoute()); - assertFalse(r.isDefaultRoute()); - assertFalse(r.isIPv4Default()); - assertFalse(r.isIPv6Default()); - if (isAtLeastR()) { - assertTrue(r.isIPv4UnreachableDefault()); - assertFalse(r.isIPv6UnreachableDefault()); - } - - r = new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE); - assertFalse(r.isHostRoute()); - assertFalse(r.isDefaultRoute()); - assertFalse(r.isIPv4Default()); - assertFalse(r.isIPv6Default()); - if (isAtLeastR()) { - assertFalse(r.isIPv4UnreachableDefault()); - assertTrue(r.isIPv6UnreachableDefault()); - } - } - - @Test - public void testTruncation() { - LinkAddress l; - RouteInfo r; - - l = new LinkAddress("192.0.2.5/30"); - r = new RouteInfo(l, Address("192.0.2.1"), "wlan0"); - assertEquals("192.0.2.4", r.getDestination().getAddress().getHostAddress()); - - l = new LinkAddress("2001:db8:1:f::5/63"); - r = new RouteInfo(l, Address("2001:db8:5::1"), "wlan0"); - assertEquals("2001:db8:1:e::", r.getDestination().getAddress().getHostAddress()); - } - - // Make sure that creating routes to multicast addresses doesn't throw an exception. Even though - // there's nothing we can do with them, we don't want to crash if, e.g., someone calls - // requestRouteToHostAddress("230.0.0.0", MOBILE_HIPRI); - @Test - public void testMulticastRoute() { - RouteInfo r; - r = new RouteInfo(Prefix("230.0.0.0/32"), Address("192.0.2.1"), "wlan0"); - r = new RouteInfo(Prefix("ff02::1/128"), Address("2001:db8::1"), "wlan0"); - // No exceptions? Good. - } - - @Test - public void testParceling() { - RouteInfo r; - r = new RouteInfo(Prefix("192.0.2.0/24"), Address("192.0.2.1"), null); - assertParcelingIsLossless(r); - r = new RouteInfo(Prefix("192.0.2.0/24"), null, "wlan0"); - assertParcelingIsLossless(r); - r = new RouteInfo(Prefix("192.0.2.0/24"), Address("192.0.2.1"), "wlan0", RTN_UNREACHABLE); - assertParcelingIsLossless(r); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testMtuParceling() { - final RouteInfo r = new RouteInfo(Prefix("ff02::1/128"), Address("2001:db8::"), "testiface", - RTN_UNREACHABLE, 1450 /* mtu */); - assertParcelingIsLossless(r); - } - - @Test @IgnoreAfter(Build.VERSION_CODES.Q) - public void testFieldCount_Q() { - assertFieldCountEquals(6, RouteInfo.class); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testFieldCount() { - // Make sure any new field is covered by the above parceling tests when changing this number - assertFieldCountEquals(7, RouteInfo.class); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testMtu() { - RouteInfo r; - r = new RouteInfo(Prefix("0.0.0.0/0"), Address("0.0.0.0"), "wlan0", - RouteInfo.RTN_UNICAST, 1500); - assertEquals(1500, r.getMtu()); - - r = new RouteInfo(Prefix("0.0.0.0/0"), Address("0.0.0.0"), "wlan0"); - assertEquals(0, r.getMtu()); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testRouteKey() { - RouteInfo.RouteKey k1, k2; - // Only prefix, null gateway and null interface - k1 = new RouteInfo(Prefix("2001:db8::/128"), null).getRouteKey(); - k2 = new RouteInfo(Prefix("2001:db8::/128"), null).getRouteKey(); - assertEquals(k1, k2); - assertEquals(k1.hashCode(), k2.hashCode()); - - // With prefix, gateway and interface. Type and MTU does not affect RouteKey equality - k1 = new RouteInfo(Prefix("192.0.2.0/24"), Address("192.0.2.1"), "wlan0", - RTN_UNREACHABLE, 1450).getRouteKey(); - k2 = new RouteInfo(Prefix("192.0.2.0/24"), Address("192.0.2.1"), "wlan0", - RouteInfo.RTN_UNICAST, 1400).getRouteKey(); - assertEquals(k1, k2); - assertEquals(k1.hashCode(), k2.hashCode()); - - // Different scope IDs are ignored by the kernel, so we consider them equal here too. - k1 = new RouteInfo(Prefix("2001:db8::/64"), Address("fe80::1%1"), "wlan0").getRouteKey(); - k2 = new RouteInfo(Prefix("2001:db8::/64"), Address("fe80::1%2"), "wlan0").getRouteKey(); - assertEquals(k1, k2); - assertEquals(k1.hashCode(), k2.hashCode()); - - // Different prefix - k1 = new RouteInfo(Prefix("192.0.2.0/24"), null).getRouteKey(); - k2 = new RouteInfo(Prefix("192.0.3.0/24"), null).getRouteKey(); - assertNotEquals(k1, k2); - - // Different gateway - k1 = new RouteInfo(Prefix("ff02::1/128"), Address("2001:db8::1"), null).getRouteKey(); - k2 = new RouteInfo(Prefix("ff02::1/128"), Address("2001:db8::2"), null).getRouteKey(); - assertNotEquals(k1, k2); - - // Different interface - k1 = new RouteInfo(Prefix("ff02::1/128"), null, "tun0").getRouteKey(); - k2 = new RouteInfo(Prefix("ff02::1/128"), null, "tun1").getRouteKey(); - assertNotEquals(k1, k2); - } -} diff --git a/packages/Connectivity/tests/common/java/android/net/StaticIpConfigurationTest.java b/packages/Connectivity/tests/common/java/android/net/StaticIpConfigurationTest.java deleted file mode 100644 index b5f23bf19a3c0..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/StaticIpConfigurationTest.java +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import android.os.Parcel; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class StaticIpConfigurationTest { - - private static final String ADDRSTR = "192.0.2.2/25"; - private static final LinkAddress ADDR = new LinkAddress(ADDRSTR); - private static final InetAddress GATEWAY = IpAddress("192.0.2.1"); - private static final InetAddress OFFLINKGATEWAY = IpAddress("192.0.2.129"); - private static final InetAddress DNS1 = IpAddress("8.8.8.8"); - private static final InetAddress DNS2 = IpAddress("8.8.4.4"); - private static final InetAddress DNS3 = IpAddress("4.2.2.2"); - private static final String IFACE = "eth0"; - private static final String FAKE_DOMAINS = "google.com"; - - private static InetAddress IpAddress(String addr) { - return InetAddress.parseNumericAddress(addr); - } - - private void checkEmpty(StaticIpConfiguration s) { - assertNull(s.ipAddress); - assertNull(s.gateway); - assertNull(s.domains); - assertEquals(0, s.dnsServers.size()); - } - - private StaticIpConfiguration makeTestObject() { - StaticIpConfiguration s = new StaticIpConfiguration(); - s.ipAddress = ADDR; - s.gateway = GATEWAY; - s.dnsServers.add(DNS1); - s.dnsServers.add(DNS2); - s.dnsServers.add(DNS3); - s.domains = FAKE_DOMAINS; - return s; - } - - @Test - public void testConstructor() { - StaticIpConfiguration s = new StaticIpConfiguration(); - checkEmpty(s); - } - - @Test - public void testCopyAndClear() { - StaticIpConfiguration empty = new StaticIpConfiguration((StaticIpConfiguration) null); - checkEmpty(empty); - - StaticIpConfiguration s1 = makeTestObject(); - StaticIpConfiguration s2 = new StaticIpConfiguration(s1); - assertEquals(s1, s2); - s2.clear(); - assertEquals(empty, s2); - } - - @Test - public void testHashCodeAndEquals() { - HashSet hashCodes = new HashSet(); - hashCodes.add(0); - - StaticIpConfiguration s = new StaticIpConfiguration(); - // Check that this hash code is nonzero and different from all the ones seen so far. - assertTrue(hashCodes.add(s.hashCode())); - - s.ipAddress = ADDR; - assertTrue(hashCodes.add(s.hashCode())); - - s.gateway = GATEWAY; - assertTrue(hashCodes.add(s.hashCode())); - - s.dnsServers.add(DNS1); - assertTrue(hashCodes.add(s.hashCode())); - - s.dnsServers.add(DNS2); - assertTrue(hashCodes.add(s.hashCode())); - - s.dnsServers.add(DNS3); - assertTrue(hashCodes.add(s.hashCode())); - - s.domains = "example.com"; - assertTrue(hashCodes.add(s.hashCode())); - - assertFalse(s.equals(null)); - assertEquals(s, s); - - StaticIpConfiguration s2 = new StaticIpConfiguration(s); - assertEquals(s, s2); - - s.ipAddress = new LinkAddress(DNS1, 32); - assertNotEquals(s, s2); - - s2 = new StaticIpConfiguration(s); - s.domains = "foo"; - assertNotEquals(s, s2); - - s2 = new StaticIpConfiguration(s); - s.gateway = DNS2; - assertNotEquals(s, s2); - - s2 = new StaticIpConfiguration(s); - s.dnsServers.add(DNS3); - assertNotEquals(s, s2); - } - - @Test - public void testToLinkProperties() { - LinkProperties expected = new LinkProperties(); - expected.setInterfaceName(IFACE); - - StaticIpConfiguration s = new StaticIpConfiguration(); - assertEquals(expected, s.toLinkProperties(IFACE)); - - final RouteInfo connectedRoute = new RouteInfo(new IpPrefix(ADDRSTR), null, IFACE); - s.ipAddress = ADDR; - expected.addLinkAddress(ADDR); - expected.addRoute(connectedRoute); - assertEquals(expected, s.toLinkProperties(IFACE)); - - s.gateway = GATEWAY; - RouteInfo defaultRoute = new RouteInfo(new IpPrefix("0.0.0.0/0"), GATEWAY, IFACE); - expected.addRoute(defaultRoute); - assertEquals(expected, s.toLinkProperties(IFACE)); - - s.gateway = OFFLINKGATEWAY; - expected.removeRoute(defaultRoute); - defaultRoute = new RouteInfo(new IpPrefix("0.0.0.0/0"), OFFLINKGATEWAY, IFACE); - expected.addRoute(defaultRoute); - - RouteInfo gatewayRoute = new RouteInfo(new IpPrefix("192.0.2.129/32"), null, IFACE); - expected.addRoute(gatewayRoute); - assertEquals(expected, s.toLinkProperties(IFACE)); - - s.dnsServers.add(DNS1); - expected.addDnsServer(DNS1); - assertEquals(expected, s.toLinkProperties(IFACE)); - - s.dnsServers.add(DNS2); - s.dnsServers.add(DNS3); - expected.addDnsServer(DNS2); - expected.addDnsServer(DNS3); - assertEquals(expected, s.toLinkProperties(IFACE)); - - s.domains = FAKE_DOMAINS; - expected.setDomains(FAKE_DOMAINS); - assertEquals(expected, s.toLinkProperties(IFACE)); - - s.gateway = null; - expected.removeRoute(defaultRoute); - expected.removeRoute(gatewayRoute); - assertEquals(expected, s.toLinkProperties(IFACE)); - - // Without knowing the IP address, we don't have a directly-connected route, so we can't - // tell if the gateway is off-link or not and we don't add a host route. This isn't a real - // configuration, but we should at least not crash. - s.gateway = OFFLINKGATEWAY; - s.ipAddress = null; - expected.removeLinkAddress(ADDR); - expected.removeRoute(connectedRoute); - expected.addRoute(defaultRoute); - assertEquals(expected, s.toLinkProperties(IFACE)); - } - - private StaticIpConfiguration passThroughParcel(StaticIpConfiguration s) { - Parcel p = Parcel.obtain(); - StaticIpConfiguration s2 = null; - try { - s.writeToParcel(p, 0); - p.setDataPosition(0); - s2 = StaticIpConfiguration.readFromParcel(p); - } finally { - p.recycle(); - } - assertNotNull(s2); - return s2; - } - - @Test - public void testParceling() { - StaticIpConfiguration s = makeTestObject(); - StaticIpConfiguration s2 = passThroughParcel(s); - assertEquals(s, s2); - } - - @Test - public void testBuilder() { - final ArrayList dnsServers = new ArrayList<>(); - dnsServers.add(DNS1); - - final StaticIpConfiguration s = new StaticIpConfiguration.Builder() - .setIpAddress(ADDR) - .setGateway(GATEWAY) - .setDomains(FAKE_DOMAINS) - .setDnsServers(dnsServers) - .build(); - - assertEquals(s.ipAddress, s.getIpAddress()); - assertEquals(ADDR, s.getIpAddress()); - assertEquals(s.gateway, s.getGateway()); - assertEquals(GATEWAY, s.getGateway()); - assertEquals(s.domains, s.getDomains()); - assertEquals(FAKE_DOMAINS, s.getDomains()); - assertTrue(s.dnsServers.equals(s.getDnsServers())); - assertEquals(1, s.getDnsServers().size()); - assertEquals(DNS1, s.getDnsServers().get(0)); - } - - @Test - public void testAddDnsServers() { - final StaticIpConfiguration s = new StaticIpConfiguration((StaticIpConfiguration) null); - checkEmpty(s); - - s.addDnsServer(DNS1); - assertEquals(1, s.getDnsServers().size()); - assertEquals(DNS1, s.getDnsServers().get(0)); - - s.addDnsServer(DNS2); - s.addDnsServer(DNS3); - assertEquals(3, s.getDnsServers().size()); - assertEquals(DNS2, s.getDnsServers().get(1)); - assertEquals(DNS3, s.getDnsServers().get(2)); - } - - @Test - public void testGetRoutes() { - final StaticIpConfiguration s = makeTestObject(); - final List routeInfoList = s.getRoutes(IFACE); - - assertEquals(2, routeInfoList.size()); - assertEquals(new RouteInfo(ADDR, (InetAddress) null, IFACE), routeInfoList.get(0)); - assertEquals(new RouteInfo((IpPrefix) null, GATEWAY, IFACE), routeInfoList.get(1)); - } -} diff --git a/packages/Connectivity/tests/common/java/android/net/TcpKeepalivePacketDataTest.kt b/packages/Connectivity/tests/common/java/android/net/TcpKeepalivePacketDataTest.kt deleted file mode 100644 index 7a18bb08faa8e..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/TcpKeepalivePacketDataTest.kt +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net - -import android.net.InetAddresses.parseNumericAddress -import android.os.Build -import com.android.testutils.DevSdkIgnoreRule -import com.android.testutils.DevSdkIgnoreRunner -import com.android.testutils.assertFieldCountEquals -import com.android.testutils.assertParcelSane -import org.junit.Test -import org.junit.runner.RunWith -import java.net.InetAddress -import kotlin.test.assertEquals -import kotlin.test.assertNotEquals -import kotlin.test.assertTrue - -@RunWith(DevSdkIgnoreRunner::class) -@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R) // TcpKeepalivePacketData added to SDK in S -class TcpKeepalivePacketDataTest { - private fun makeData( - srcAddress: InetAddress = parseNumericAddress("192.0.2.123"), - srcPort: Int = 1234, - dstAddress: InetAddress = parseNumericAddress("192.0.2.231"), - dstPort: Int = 4321, - data: ByteArray = byteArrayOf(1, 2, 3), - tcpSeq: Int = 135, - tcpAck: Int = 246, - tcpWnd: Int = 1234, - tcpWndScale: Int = 2, - ipTos: Int = 0x12, - ipTtl: Int = 10 - ) = TcpKeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, data, tcpSeq, tcpAck, - tcpWnd, tcpWndScale, ipTos, ipTtl) - - @Test - fun testEquals() { - val data1 = makeData() - val data2 = makeData() - assertEquals(data1, data2) - assertEquals(data1.hashCode(), data2.hashCode()) - } - - @Test - fun testNotEquals() { - assertNotEquals(makeData(srcAddress = parseNumericAddress("192.0.2.124")), makeData()) - assertNotEquals(makeData(srcPort = 1235), makeData()) - assertNotEquals(makeData(dstAddress = parseNumericAddress("192.0.2.232")), makeData()) - assertNotEquals(makeData(dstPort = 4322), makeData()) - // .equals does not test .packet, as it should be generated from the other fields - assertNotEquals(makeData(tcpSeq = 136), makeData()) - assertNotEquals(makeData(tcpAck = 247), makeData()) - assertNotEquals(makeData(tcpWnd = 1235), makeData()) - assertNotEquals(makeData(tcpWndScale = 3), makeData()) - assertNotEquals(makeData(ipTos = 0x14), makeData()) - assertNotEquals(makeData(ipTtl = 11), makeData()) - - // Update above assertions if field is added - assertFieldCountEquals(5, KeepalivePacketData::class.java) - assertFieldCountEquals(6, TcpKeepalivePacketData::class.java) - } - - @Test - fun testParcelUnparcel() { - assertParcelSane(makeData(), fieldCount = 6) { a, b -> - // .equals() does not verify .packet - a == b && a.packet contentEquals b.packet - } - } - - @Test - fun testToString() { - val data = makeData() - val str = data.toString() - - assertTrue(str.contains(data.srcAddress.hostAddress)) - assertTrue(str.contains(data.srcPort.toString())) - assertTrue(str.contains(data.dstAddress.hostAddress)) - assertTrue(str.contains(data.dstPort.toString())) - // .packet not included in toString() - assertTrue(str.contains(data.getTcpSeq().toString())) - assertTrue(str.contains(data.getTcpAck().toString())) - assertTrue(str.contains(data.getTcpWindow().toString())) - assertTrue(str.contains(data.getTcpWindowScale().toString())) - assertTrue(str.contains(data.getIpTos().toString())) - assertTrue(str.contains(data.getIpTtl().toString())) - - // Update above assertions if field is added - assertFieldCountEquals(5, KeepalivePacketData::class.java) - assertFieldCountEquals(6, TcpKeepalivePacketData::class.java) - } -} \ No newline at end of file diff --git a/packages/Connectivity/tests/common/java/android/net/UidRangeTest.java b/packages/Connectivity/tests/common/java/android/net/UidRangeTest.java deleted file mode 100644 index 1b1c95431d6f7..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/UidRangeTest.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static android.os.UserHandle.MIN_SECONDARY_USER_ID; -import static android.os.UserHandle.SYSTEM; -import static android.os.UserHandle.USER_SYSTEM; -import static android.os.UserHandle.getUid; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import android.os.Build; -import android.os.UserHandle; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.testutils.DevSdkIgnoreRule; -import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class UidRangeTest { - - /* - * UidRange is no longer passed to netd. UID ranges between the framework and netd are passed as - * UidRangeParcel objects. - */ - - @Rule - public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule(); - - @Test - public void testSingleItemUidRangeAllowed() { - new UidRange(123, 123); - new UidRange(0, 0); - new UidRange(Integer.MAX_VALUE, Integer.MAX_VALUE); - } - - @Test - public void testNegativeUidsDisallowed() { - try { - new UidRange(-2, 100); - fail("Exception not thrown for negative start UID"); - } catch (IllegalArgumentException expected) { - } - - try { - new UidRange(-200, -100); - fail("Exception not thrown for negative stop UID"); - } catch (IllegalArgumentException expected) { - } - } - - @Test - public void testStopLessThanStartDisallowed() { - final int x = 4195000; - try { - new UidRange(x, x - 1); - fail("Exception not thrown for negative-length UID range"); - } catch (IllegalArgumentException expected) { - } - } - - @Test - public void testGetStartAndEndUser() throws Exception { - final UidRange uidRangeOfPrimaryUser = new UidRange( - getUid(USER_SYSTEM, 10000), getUid(USER_SYSTEM, 10100)); - final UidRange uidRangeOfSecondaryUser = new UidRange( - getUid(MIN_SECONDARY_USER_ID, 10000), getUid(MIN_SECONDARY_USER_ID, 10100)); - assertEquals(USER_SYSTEM, uidRangeOfPrimaryUser.getStartUser()); - assertEquals(USER_SYSTEM, uidRangeOfPrimaryUser.getEndUser()); - assertEquals(MIN_SECONDARY_USER_ID, uidRangeOfSecondaryUser.getStartUser()); - assertEquals(MIN_SECONDARY_USER_ID, uidRangeOfSecondaryUser.getEndUser()); - - final UidRange uidRangeForDifferentUsers = new UidRange( - getUid(USER_SYSTEM, 10000), getUid(MIN_SECONDARY_USER_ID, 10100)); - assertEquals(USER_SYSTEM, uidRangeOfPrimaryUser.getStartUser()); - assertEquals(MIN_SECONDARY_USER_ID, uidRangeOfSecondaryUser.getEndUser()); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.R) - public void testCreateForUser() throws Exception { - final UidRange uidRangeOfPrimaryUser = UidRange.createForUser(SYSTEM); - final UidRange uidRangeOfSecondaryUser = UidRange.createForUser( - UserHandle.of(USER_SYSTEM + 1)); - assertTrue(uidRangeOfPrimaryUser.stop < uidRangeOfSecondaryUser.start); - assertEquals(USER_SYSTEM, uidRangeOfPrimaryUser.getStartUser()); - assertEquals(USER_SYSTEM, uidRangeOfPrimaryUser.getEndUser()); - assertEquals(USER_SYSTEM + 1, uidRangeOfSecondaryUser.getStartUser()); - assertEquals(USER_SYSTEM + 1, uidRangeOfSecondaryUser.getEndUser()); - } -} diff --git a/packages/Connectivity/tests/common/java/android/net/UnderlyingNetworkInfoTest.kt b/packages/Connectivity/tests/common/java/android/net/UnderlyingNetworkInfoTest.kt deleted file mode 100644 index f23ba26d00396..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/UnderlyingNetworkInfoTest.kt +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net - -import android.os.Build -import androidx.test.filters.SmallTest -import com.android.testutils.DevSdkIgnoreRule -import com.android.testutils.DevSdkIgnoreRunner -import com.android.testutils.assertParcelSane -import org.junit.Test -import org.junit.runner.RunWith -import kotlin.test.assertEquals - -private const val TEST_OWNER_UID = 123 -private const val TEST_IFACE = "test_tun0" -private val TEST_IFACE_LIST = listOf("wlan0", "rmnet_data0", "eth0") - -@SmallTest -@RunWith(DevSdkIgnoreRunner::class) -@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R) -class UnderlyingNetworkInfoTest { - @Test - fun testParcelUnparcel() { - val testInfo = UnderlyingNetworkInfo(TEST_OWNER_UID, TEST_IFACE, TEST_IFACE_LIST) - assertEquals(TEST_OWNER_UID, testInfo.getOwnerUid()) - assertEquals(TEST_IFACE, testInfo.getInterface()) - assertEquals(TEST_IFACE_LIST, testInfo.getUnderlyingInterfaces()) - assertParcelSane(testInfo, 3) - - val emptyInfo = UnderlyingNetworkInfo(0, String(), listOf()) - assertEquals(0, emptyInfo.getOwnerUid()) - assertEquals(String(), emptyInfo.getInterface()) - assertEquals(listOf(), emptyInfo.getUnderlyingInterfaces()) - assertParcelSane(emptyInfo, 3) - } -} \ No newline at end of file diff --git a/packages/Connectivity/tests/common/java/android/net/apf/ApfCapabilitiesTest.java b/packages/Connectivity/tests/common/java/android/net/apf/ApfCapabilitiesTest.java deleted file mode 100644 index 88996d9252627..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/apf/ApfCapabilitiesTest.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.apf; - -import static com.android.testutils.ParcelUtils.assertParcelSane; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import android.content.Context; -import android.os.Build; - -import androidx.test.InstrumentationRegistry; -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.testutils.DevSdkIgnoreRule; -import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.Arrays; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class ApfCapabilitiesTest { - @Rule - public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule(); - - private Context mContext; - - @Before - public void setUp() { - mContext = InstrumentationRegistry.getContext(); - } - - @Test - public void testConstructAndParcel() { - final ApfCapabilities caps = new ApfCapabilities(123, 456, 789); - assertEquals(123, caps.apfVersionSupported); - assertEquals(456, caps.maximumApfProgramSize); - assertEquals(789, caps.apfPacketFormat); - - assertParcelSane(caps, 3); - } - - @Test - public void testEquals() { - assertEquals(new ApfCapabilities(1, 2, 3), new ApfCapabilities(1, 2, 3)); - assertNotEquals(new ApfCapabilities(2, 2, 3), new ApfCapabilities(1, 2, 3)); - assertNotEquals(new ApfCapabilities(1, 3, 3), new ApfCapabilities(1, 2, 3)); - assertNotEquals(new ApfCapabilities(1, 2, 4), new ApfCapabilities(1, 2, 3)); - } - - @Test - public void testHasDataAccess() { - //hasDataAccess is only supported starting at apf version 4. - ApfCapabilities caps = new ApfCapabilities(1 /* apfVersionSupported */, 2, 3); - assertFalse(caps.hasDataAccess()); - - caps = new ApfCapabilities(4 /* apfVersionSupported */, 5, 6); - assertTrue(caps.hasDataAccess()); - } - - @Test - public void testGetApfDrop8023Frames() { - // Get com.android.internal.R.bool.config_apfDrop802_3Frames. The test cannot directly - // use R.bool.config_apfDrop802_3Frames because that is not a stable resource ID. - final int resId = mContext.getResources().getIdentifier("config_apfDrop802_3Frames", - "bool", "android"); - final boolean shouldDrop8023Frames = mContext.getResources().getBoolean(resId); - final boolean actual = ApfCapabilities.getApfDrop8023Frames(); - assertEquals(shouldDrop8023Frames, actual); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.R) - public void testGetApfDrop8023Frames_S() { - // IpClient does not call getApfDrop8023Frames() since S, so any customization of the return - // value on S+ is a configuration error as it will not be used by IpClient. - assertTrue("android.R.bool.config_apfDrop802_3Frames has been modified to false, but " - + "starting from S its value is not used by IpClient. If the modification is " - + "intentional, use a runtime resource overlay for the NetworkStack package to " - + "overlay com.android.networkstack.R.bool.config_apfDrop802_3Frames instead.", - ApfCapabilities.getApfDrop8023Frames()); - } - - @Test - public void testGetApfEtherTypeBlackList() { - // Get com.android.internal.R.array.config_apfEthTypeBlackList. The test cannot directly - // use R.array.config_apfEthTypeBlackList because that is not a stable resource ID. - final int resId = mContext.getResources().getIdentifier("config_apfEthTypeBlackList", - "array", "android"); - final int[] blacklistedEtherTypeArray = mContext.getResources().getIntArray(resId); - final int[] actual = ApfCapabilities.getApfEtherTypeBlackList(); - assertNotNull(actual); - assertTrue(Arrays.equals(blacklistedEtherTypeArray, actual)); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.R) - public void testGetApfEtherTypeBlackList_S() { - // IpClient does not call getApfEtherTypeBlackList() since S, so any customization of the - // return value on S+ is a configuration error as it will not be used by IpClient. - assertArrayEquals("android.R.array.config_apfEthTypeBlackList has been modified, but " - + "starting from S its value is not used by IpClient. If the modification " - + "is intentional, use a runtime resource overlay for the NetworkStack " - + "package to overlay " - + "com.android.networkstack.R.array.config_apfEthTypeDenyList instead.", - new int[] { 0x88a2, 0x88a4, 0x88b8, 0x88cd, 0x88e3 }, - ApfCapabilities.getApfEtherTypeBlackList()); - } -} diff --git a/packages/Connectivity/tests/common/java/android/net/metrics/ApfProgramEventTest.kt b/packages/Connectivity/tests/common/java/android/net/metrics/ApfProgramEventTest.kt deleted file mode 100644 index 0b7b74097cc61..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/metrics/ApfProgramEventTest.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.metrics; - -import androidx.test.filters.SmallTest -import androidx.test.runner.AndroidJUnit4 -import com.android.testutils.assertParcelSane -import org.junit.Assert.assertEquals -import org.junit.Assert.assertFalse -import org.junit.Assert.assertTrue -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -@SmallTest -class ApfProgramEventTest { - private infix fun Int.hasFlag(flag: Int) = (this and (1 shl flag)) != 0 - - @Test - fun testBuilderAndParcel() { - val apfProgramEvent = ApfProgramEvent.Builder() - .setLifetime(1) - .setActualLifetime(2) - .setFilteredRas(3) - .setCurrentRas(4) - .setProgramLength(5) - .setFlags(true, true) - .build() - - assertEquals(1, apfProgramEvent.lifetime) - assertEquals(2, apfProgramEvent.actualLifetime) - assertEquals(3, apfProgramEvent.filteredRas) - assertEquals(4, apfProgramEvent.currentRas) - assertEquals(5, apfProgramEvent.programLength) - assertEquals(ApfProgramEvent.flagsFor(true, true), apfProgramEvent.flags) - - assertParcelSane(apfProgramEvent, 6) - } - - @Test - fun testFlagsFor() { - var flags = ApfProgramEvent.flagsFor(false, false) - assertFalse(flags hasFlag ApfProgramEvent.FLAG_HAS_IPV4_ADDRESS) - assertFalse(flags hasFlag ApfProgramEvent.FLAG_MULTICAST_FILTER_ON) - - flags = ApfProgramEvent.flagsFor(true, false) - assertTrue(flags hasFlag ApfProgramEvent.FLAG_HAS_IPV4_ADDRESS) - assertFalse(flags hasFlag ApfProgramEvent.FLAG_MULTICAST_FILTER_ON) - - flags = ApfProgramEvent.flagsFor(false, true) - assertFalse(flags hasFlag ApfProgramEvent.FLAG_HAS_IPV4_ADDRESS) - assertTrue(flags hasFlag ApfProgramEvent.FLAG_MULTICAST_FILTER_ON) - - flags = ApfProgramEvent.flagsFor(true, true) - assertTrue(flags hasFlag ApfProgramEvent.FLAG_HAS_IPV4_ADDRESS) - assertTrue(flags hasFlag ApfProgramEvent.FLAG_MULTICAST_FILTER_ON) - } -} diff --git a/packages/Connectivity/tests/common/java/android/net/metrics/ApfStatsTest.kt b/packages/Connectivity/tests/common/java/android/net/metrics/ApfStatsTest.kt deleted file mode 100644 index 46a8c8e5b5090..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/metrics/ApfStatsTest.kt +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.metrics - -import androidx.test.filters.SmallTest -import androidx.test.runner.AndroidJUnit4 -import com.android.testutils.assertParcelSane -import org.junit.Assert.assertEquals -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -@SmallTest -class ApfStatsTest { - @Test - fun testBuilderAndParcel() { - val apfStats = ApfStats.Builder() - .setDurationMs(Long.MAX_VALUE) - .setReceivedRas(1) - .setMatchingRas(2) - .setDroppedRas(3) - .setZeroLifetimeRas(4) - .setParseErrors(5) - .setProgramUpdates(6) - .setProgramUpdatesAll(7) - .setProgramUpdatesAllowingMulticast(8) - .setMaxProgramSize(9) - .build() - - assertEquals(Long.MAX_VALUE, apfStats.durationMs) - assertEquals(1, apfStats.receivedRas) - assertEquals(2, apfStats.matchingRas) - assertEquals(3, apfStats.droppedRas) - assertEquals(4, apfStats.zeroLifetimeRas) - assertEquals(5, apfStats.parseErrors) - assertEquals(6, apfStats.programUpdates) - assertEquals(7, apfStats.programUpdatesAll) - assertEquals(8, apfStats.programUpdatesAllowingMulticast) - assertEquals(9, apfStats.maxProgramSize) - - assertParcelSane(apfStats, 10) - } -} diff --git a/packages/Connectivity/tests/common/java/android/net/metrics/DhcpClientEventTest.kt b/packages/Connectivity/tests/common/java/android/net/metrics/DhcpClientEventTest.kt deleted file mode 100644 index 8d7a9c405024b..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/metrics/DhcpClientEventTest.kt +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.metrics - -import androidx.test.filters.SmallTest -import androidx.test.runner.AndroidJUnit4 -import com.android.testutils.assertParcelSane -import org.junit.Assert.assertEquals -import org.junit.Test -import org.junit.runner.RunWith - -private const val FAKE_MESSAGE = "test" - -@RunWith(AndroidJUnit4::class) -@SmallTest -class DhcpClientEventTest { - @Test - fun testBuilderAndParcel() { - val dhcpClientEvent = DhcpClientEvent.Builder() - .setMsg(FAKE_MESSAGE) - .setDurationMs(Integer.MAX_VALUE) - .build() - - assertEquals(FAKE_MESSAGE, dhcpClientEvent.msg) - assertEquals(Integer.MAX_VALUE, dhcpClientEvent.durationMs) - - assertParcelSane(dhcpClientEvent, 2) - } -} diff --git a/packages/Connectivity/tests/common/java/android/net/metrics/DhcpErrorEventTest.kt b/packages/Connectivity/tests/common/java/android/net/metrics/DhcpErrorEventTest.kt deleted file mode 100644 index 236f72eafbdcf..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/metrics/DhcpErrorEventTest.kt +++ /dev/null @@ -1,65 +0,0 @@ -package android.net.metrics - -import android.net.metrics.DhcpErrorEvent.DHCP_INVALID_OPTION_LENGTH -import android.net.metrics.DhcpErrorEvent.errorCodeWithOption -import androidx.test.filters.SmallTest -import androidx.test.runner.AndroidJUnit4 -import com.android.testutils.parcelingRoundTrip -import java.lang.reflect.Modifier -import org.junit.Assert.assertEquals -import org.junit.Assert.assertNotNull -import org.junit.Assert.assertTrue -import org.junit.Test -import org.junit.runner.RunWith - -private const val TEST_ERROR_CODE = 12345 -//DHCP Optional Type: DHCP Subnet Mask (Copy from DhcpPacket.java due to it's protected) -private const val DHCP_SUBNET_MASK = 1 - -@RunWith(AndroidJUnit4::class) -@SmallTest -class DhcpErrorEventTest { - - @Test - fun testConstructor() { - val event = DhcpErrorEvent(TEST_ERROR_CODE) - assertEquals(TEST_ERROR_CODE, event.errorCode) - } - - @Test - fun testParcelUnparcel() { - val event = DhcpErrorEvent(TEST_ERROR_CODE) - val parceled = parcelingRoundTrip(event) - assertEquals(TEST_ERROR_CODE, parceled.errorCode) - } - - @Test - fun testErrorCodeWithOption() { - val errorCode = errorCodeWithOption(DHCP_INVALID_OPTION_LENGTH, DHCP_SUBNET_MASK); - assertTrue((DHCP_INVALID_OPTION_LENGTH and errorCode) == DHCP_INVALID_OPTION_LENGTH); - assertTrue((DHCP_SUBNET_MASK and errorCode) == DHCP_SUBNET_MASK); - } - - @Test - fun testToString() { - val names = listOf("L2_ERROR", "L3_ERROR", "L4_ERROR", "DHCP_ERROR", "MISC_ERROR") - val errorFields = DhcpErrorEvent::class.java.declaredFields.filter { - it.type == Int::class.javaPrimitiveType - && Modifier.isPublic(it.modifiers) && Modifier.isStatic(it.modifiers) - && it.name !in names - } - - errorFields.forEach { - val intValue = it.getInt(null) - val stringValue = DhcpErrorEvent(intValue).toString() - assertTrue("Invalid string for error 0x%08X (field %s): %s".format(intValue, it.name, - stringValue), - stringValue.contains(it.name)) - } - } - - @Test - fun testToString_InvalidErrorCode() { - assertNotNull(DhcpErrorEvent(TEST_ERROR_CODE).toString()) - } -} diff --git a/packages/Connectivity/tests/common/java/android/net/metrics/IpConnectivityLogTest.java b/packages/Connectivity/tests/common/java/android/net/metrics/IpConnectivityLogTest.java deleted file mode 100644 index d4780d3a5d7b4..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/metrics/IpConnectivityLogTest.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.metrics; - -import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; -import static android.net.NetworkCapabilities.TRANSPORT_WIFI; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.timeout; -import static org.mockito.Mockito.verify; - -import android.net.ConnectivityMetricsEvent; -import android.net.IIpConnectivityMetrics; -import android.net.Network; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.internal.util.BitUtils; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.Collections; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class IpConnectivityLogTest { - private static final int FAKE_NET_ID = 100; - private static final int[] FAKE_TRANSPORT_TYPES = BitUtils.unpackBits(TRANSPORT_WIFI); - private static final long FAKE_TIME_STAMP = System.currentTimeMillis(); - private static final String FAKE_INTERFACE_NAME = "test"; - private static final IpReachabilityEvent FAKE_EV = - new IpReachabilityEvent(IpReachabilityEvent.NUD_FAILED); - - @Mock IIpConnectivityMetrics mMockService; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - } - - @Test - public void testLoggingEvents() throws Exception { - IpConnectivityLog logger = new IpConnectivityLog(mMockService); - - assertTrue(logger.log(FAKE_EV)); - assertTrue(logger.log(FAKE_TIME_STAMP, FAKE_EV)); - assertTrue(logger.log(FAKE_NET_ID, FAKE_TRANSPORT_TYPES, FAKE_EV)); - assertTrue(logger.log(new Network(FAKE_NET_ID), FAKE_TRANSPORT_TYPES, FAKE_EV)); - assertTrue(logger.log(FAKE_INTERFACE_NAME, FAKE_EV)); - assertTrue(logger.log(makeExpectedEvent(FAKE_TIME_STAMP, FAKE_NET_ID, TRANSPORT_WIFI, - FAKE_INTERFACE_NAME))); - - List got = verifyEvents(6); - assertEventsEqual(makeExpectedEvent(got.get(0).timestamp, 0, 0, null), got.get(0)); - assertEventsEqual(makeExpectedEvent(FAKE_TIME_STAMP, 0, 0, null), got.get(1)); - assertEventsEqual(makeExpectedEvent(got.get(2).timestamp, FAKE_NET_ID, - TRANSPORT_WIFI, null), got.get(2)); - assertEventsEqual(makeExpectedEvent(got.get(3).timestamp, FAKE_NET_ID, - TRANSPORT_WIFI, null), got.get(3)); - assertEventsEqual(makeExpectedEvent(got.get(4).timestamp, 0, 0, FAKE_INTERFACE_NAME), - got.get(4)); - assertEventsEqual(makeExpectedEvent(FAKE_TIME_STAMP, FAKE_NET_ID, - TRANSPORT_WIFI, FAKE_INTERFACE_NAME), got.get(5)); - } - - @Test - public void testLoggingEventsWithMultipleCallers() throws Exception { - IpConnectivityLog logger = new IpConnectivityLog(mMockService); - - final int nCallers = 10; - final int nEvents = 10; - for (int n = 0; n < nCallers; n++) { - final int i = n; - new Thread() { - public void run() { - for (int j = 0; j < nEvents; j++) { - assertTrue(logger.log(makeExpectedEvent( - FAKE_TIME_STAMP + i * 100 + j, - FAKE_NET_ID + i * 100 + j, - ((i + j) % 2 == 0) ? TRANSPORT_WIFI : TRANSPORT_CELLULAR, - FAKE_INTERFACE_NAME))); - } - } - }.start(); - } - - List got = verifyEvents(nCallers * nEvents, 200); - Collections.sort(got, EVENT_COMPARATOR); - Iterator iter = got.iterator(); - for (int i = 0; i < nCallers; i++) { - for (int j = 0; j < nEvents; j++) { - final long expectedTimestamp = FAKE_TIME_STAMP + i * 100 + j; - final int expectedNetId = FAKE_NET_ID + i * 100 + j; - final long expectedTransports = - ((i + j) % 2 == 0) ? TRANSPORT_WIFI : TRANSPORT_CELLULAR; - assertEventsEqual(makeExpectedEvent(expectedTimestamp, expectedNetId, - expectedTransports, FAKE_INTERFACE_NAME), iter.next()); - } - } - } - - private List verifyEvents(int n, int timeoutMs) throws Exception { - ArgumentCaptor captor = - ArgumentCaptor.forClass(ConnectivityMetricsEvent.class); - verify(mMockService, timeout(timeoutMs).times(n)).logEvent(captor.capture()); - return captor.getAllValues(); - } - - private List verifyEvents(int n) throws Exception { - return verifyEvents(n, 10); - } - - - private ConnectivityMetricsEvent makeExpectedEvent(long timestamp, int netId, long transports, - String ifname) { - ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent(); - ev.timestamp = timestamp; - ev.data = FAKE_EV; - ev.netId = netId; - ev.transports = transports; - ev.ifname = ifname; - return ev; - } - - /** Outer equality for ConnectivityMetricsEvent to avoid overriding equals() and hashCode(). */ - private void assertEventsEqual(ConnectivityMetricsEvent expected, - ConnectivityMetricsEvent got) { - assertEquals(expected.data, got.data); - assertEquals(expected.timestamp, got.timestamp); - assertEquals(expected.netId, got.netId); - assertEquals(expected.transports, got.transports); - assertEquals(expected.ifname, got.ifname); - } - - static final Comparator EVENT_COMPARATOR = - Comparator.comparingLong((ev) -> ev.timestamp); -} diff --git a/packages/Connectivity/tests/common/java/android/net/metrics/IpManagerEventTest.kt b/packages/Connectivity/tests/common/java/android/net/metrics/IpManagerEventTest.kt deleted file mode 100644 index 64be50837fc92..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/metrics/IpManagerEventTest.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.metrics - -import androidx.test.filters.SmallTest -import androidx.test.runner.AndroidJUnit4 -import com.android.testutils.assertParcelSane -import org.junit.Assert.assertEquals -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -@SmallTest -class IpManagerEventTest { - @Test - fun testConstructorAndParcel() { - (IpManagerEvent.PROVISIONING_OK..IpManagerEvent.ERROR_INTERFACE_NOT_FOUND).forEach { - val ipManagerEvent = IpManagerEvent(it, Long.MAX_VALUE) - assertEquals(it, ipManagerEvent.eventType) - assertEquals(Long.MAX_VALUE, ipManagerEvent.durationMs) - - assertParcelSane(ipManagerEvent, 2) - } - } -} diff --git a/packages/Connectivity/tests/common/java/android/net/metrics/IpReachabilityEventTest.kt b/packages/Connectivity/tests/common/java/android/net/metrics/IpReachabilityEventTest.kt deleted file mode 100644 index 55b5e492dd473..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/metrics/IpReachabilityEventTest.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.metrics - -import androidx.test.filters.SmallTest -import androidx.test.runner.AndroidJUnit4 -import com.android.testutils.assertParcelSane -import org.junit.Assert.assertEquals -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -@SmallTest -class IpReachabilityEventTest { - @Test - fun testConstructorAndParcel() { - (IpReachabilityEvent.PROBE..IpReachabilityEvent.PROVISIONING_LOST_ORGANIC).forEach { - val ipReachabilityEvent = IpReachabilityEvent(it) - assertEquals(it, ipReachabilityEvent.eventType) - - assertParcelSane(ipReachabilityEvent, 1) - } - } -} diff --git a/packages/Connectivity/tests/common/java/android/net/metrics/NetworkEventTest.kt b/packages/Connectivity/tests/common/java/android/net/metrics/NetworkEventTest.kt deleted file mode 100644 index 41430b03a1eb7..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/metrics/NetworkEventTest.kt +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.metrics - -import androidx.test.filters.SmallTest -import androidx.test.runner.AndroidJUnit4 -import com.android.testutils.assertParcelSane -import org.junit.Assert.assertEquals -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -@SmallTest -class NetworkEventTest { - @Test - fun testConstructorAndParcel() { - (NetworkEvent.NETWORK_CONNECTED..NetworkEvent.NETWORK_PARTIAL_CONNECTIVITY).forEach { - var networkEvent = NetworkEvent(it) - assertEquals(it, networkEvent.eventType) - assertEquals(0, networkEvent.durationMs) - - networkEvent = NetworkEvent(it, Long.MAX_VALUE) - assertEquals(it, networkEvent.eventType) - assertEquals(Long.MAX_VALUE, networkEvent.durationMs) - - assertParcelSane(networkEvent, 2) - } - } -} diff --git a/packages/Connectivity/tests/common/java/android/net/metrics/RaEventTest.kt b/packages/Connectivity/tests/common/java/android/net/metrics/RaEventTest.kt deleted file mode 100644 index d9b720332fbe2..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/metrics/RaEventTest.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.metrics - -import androidx.test.filters.SmallTest -import androidx.test.runner.AndroidJUnit4 -import com.android.testutils.assertParcelSane -import org.junit.Assert.assertEquals -import org.junit.Test -import org.junit.runner.RunWith - -private const val NO_LIFETIME: Long = -1L - -@RunWith(AndroidJUnit4::class) -@SmallTest -class RaEventTest { - @Test - fun testConstructorAndParcel() { - var raEvent = RaEvent.Builder().build() - assertEquals(NO_LIFETIME, raEvent.routerLifetime) - assertEquals(NO_LIFETIME, raEvent.prefixValidLifetime) - assertEquals(NO_LIFETIME, raEvent.prefixPreferredLifetime) - assertEquals(NO_LIFETIME, raEvent.routeInfoLifetime) - assertEquals(NO_LIFETIME, raEvent.rdnssLifetime) - assertEquals(NO_LIFETIME, raEvent.dnsslLifetime) - - raEvent = RaEvent.Builder() - .updateRouterLifetime(1) - .updatePrefixValidLifetime(2) - .updatePrefixPreferredLifetime(3) - .updateRouteInfoLifetime(4) - .updateRdnssLifetime(5) - .updateDnsslLifetime(6) - .build() - assertEquals(1, raEvent.routerLifetime) - assertEquals(2, raEvent.prefixValidLifetime) - assertEquals(3, raEvent.prefixPreferredLifetime) - assertEquals(4, raEvent.routeInfoLifetime) - assertEquals(5, raEvent.rdnssLifetime) - assertEquals(6, raEvent.dnsslLifetime) - - raEvent = RaEvent.Builder() - .updateRouterLifetime(Long.MIN_VALUE) - .updateRouterLifetime(Long.MAX_VALUE) - .build() - assertEquals(Long.MIN_VALUE, raEvent.routerLifetime) - - raEvent = RaEvent(1, 2, 3, 4, 5, 6) - assertEquals(1, raEvent.routerLifetime) - assertEquals(2, raEvent.prefixValidLifetime) - assertEquals(3, raEvent.prefixPreferredLifetime) - assertEquals(4, raEvent.routeInfoLifetime) - assertEquals(5, raEvent.rdnssLifetime) - assertEquals(6, raEvent.dnsslLifetime) - - assertParcelSane(raEvent, 6) - } -} diff --git a/packages/Connectivity/tests/common/java/android/net/metrics/ValidationProbeEventTest.kt b/packages/Connectivity/tests/common/java/android/net/metrics/ValidationProbeEventTest.kt deleted file mode 100644 index 51c0d41bf4d5b..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/metrics/ValidationProbeEventTest.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.metrics - -import androidx.test.filters.SmallTest -import androidx.test.runner.AndroidJUnit4 -import com.android.testutils.assertParcelSane -import java.lang.reflect.Modifier -import org.junit.Assert.assertEquals -import org.junit.Assert.assertTrue -import org.junit.Test -import org.junit.runner.RunWith - -private const val FIRST_VALIDATION: Int = 1 shl 8 -private const val REVALIDATION: Int = 2 shl 8 - -@RunWith(AndroidJUnit4::class) -@SmallTest -class ValidationProbeEventTest { - private infix fun Int.hasType(type: Int) = (type and this) == type - - @Test - fun testBuilderAndParcel() { - var validationProbeEvent = ValidationProbeEvent.Builder() - .setProbeType(ValidationProbeEvent.PROBE_DNS, false).build() - - assertTrue(validationProbeEvent.probeType hasType REVALIDATION) - - validationProbeEvent = ValidationProbeEvent.Builder() - .setDurationMs(Long.MAX_VALUE) - .setProbeType(ValidationProbeEvent.PROBE_DNS, true) - .setReturnCode(ValidationProbeEvent.DNS_SUCCESS) - .build() - - assertEquals(Long.MAX_VALUE, validationProbeEvent.durationMs) - assertTrue(validationProbeEvent.probeType hasType ValidationProbeEvent.PROBE_DNS) - assertTrue(validationProbeEvent.probeType hasType FIRST_VALIDATION) - assertEquals(ValidationProbeEvent.DNS_SUCCESS, validationProbeEvent.returnCode) - - assertParcelSane(validationProbeEvent, 3) - } - - @Test - fun testGetProbeName() { - val probeFields = ValidationProbeEvent::class.java.declaredFields.filter { - it.type == Int::class.javaPrimitiveType - && Modifier.isPublic(it.modifiers) && Modifier.isStatic(it.modifiers) - && it.name.contains("PROBE") - } - - probeFields.forEach { - val intValue = it.getInt(null) - val stringValue = ValidationProbeEvent.getProbeName(intValue) - assertEquals(it.name, stringValue) - } - - } -} diff --git a/packages/Connectivity/tests/common/java/android/net/netstats/NetworkStatsApiTest.kt b/packages/Connectivity/tests/common/java/android/net/netstats/NetworkStatsApiTest.kt deleted file mode 100644 index 7b22e45db90ab..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/netstats/NetworkStatsApiTest.kt +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.netstats - -import android.net.NetworkStats -import android.net.NetworkStats.DEFAULT_NETWORK_NO -import android.net.NetworkStats.DEFAULT_NETWORK_YES -import android.net.NetworkStats.Entry -import android.net.NetworkStats.IFACE_VT -import android.net.NetworkStats.METERED_NO -import android.net.NetworkStats.METERED_YES -import android.net.NetworkStats.ROAMING_NO -import android.net.NetworkStats.ROAMING_YES -import android.net.NetworkStats.SET_DEFAULT -import android.net.NetworkStats.SET_FOREGROUND -import android.net.NetworkStats.TAG_NONE -import android.os.Build -import androidx.test.filters.SmallTest -import com.android.testutils.DevSdkIgnoreRule -import com.android.testutils.assertFieldCountEquals -import com.android.testutils.assertNetworkStatsEquals -import com.android.testutils.assertParcelingIsLossless -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith -import org.junit.runners.JUnit4 -import kotlin.test.assertEquals - -@RunWith(JUnit4::class) -@SmallTest -class NetworkStatsApiTest { - @Rule - @JvmField - val ignoreRule = DevSdkIgnoreRule(ignoreClassUpTo = Build.VERSION_CODES.Q) - - private val testStatsEmpty = NetworkStats(0L, 0) - - // Note that these variables need to be initialized outside of constructor, initialize - // here with methods that don't exist in Q devices will result in crash. - - // stats1 and stats2 will have some entries with common keys, which are expected to - // be merged if performing add on these 2 stats. - private lateinit var testStats1: NetworkStats - private lateinit var testStats2: NetworkStats - - // This is a result of adding stats1 and stats2, while the merging of common key items is - // subject to test later, this should not be initialized with for a loop to add stats1 - // and stats2 above. - private lateinit var testStats3: NetworkStats - - companion object { - private const val TEST_IFACE = "test0" - private const val TEST_UID1 = 1001 - private const val TEST_UID2 = 1002 - } - - @Before - fun setUp() { - testStats1 = NetworkStats(0L, 0) - // Entries which only appear in set1. - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 20, 3, 57, 40, 3)) - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_YES, DEFAULT_NETWORK_NO, 31, 7, 24, 5, 8)) - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, - METERED_YES, ROAMING_NO, DEFAULT_NETWORK_NO, 25, 3, 47, 8, 2)) - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_FOREGROUND, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 37, 52, 1, 10, 4)) - // Entries which are common for set1 and set2. - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 101, 2, 103, 4, 5)) - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, 0x80, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 17, 2, 11, 1, 0)) - .addEntry(Entry(TEST_IFACE, TEST_UID2, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 40, 1, 0, 0, 8)) - .addEntry(Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 3, 1, 6, 2, 0)) - assertEquals(8, testStats1.size()) - - testStats2 = NetworkStats(0L, 0) - // Entries which are common for set1 and set2. - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, 0x80, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 3, 15, 2, 31, 1)) - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_FOREGROUND, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 13, 61, 10, 1, 45)) - .addEntry(Entry(TEST_IFACE, TEST_UID2, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 11, 2, 3, 4, 7)) - .addEntry(Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 4, 3, 2, 1, 0)) - // Entry which only appears in set2. - .addEntry(Entry(IFACE_VT, TEST_UID2, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 2, 3, 7, 8, 0)) - assertEquals(5, testStats2.size()) - - testStats3 = NetworkStats(0L, 9) - // Entries which are unique either in stats1 or stats2. - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 101, 2, 103, 4, 5)) - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_YES, DEFAULT_NETWORK_NO, 31, 7, 24, 5, 8)) - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, - METERED_YES, ROAMING_NO, DEFAULT_NETWORK_NO, 25, 3, 47, 8, 2)) - .addEntry(Entry(IFACE_VT, TEST_UID2, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 2, 3, 7, 8, 0)) - // Entries which are common for stats1 and stats2 are being merged. - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 20, 3, 57, 40, 3)) - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, 0x80, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 20, 17, 13, 32, 1)) - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_FOREGROUND, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 50, 113, 11, 11, 49)) - .addEntry(Entry(TEST_IFACE, TEST_UID2, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 51, 3, 3, 4, 15)) - .addEntry(Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 7, 4, 8, 3, 0)) - assertEquals(9, testStats3.size()) - } - - @Test - fun testAddEntry() { - val expectedEntriesInStats2 = arrayOf( - Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, 0x80, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 3, 15, 2, 31, 1), - Entry(TEST_IFACE, TEST_UID1, SET_FOREGROUND, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 13, 61, 10, 1, 45), - Entry(TEST_IFACE, TEST_UID2, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 11, 2, 3, 4, 7), - Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 4, 3, 2, 1, 0), - Entry(IFACE_VT, TEST_UID2, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 2, 3, 7, 8, 0)) - - // While testStats* are already initialized with addEntry, verify content added - // matches expectation. - for (i in expectedEntriesInStats2.indices) { - val entry = testStats2.getValues(i, null) - assertEquals(expectedEntriesInStats2[i], entry) - } - - // Verify entry updated with addEntry. - val stats = testStats2.addEntry(Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 12, -5, 7, 0, 9)) - assertEquals(Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 16, -2, 9, 1, 9), - stats.getValues(3, null)) - } - - @Test - fun testAdd() { - var stats = NetworkStats(0L, 0) - assertNetworkStatsEquals(testStatsEmpty, stats) - stats = stats.add(testStats2) - assertNetworkStatsEquals(testStats2, stats) - stats = stats.add(testStats1) - // EMPTY + STATS2 + STATS1 = STATS3 - assertNetworkStatsEquals(testStats3, stats) - } - - @Test - fun testParcelUnparcel() { - assertParcelingIsLossless(testStatsEmpty) - assertParcelingIsLossless(testStats1) - assertParcelingIsLossless(testStats2) - assertFieldCountEquals(15, NetworkStats::class.java) - } - - @Test - fun testDescribeContents() { - assertEquals(0, testStatsEmpty.describeContents()) - assertEquals(0, testStats1.describeContents()) - assertEquals(0, testStats2.describeContents()) - assertEquals(0, testStats3.describeContents()) - } - - @Test - fun testSubtract() { - // STATS3 - STATS2 = STATS1 - assertNetworkStatsEquals(testStats1, testStats3.subtract(testStats2)) - // STATS3 - STATS1 = STATS2 - assertNetworkStatsEquals(testStats2, testStats3.subtract(testStats1)) - } - - @Test - fun testMethodsDontModifyReceiver() { - listOf(testStatsEmpty, testStats1, testStats2, testStats3).forEach { - val origStats = it.clone() - it.addEntry(Entry(TEST_IFACE, TEST_UID1, SET_FOREGROUND, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 13, 61, 10, 1, 45)) - it.add(testStats3) - it.subtract(testStats1) - assertNetworkStatsEquals(origStats, it) - } - } -} \ No newline at end of file diff --git a/packages/Connectivity/tests/common/java/android/net/util/SocketUtilsTest.kt b/packages/Connectivity/tests/common/java/android/net/util/SocketUtilsTest.kt deleted file mode 100644 index aaf97f36889b9..0000000000000 --- a/packages/Connectivity/tests/common/java/android/net/util/SocketUtilsTest.kt +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.util - -import android.os.Build -import android.system.NetlinkSocketAddress -import android.system.Os -import android.system.OsConstants.AF_INET -import android.system.OsConstants.ETH_P_ALL -import android.system.OsConstants.IPPROTO_UDP -import android.system.OsConstants.RTMGRP_NEIGH -import android.system.OsConstants.SOCK_DGRAM -import android.system.PacketSocketAddress -import androidx.test.filters.SmallTest -import androidx.test.runner.AndroidJUnit4 -import com.android.testutils.DevSdkIgnoreRule -import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo -import org.junit.Assert.assertEquals -import org.junit.Assert.assertFalse -import org.junit.Assert.assertTrue -import org.junit.Assert.fail -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith - -private const val TEST_INDEX = 123 -private const val TEST_PORT = 555 -private const val FF_BYTE = 0xff.toByte() - -@RunWith(AndroidJUnit4::class) -@SmallTest -class SocketUtilsTest { - @Rule @JvmField - val ignoreRule = DevSdkIgnoreRule() - - @Test - fun testMakeNetlinkSocketAddress() { - val nlAddress = SocketUtils.makeNetlinkSocketAddress(TEST_PORT, RTMGRP_NEIGH) - if (nlAddress is NetlinkSocketAddress) { - assertEquals(TEST_PORT, nlAddress.getPortId()) - assertEquals(RTMGRP_NEIGH, nlAddress.getGroupsMask()) - } else { - fail("Not NetlinkSocketAddress object") - } - } - - @Test - fun testMakePacketSocketAddress_Q() { - val pkAddress = SocketUtils.makePacketSocketAddress(ETH_P_ALL, TEST_INDEX) - assertTrue("Not PacketSocketAddress object", pkAddress is PacketSocketAddress) - - val pkAddress2 = SocketUtils.makePacketSocketAddress(TEST_INDEX, ByteArray(6) { FF_BYTE }) - assertTrue("Not PacketSocketAddress object", pkAddress2 is PacketSocketAddress) - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - fun testMakePacketSocketAddress() { - val pkAddress = SocketUtils.makePacketSocketAddress( - ETH_P_ALL, TEST_INDEX, ByteArray(6) { FF_BYTE }) - assertTrue("Not PacketSocketAddress object", pkAddress is PacketSocketAddress) - } - - @Test - fun testCloseSocket() { - // Expect no exception happening with null object. - SocketUtils.closeSocket(null) - - val fd = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP) - assertTrue(fd.valid()) - SocketUtils.closeSocket(fd) - assertFalse(fd.valid()) - // Expecting socket should be still invalid even closed socket again. - SocketUtils.closeSocket(fd) - assertFalse(fd.valid()) - } -} diff --git a/packages/Connectivity/tests/deflake/Android.bp b/packages/Connectivity/tests/deflake/Android.bp deleted file mode 100644 index 58ece37ef6477..0000000000000 --- a/packages/Connectivity/tests/deflake/Android.bp +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright (C) 2019 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_base_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_base_license"], -} - -java_test_host { - name: "FrameworksNetDeflakeTest", - srcs: ["src/**/*.kt"], - libs: [ - "junit", - "tradefed", - ], - static_libs: [ - "kotlin-test", - "net-host-tests-utils", - ], - data: [":FrameworksNetTests"], - test_suites: ["device-tests"], -} diff --git a/packages/Connectivity/tests/deflake/src/com/android/server/net/FrameworksNetDeflakeTest.kt b/packages/Connectivity/tests/deflake/src/com/android/server/net/FrameworksNetDeflakeTest.kt deleted file mode 100644 index 62855255fec25..0000000000000 --- a/packages/Connectivity/tests/deflake/src/com/android/server/net/FrameworksNetDeflakeTest.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.server.net - -import com.android.testutils.host.DeflakeHostTestBase -import com.android.tradefed.testtype.DeviceJUnit4ClassRunner -import org.junit.runner.RunWith - -@RunWith(DeviceJUnit4ClassRunner::class) -class FrameworksNetDeflakeTest: DeflakeHostTestBase() { - override val runCount = 20 - override val testApkFilename = "FrameworksNetTests.apk" - override val testClasses = listOf("com.android.server.ConnectivityServiceTest") -} \ No newline at end of file diff --git a/packages/Connectivity/tests/integration/Android.bp b/packages/Connectivity/tests/integration/Android.bp deleted file mode 100644 index 39c424e31f0eb..0000000000000 --- a/packages/Connectivity/tests/integration/Android.bp +++ /dev/null @@ -1,78 +0,0 @@ -// -// Copyright (C) 2019 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_base_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_base_license"], -} - -android_test { - name: "FrameworksNetIntegrationTests", - defaults: ["framework-connectivity-test-defaults"], - platform_apis: true, - certificate: "platform", - srcs: [ - "src/**/*.kt", - "src/**/*.aidl", - ], - libs: [ - "android.test.mock", - ], - static_libs: [ - "NetworkStackApiStableLib", - "androidx.test.ext.junit", - "frameworks-net-integration-testutils", - "kotlin-reflect", - "mockito-target-extended-minus-junit4", - "net-tests-utils", - "service-connectivity", - "services.core", - "services.net", - "testables", - ], - test_suites: ["device-tests"], - use_embedded_native_libs: true, - jni_libs: [ - // For mockito extended - "libdexmakerjvmtiagent", - "libstaticjvmtiagent", - // android_library does not include JNI libs: include NetworkStack dependencies here - "libnativehelper_compat_libc++", - "libnetworkstackutilsjni", - ], -} - -// Utilities for testing framework code both in integration and unit tests. -java_library { - name: "frameworks-net-integration-testutils", - defaults: ["framework-connectivity-test-defaults"], - srcs: ["util/**/*.java", "util/**/*.kt"], - static_libs: [ - "androidx.annotation_annotation", - "androidx.test.rules", - "junit", - "net-tests-utils", - ], - libs: [ - "service-connectivity", - "services.core", - "services.net", - ], -} diff --git a/packages/Connectivity/tests/integration/AndroidManifest.xml b/packages/Connectivity/tests/integration/AndroidManifest.xml deleted file mode 100644 index 2e1368935759b..0000000000000 --- a/packages/Connectivity/tests/integration/AndroidManifest.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/Connectivity/tests/integration/res/values/config.xml b/packages/Connectivity/tests/integration/res/values/config.xml deleted file mode 100644 index 2c8046ffd781a..0000000000000 --- a/packages/Connectivity/tests/integration/res/values/config.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - 12500 - http://test.android.com - https://secure.test.android.com - - http://fallback1.android.com - http://fallback2.android.com - - - - diff --git a/packages/Connectivity/tests/integration/src/android/net/TestNetworkStackClient.kt b/packages/Connectivity/tests/integration/src/android/net/TestNetworkStackClient.kt deleted file mode 100644 index 61ef5bdca4872..0000000000000 --- a/packages/Connectivity/tests/integration/src/android/net/TestNetworkStackClient.kt +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package android.net - -import android.content.ComponentName -import android.content.Context -import android.content.Intent -import android.net.networkstack.NetworkStackClientBase -import android.os.IBinder -import com.android.server.net.integrationtests.TestNetworkStackService -import org.mockito.Mockito.any -import org.mockito.Mockito.spy -import org.mockito.Mockito.timeout -import org.mockito.Mockito.verify -import kotlin.test.fail - -const val TEST_ACTION_SUFFIX = ".Test" - -class TestNetworkStackClient(private val context: Context) : NetworkStackClientBase() { - // TODO: consider switching to TrackRecord for more expressive checks - private val lastCallbacks = HashMap() - private val moduleConnector = ConnectivityModuleConnector { _, action, _, _ -> - val intent = Intent(action) - val serviceName = TestNetworkStackService::class.qualifiedName - ?: fail("TestNetworkStackService name not found") - intent.component = ComponentName(context.packageName, serviceName) - return@ConnectivityModuleConnector intent - }.also { it.init(context) } - - fun start() { - moduleConnector.startModuleService( - INetworkStackConnector::class.qualifiedName + TEST_ACTION_SUFFIX, - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) { connector -> - onNetworkStackConnected(INetworkStackConnector.Stub.asInterface(connector)) - } - } - - // base may be an instance of an inaccessible subclass, so non-spyable. - // Use a known open class that delegates to the original instance for all methods except - // asBinder. asBinder needs to use its own non-delegated implementation as otherwise it would - // return a binder token to a class that is not spied on. - open class NetworkMonitorCallbacksWrapper(private val base: INetworkMonitorCallbacks) : - INetworkMonitorCallbacks.Stub(), INetworkMonitorCallbacks by base { - // asBinder is implemented by both base class and delegate: specify explicitly - override fun asBinder(): IBinder { - return super.asBinder() - } - } - - override fun makeNetworkMonitor(network: Network, name: String?, cb: INetworkMonitorCallbacks) { - val cbSpy = spy(NetworkMonitorCallbacksWrapper(cb)) - lastCallbacks[network] = cbSpy - super.makeNetworkMonitor(network, name, cbSpy) - } - - fun verifyNetworkMonitorCreated(network: Network, timeoutMs: Long) { - val cb = lastCallbacks[network] - ?: fail("NetworkMonitor for network $network not requested") - verify(cb, timeout(timeoutMs)).onNetworkMonitorCreated(any()) - } -} \ No newline at end of file diff --git a/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt b/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt deleted file mode 100644 index e039ef0725426..0000000000000 --- a/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.server.net.integrationtests - -import android.app.usage.NetworkStatsManager -import android.content.ComponentName -import android.content.Context -import android.content.Context.BIND_AUTO_CREATE -import android.content.Context.BIND_IMPORTANT -import android.content.Intent -import android.content.ServiceConnection -import android.net.ConnectivityManager -import android.net.IDnsResolver -import android.net.INetd -import android.net.LinkProperties -import android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL -import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET -import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED -import android.net.NetworkCapabilities.TRANSPORT_CELLULAR -import android.net.NetworkRequest -import android.net.TestNetworkStackClient -import android.net.Uri -import android.net.metrics.IpConnectivityLog -import android.os.ConditionVariable -import android.os.IBinder -import android.os.SystemConfigManager -import android.os.UserHandle -import android.testing.TestableContext -import android.util.Log -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.ConnectivityService -import com.android.server.NetworkAgentWrapper -import com.android.server.TestNetIdManager -import com.android.server.connectivity.MockableSystemProperties -import com.android.server.connectivity.ProxyTracker -import com.android.testutils.TestableNetworkCallback -import org.junit.After -import org.junit.Before -import org.junit.BeforeClass -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.AdditionalAnswers -import org.mockito.ArgumentMatchers.anyString -import org.mockito.Mock -import org.mockito.Mockito.any -import org.mockito.Mockito.anyInt -import org.mockito.Mockito.doNothing -import org.mockito.Mockito.doReturn -import org.mockito.Mockito.eq -import org.mockito.Mockito.mock -import org.mockito.Mockito.spy -import org.mockito.MockitoAnnotations -import org.mockito.Spy -import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertNotNull -import kotlin.test.assertTrue -import kotlin.test.fail - -const val SERVICE_BIND_TIMEOUT_MS = 5_000L -const val TEST_TIMEOUT_MS = 10_000L - -/** - * Test that exercises an instrumented version of ConnectivityService against an instrumented - * NetworkStack in a different test process. - */ -@RunWith(AndroidJUnit4::class) -class ConnectivityServiceIntegrationTest { - // lateinit used here for mocks as they need to be reinitialized between each test and the test - // should crash if they are used before being initialized. - @Mock - private lateinit var statsManager: NetworkStatsManager - @Mock - private lateinit var log: IpConnectivityLog - @Mock - private lateinit var netd: INetd - @Mock - private lateinit var dnsResolver: IDnsResolver - @Mock - private lateinit var systemConfigManager: SystemConfigManager - @Spy - private var context = TestableContext(realContext) - - // lateinit for these three classes under test, as they should be reset to a different instance - // for every test but should always be initialized before use (or the test should crash). - private lateinit var networkStackClient: TestNetworkStackClient - private lateinit var service: ConnectivityService - private lateinit var cm: ConnectivityManager - - companion object { - // lateinit for this binder token, as it must be initialized before any test code is run - // and use of it before init should crash the test. - private lateinit var nsInstrumentation: INetworkStackInstrumentation - private val bindingCondition = ConditionVariable(false) - - private val realContext get() = InstrumentationRegistry.getInstrumentation().context - private val httpProbeUrl get() = - realContext.getResources().getString(R.string.config_captive_portal_http_url) - private val httpsProbeUrl get() = - realContext.getResources().getString(R.string.config_captive_portal_https_url) - - private class InstrumentationServiceConnection : ServiceConnection { - override fun onServiceConnected(name: ComponentName?, service: IBinder?) { - Log.i("TestNetworkStack", "Service connected") - try { - if (service == null) fail("Error binding to NetworkStack instrumentation") - if (::nsInstrumentation.isInitialized) fail("Service already connected") - nsInstrumentation = INetworkStackInstrumentation.Stub.asInterface(service) - } finally { - bindingCondition.open() - } - } - - override fun onServiceDisconnected(name: ComponentName?) = Unit - } - - @BeforeClass - @JvmStatic - fun setUpClass() { - val intent = Intent(realContext, NetworkStackInstrumentationService::class.java) - intent.action = INetworkStackInstrumentation::class.qualifiedName - assertTrue(realContext.bindService(intent, InstrumentationServiceConnection(), - BIND_AUTO_CREATE or BIND_IMPORTANT), - "Error binding to instrumentation service") - assertTrue(bindingCondition.block(SERVICE_BIND_TIMEOUT_MS), - "Timed out binding to instrumentation service " + - "after $SERVICE_BIND_TIMEOUT_MS ms") - } - } - - @Before - fun setUp() { - MockitoAnnotations.initMocks(this) - val asUserCtx = mock(Context::class.java, AdditionalAnswers.delegatesTo(context)) - doReturn(UserHandle.ALL).`when`(asUserCtx).user - doReturn(asUserCtx).`when`(context).createContextAsUser(eq(UserHandle.ALL), anyInt()) - doNothing().`when`(context).sendStickyBroadcast(any(), any()) - doReturn(Context.SYSTEM_CONFIG_SERVICE).`when`(context) - .getSystemServiceName(SystemConfigManager::class.java) - doReturn(systemConfigManager).`when`(context) - .getSystemService(Context.SYSTEM_CONFIG_SERVICE) - doReturn(IntArray(0)).`when`(systemConfigManager).getSystemPermissionUids(anyString()) - - networkStackClient = TestNetworkStackClient(realContext) - networkStackClient.start() - - service = TestConnectivityService(makeDependencies()) - cm = ConnectivityManager(context, service) - context.addMockSystemService(Context.CONNECTIVITY_SERVICE, cm) - context.addMockSystemService(Context.NETWORK_STATS_SERVICE, statsManager) - - service.systemReadyInternal() - } - - private inner class TestConnectivityService(deps: Dependencies) : ConnectivityService( - context, dnsResolver, log, netd, deps) - - private fun makeDependencies(): ConnectivityService.Dependencies { - val deps = spy(ConnectivityService.Dependencies()) - doReturn(networkStackClient).`when`(deps).networkStack - doReturn(mock(ProxyTracker::class.java)).`when`(deps).makeProxyTracker(any(), any()) - doReturn(mock(MockableSystemProperties::class.java)).`when`(deps).systemProperties - doReturn(TestNetIdManager()).`when`(deps).makeNetIdManager() - return deps - } - - @After - fun tearDown() { - nsInstrumentation.clearAllState() - } - - @Test - fun testValidation() { - val request = NetworkRequest.Builder() - .clearCapabilities() - .addCapability(NET_CAPABILITY_INTERNET) - .build() - val testCallback = TestableNetworkCallback() - - cm.registerNetworkCallback(request, testCallback) - nsInstrumentation.addHttpResponse(HttpResponse(httpProbeUrl, responseCode = 204)) - nsInstrumentation.addHttpResponse(HttpResponse(httpsProbeUrl, responseCode = 204)) - - val na = NetworkAgentWrapper(TRANSPORT_CELLULAR, LinkProperties(), null /* ncTemplate */, - context) - networkStackClient.verifyNetworkMonitorCreated(na.network, TEST_TIMEOUT_MS) - - na.addCapability(NET_CAPABILITY_INTERNET) - na.connect() - - testCallback.expectAvailableThenValidatedCallbacks(na.network, TEST_TIMEOUT_MS) - assertEquals(2, nsInstrumentation.getRequestUrls().size) - } - - @Test - fun testCapportApi() { - val request = NetworkRequest.Builder() - .clearCapabilities() - .addCapability(NET_CAPABILITY_INTERNET) - .build() - val testCb = TestableNetworkCallback() - val apiUrl = "https://capport.android.com" - - cm.registerNetworkCallback(request, testCb) - nsInstrumentation.addHttpResponse(HttpResponse( - apiUrl, - """ - |{ - | "captive": true, - | "user-portal-url": "https://login.capport.android.com", - | "venue-info-url": "https://venueinfo.capport.android.com" - |} - """.trimMargin())) - - // Tests will fail if a non-mocked query is received: mock the HTTPS probe, but not the - // HTTP probe as it should not be sent. - // Even if the HTTPS probe succeeds, a portal should be detected as the API takes precedence - // in that case. - nsInstrumentation.addHttpResponse(HttpResponse(httpsProbeUrl, responseCode = 204)) - - val lp = LinkProperties() - lp.captivePortalApiUrl = Uri.parse(apiUrl) - val na = NetworkAgentWrapper(TRANSPORT_CELLULAR, lp, null /* ncTemplate */, context) - networkStackClient.verifyNetworkMonitorCreated(na.network, TEST_TIMEOUT_MS) - - na.addCapability(NET_CAPABILITY_INTERNET) - na.connect() - - testCb.expectAvailableCallbacks(na.network, validated = false, tmt = TEST_TIMEOUT_MS) - - val capportData = testCb.expectLinkPropertiesThat(na, TEST_TIMEOUT_MS) { - it.captivePortalData != null - }.lp.captivePortalData - assertNotNull(capportData) - assertTrue(capportData.isCaptive) - assertEquals(Uri.parse("https://login.capport.android.com"), capportData.userPortalUrl) - assertEquals(Uri.parse("https://venueinfo.capport.android.com"), capportData.venueInfoUrl) - - val nc = testCb.expectCapabilitiesWith(NET_CAPABILITY_CAPTIVE_PORTAL, na, TEST_TIMEOUT_MS) - assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED)) - } -} \ No newline at end of file diff --git a/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/HttpResponse.aidl b/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/HttpResponse.aidl deleted file mode 100644 index 9a2bcfea7641b..0000000000000 --- a/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/HttpResponse.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.server.net.integrationtests; - -parcelable HttpResponse; \ No newline at end of file diff --git a/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/HttpResponse.kt b/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/HttpResponse.kt deleted file mode 100644 index e2063138fef1b..0000000000000 --- a/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/HttpResponse.kt +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.server.net.integrationtests - -import android.os.Parcel -import android.os.Parcelable - -data class HttpResponse( - val requestUrl: String, - val responseCode: Int, - val content: String = "", - val redirectUrl: String? = null -) : Parcelable { - constructor(p: Parcel): this(p.readString(), p.readInt(), p.readString(), p.readString()) - constructor(requestUrl: String, contentBody: String): this( - requestUrl, - responseCode = 200, - content = contentBody, - redirectUrl = null) - - override fun writeToParcel(dest: Parcel, flags: Int) { - with(dest) { - writeString(requestUrl) - writeInt(responseCode) - writeString(content) - writeString(redirectUrl) - } - } - - override fun describeContents() = 0 - companion object CREATOR : Parcelable.Creator { - override fun createFromParcel(source: Parcel) = HttpResponse(source) - override fun newArray(size: Int) = arrayOfNulls(size) - } -} \ No newline at end of file diff --git a/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/INetworkStackInstrumentation.aidl b/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/INetworkStackInstrumentation.aidl deleted file mode 100644 index efc58add9cf50..0000000000000 --- a/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/INetworkStackInstrumentation.aidl +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.server.net.integrationtests; - -import com.android.server.net.integrationtests.HttpResponse; - -interface INetworkStackInstrumentation { - void clearAllState(); - void addHttpResponse(in HttpResponse response); - List getRequestUrls(); -} \ No newline at end of file diff --git a/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/NetworkStackInstrumentationService.kt b/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/NetworkStackInstrumentationService.kt deleted file mode 100644 index e807952cec11d..0000000000000 --- a/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/NetworkStackInstrumentationService.kt +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.server.net.integrationtests - -import android.app.Service -import android.content.Intent -import java.net.URL -import java.util.Collections -import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.ConcurrentLinkedQueue -import kotlin.collections.ArrayList -import kotlin.test.fail - -/** - * An instrumentation interface for the NetworkStack that allows controlling behavior to - * facilitate integration tests. - */ -class NetworkStackInstrumentationService : Service() { - override fun onBind(intent: Intent) = InstrumentationConnector.asBinder() - - object InstrumentationConnector : INetworkStackInstrumentation.Stub() { - private val httpResponses = ConcurrentHashMap>() - .run { - withDefault { key -> getOrPut(key) { ConcurrentLinkedQueue() } } - } - private val httpRequestUrls = Collections.synchronizedList(ArrayList()) - - /** - * Called when an HTTP request is being processed by NetworkMonitor. Returns the response - * that should be simulated. - */ - fun processRequest(url: URL): HttpResponse { - val strUrl = url.toString() - httpRequestUrls.add(strUrl) - return httpResponses[strUrl]?.poll() - ?: fail("No mocked response for request: $strUrl. " + - "Mocked URL keys are: ${httpResponses.keys}") - } - - /** - * Clear all state of this connector. This is intended for use between two tests, so all - * state should be reset as if the connector was just created. - */ - override fun clearAllState() { - httpResponses.clear() - httpRequestUrls.clear() - } - - /** - * Add a response to a future HTTP request. - * - *

      For any subsequent HTTP/HTTPS query, the first response with a matching URL will be - * used to mock the query response. - * - *

      All requests that are expected to be sent must have a mock response: if an unexpected - * request is seen, the test will fail. - */ - override fun addHttpResponse(response: HttpResponse) { - httpResponses.getValue(response.requestUrl).add(response) - } - - /** - * Get the ordered list of request URLs that have been sent by NetworkMonitor, and were - * answered based on mock responses. - */ - override fun getRequestUrls(): List { - return ArrayList(httpRequestUrls) - } - } -} \ No newline at end of file diff --git a/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt b/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt deleted file mode 100644 index eff66584d6c1b..0000000000000 --- a/packages/Connectivity/tests/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.server.net.integrationtests - -import android.app.Service -import android.content.Context -import android.content.Intent -import android.net.INetworkMonitorCallbacks -import android.net.Network -import android.net.metrics.IpConnectivityLog -import android.net.util.SharedLog -import android.os.IBinder -import com.android.networkstack.netlink.TcpSocketTracker -import com.android.server.NetworkStackService -import com.android.server.NetworkStackService.NetworkMonitorConnector -import com.android.server.NetworkStackService.NetworkStackConnector -import com.android.server.connectivity.NetworkMonitor -import com.android.server.net.integrationtests.NetworkStackInstrumentationService.InstrumentationConnector -import org.mockito.Mockito.doReturn -import org.mockito.Mockito.mock -import org.mockito.Mockito.spy -import java.io.ByteArrayInputStream -import java.net.HttpURLConnection -import java.net.URL -import java.net.URLConnection -import java.nio.charset.StandardCharsets - -private const val TEST_NETID = 42 - -/** - * Android service that can return an [android.net.INetworkStackConnector] which can be instrumented - * through [NetworkStackInstrumentationService]. - * Useful in tests to create test instrumented NetworkStack components that can receive - * instrumentation commands through [NetworkStackInstrumentationService]. - */ -class TestNetworkStackService : Service() { - override fun onBind(intent: Intent): IBinder = TestNetworkStackConnector(makeTestContext()) - - private fun makeTestContext() = spy(applicationContext).also { - doReturn(mock(IBinder::class.java)).`when`(it).getSystemService(Context.NETD_SERVICE) - } - - private class TestPermissionChecker : NetworkStackService.PermissionChecker() { - override fun enforceNetworkStackCallingPermission() = Unit - } - - private class NetworkMonitorDeps(private val privateDnsBypassNetwork: Network) : - NetworkMonitor.Dependencies() { - override fun getPrivateDnsBypassNetwork(network: Network?) = privateDnsBypassNetwork - } - - private inner class TestNetworkStackConnector(context: Context) : NetworkStackConnector( - context, TestPermissionChecker(), NetworkStackService.Dependencies()) { - - private val network = Network(TEST_NETID) - private val privateDnsBypassNetwork = TestNetwork(TEST_NETID) - - private inner class TestNetwork(netId: Int) : Network(netId) { - override fun openConnection(url: URL): URLConnection { - val response = InstrumentationConnector.processRequest(url) - val responseBytes = response.content.toByteArray(StandardCharsets.UTF_8) - - val connection = mock(HttpURLConnection::class.java) - doReturn(response.responseCode).`when`(connection).responseCode - doReturn(responseBytes.size.toLong()).`when`(connection).contentLengthLong - doReturn(response.redirectUrl).`when`(connection).getHeaderField("location") - doReturn(ByteArrayInputStream(responseBytes)).`when`(connection).inputStream - return connection - } - } - - override fun makeNetworkMonitor( - network: Network, - name: String?, - cb: INetworkMonitorCallbacks - ) { - val nm = NetworkMonitor(this@TestNetworkStackService, cb, - this.network, - mock(IpConnectivityLog::class.java), mock(SharedLog::class.java), - mock(NetworkStackService.NetworkStackServiceManager::class.java), - NetworkMonitorDeps(privateDnsBypassNetwork), - mock(TcpSocketTracker::class.java)) - cb.onNetworkMonitorCreated(NetworkMonitorConnector(nm, TestPermissionChecker())) - } - } -} diff --git a/packages/Connectivity/tests/integration/util/com/android/server/ConnectivityServiceTestUtils.kt b/packages/Connectivity/tests/integration/util/com/android/server/ConnectivityServiceTestUtils.kt deleted file mode 100644 index 165fd3728281f..0000000000000 --- a/packages/Connectivity/tests/integration/util/com/android/server/ConnectivityServiceTestUtils.kt +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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 - */ - -@file:JvmName("ConnectivityServiceTestUtils") - -package com.android.server - -import android.net.ConnectivityManager.TYPE_BLUETOOTH -import android.net.ConnectivityManager.TYPE_ETHERNET -import android.net.ConnectivityManager.TYPE_MOBILE -import android.net.ConnectivityManager.TYPE_NONE -import android.net.ConnectivityManager.TYPE_TEST -import android.net.ConnectivityManager.TYPE_VPN -import android.net.ConnectivityManager.TYPE_WIFI -import android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH -import android.net.NetworkCapabilities.TRANSPORT_CELLULAR -import android.net.NetworkCapabilities.TRANSPORT_ETHERNET -import android.net.NetworkCapabilities.TRANSPORT_TEST -import android.net.NetworkCapabilities.TRANSPORT_VPN -import android.net.NetworkCapabilities.TRANSPORT_WIFI - -fun transportToLegacyType(transport: Int) = when (transport) { - TRANSPORT_BLUETOOTH -> TYPE_BLUETOOTH - TRANSPORT_CELLULAR -> TYPE_MOBILE - TRANSPORT_ETHERNET -> TYPE_ETHERNET - TRANSPORT_TEST -> TYPE_TEST - TRANSPORT_VPN -> TYPE_VPN - TRANSPORT_WIFI -> TYPE_WIFI - else -> TYPE_NONE -} \ No newline at end of file diff --git a/packages/Connectivity/tests/integration/util/com/android/server/NetworkAgentWrapper.java b/packages/Connectivity/tests/integration/util/com/android/server/NetworkAgentWrapper.java deleted file mode 100644 index 17db17923f4d8..0000000000000 --- a/packages/Connectivity/tests/integration/util/com/android/server/NetworkAgentWrapper.java +++ /dev/null @@ -1,388 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server; - -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_NOT_VPN; -import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; -import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET; -import static android.net.NetworkCapabilities.TRANSPORT_VPN; -import static android.net.NetworkCapabilities.TRANSPORT_WIFI; -import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE; - -import static com.android.server.ConnectivityServiceTestUtils.transportToLegacyType; - -import static junit.framework.Assert.assertTrue; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import android.annotation.NonNull; -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.LinkProperties; -import android.net.Network; -import android.net.NetworkAgent; -import android.net.NetworkAgentConfig; -import android.net.NetworkCapabilities; -import android.net.NetworkProvider; -import android.net.NetworkScore; -import android.net.NetworkSpecifier; -import android.net.QosFilter; -import android.net.SocketKeepalive; -import android.os.ConditionVariable; -import android.os.HandlerThread; -import android.os.Message; -import android.util.Log; -import android.util.Range; - -import com.android.net.module.util.ArrayTrackRecord; -import com.android.testutils.HandlerUtils; -import com.android.testutils.TestableNetworkCallback; - -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; - -public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { - private final NetworkCapabilities mNetworkCapabilities; - private final HandlerThread mHandlerThread; - private final Context mContext; - private final String mLogTag; - private final NetworkAgentConfig mNetworkAgentConfig; - - private final ConditionVariable mDisconnected = new ConditionVariable(); - private final ConditionVariable mPreventReconnectReceived = new ConditionVariable(); - private final AtomicBoolean mConnected = new AtomicBoolean(false); - private NetworkScore mScore; - private NetworkAgent mNetworkAgent; - private int mStartKeepaliveError = SocketKeepalive.ERROR_UNSUPPORTED; - private int mStopKeepaliveError = SocketKeepalive.NO_KEEPALIVE; - // Controls how test network agent is going to wait before responding to keepalive - // start/stop. Useful when simulate KeepaliveTracker is waiting for response from modem. - private long mKeepaliveResponseDelay = 0L; - private Integer mExpectedKeepaliveSlot = null; - private final ArrayTrackRecord.ReadHead mCallbackHistory = - new ArrayTrackRecord().newReadHead(); - - public NetworkAgentWrapper(int transport, LinkProperties linkProperties, - NetworkCapabilities ncTemplate, Context context) throws Exception { - final int type = transportToLegacyType(transport); - final String typeName = ConnectivityManager.getNetworkTypeName(type); - mNetworkCapabilities = (ncTemplate != null) ? ncTemplate : new NetworkCapabilities(); - mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_SUSPENDED); - mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); - mNetworkCapabilities.addTransportType(transport); - switch (transport) { - case TRANSPORT_ETHERNET: - mScore = new NetworkScore.Builder().setLegacyInt(70).build(); - break; - case TRANSPORT_WIFI: - mScore = new NetworkScore.Builder().setLegacyInt(60).build(); - break; - case TRANSPORT_CELLULAR: - mScore = new NetworkScore.Builder().setLegacyInt(50).build(); - break; - case TRANSPORT_WIFI_AWARE: - mScore = new NetworkScore.Builder().setLegacyInt(20).build(); - break; - case TRANSPORT_VPN: - mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_VPN); - // VPNs deduce the SUSPENDED capability from their underlying networks and there - // is no public API to let VPN services set it. - mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_SUSPENDED); - mScore = new NetworkScore.Builder().setLegacyInt(101).build(); - break; - default: - throw new UnsupportedOperationException("unimplemented network type"); - } - mContext = context; - mLogTag = "Mock-" + typeName; - mHandlerThread = new HandlerThread(mLogTag); - mHandlerThread.start(); - - // extraInfo is set to "" by default in NetworkAgentConfig. - final String extraInfo = (transport == TRANSPORT_CELLULAR) ? "internet.apn" : ""; - mNetworkAgentConfig = new NetworkAgentConfig.Builder() - .setLegacyType(type) - .setLegacyTypeName(typeName) - .setLegacyExtraInfo(extraInfo) - .build(); - mNetworkAgent = makeNetworkAgent(linkProperties, mNetworkAgentConfig); - } - - protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties, - final NetworkAgentConfig nac) throws Exception { - return new InstrumentedNetworkAgent(this, linkProperties, nac); - } - - public static class InstrumentedNetworkAgent extends NetworkAgent { - private final NetworkAgentWrapper mWrapper; - private static final String PROVIDER_NAME = "InstrumentedNetworkAgentProvider"; - - public InstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp, - NetworkAgentConfig nac) { - super(wrapper.mContext, wrapper.mHandlerThread.getLooper(), wrapper.mLogTag, - wrapper.mNetworkCapabilities, lp, wrapper.mScore, nac, - new NetworkProvider(wrapper.mContext, wrapper.mHandlerThread.getLooper(), - PROVIDER_NAME)); - mWrapper = wrapper; - register(); - } - - @Override - public void unwanted() { - mWrapper.mDisconnected.open(); - } - - @Override - public void startSocketKeepalive(Message msg) { - int slot = msg.arg1; - if (mWrapper.mExpectedKeepaliveSlot != null) { - assertEquals((int) mWrapper.mExpectedKeepaliveSlot, slot); - } - mWrapper.mHandlerThread.getThreadHandler().postDelayed( - () -> onSocketKeepaliveEvent(slot, mWrapper.mStartKeepaliveError), - mWrapper.mKeepaliveResponseDelay); - } - - @Override - public void stopSocketKeepalive(Message msg) { - final int slot = msg.arg1; - mWrapper.mHandlerThread.getThreadHandler().postDelayed( - () -> onSocketKeepaliveEvent(slot, mWrapper.mStopKeepaliveError), - mWrapper.mKeepaliveResponseDelay); - } - - @Override - public void onQosCallbackRegistered(final int qosCallbackId, - final @NonNull QosFilter filter) { - Log.i(mWrapper.mLogTag, "onQosCallbackRegistered"); - mWrapper.mCallbackHistory.add( - new CallbackType.OnQosCallbackRegister(qosCallbackId, filter)); - } - - @Override - public void onQosCallbackUnregistered(final int qosCallbackId) { - Log.i(mWrapper.mLogTag, "onQosCallbackUnregistered"); - mWrapper.mCallbackHistory.add(new CallbackType.OnQosCallbackUnregister(qosCallbackId)); - } - - @Override - protected void preventAutomaticReconnect() { - mWrapper.mPreventReconnectReceived.open(); - } - - @Override - protected void addKeepalivePacketFilter(Message msg) { - Log.i(mWrapper.mLogTag, "Add keepalive packet filter."); - } - - @Override - protected void removeKeepalivePacketFilter(Message msg) { - Log.i(mWrapper.mLogTag, "Remove keepalive packet filter."); - } - } - - public void setScore(@NonNull final NetworkScore score) { - mScore = score; - mNetworkAgent.sendNetworkScore(score); - } - - public void adjustScore(int change) { - final int newLegacyScore = mScore.getLegacyInt() + change; - final NetworkScore.Builder builder = new NetworkScore.Builder() - .setLegacyInt(newLegacyScore); - if (mNetworkCapabilities.hasTransport(TRANSPORT_WIFI) && newLegacyScore < 50) { - builder.setExiting(true); - } - mScore = builder.build(); - mNetworkAgent.sendNetworkScore(mScore); - } - - public NetworkScore getScore() { - return mScore; - } - - public void explicitlySelected(boolean explicitlySelected, boolean acceptUnvalidated) { - mNetworkAgent.explicitlySelected(explicitlySelected, acceptUnvalidated); - } - - public void addCapability(int capability) { - mNetworkCapabilities.addCapability(capability); - mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); - } - - public void removeCapability(int capability) { - mNetworkCapabilities.removeCapability(capability); - mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); - } - - public void setUids(Set> uids) { - mNetworkCapabilities.setUids(uids); - mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); - } - - public void setSignalStrength(int signalStrength) { - mNetworkCapabilities.setSignalStrength(signalStrength); - mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); - } - - public void setNetworkSpecifier(NetworkSpecifier networkSpecifier) { - mNetworkCapabilities.setNetworkSpecifier(networkSpecifier); - mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); - } - - public void setNetworkCapabilities(NetworkCapabilities nc, boolean sendToConnectivityService) { - mNetworkCapabilities.set(nc); - if (sendToConnectivityService) { - mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); - } - } - - public void connect() { - if (!mConnected.compareAndSet(false /* expect */, true /* update */)) { - // compareAndSet returns false when the value couldn't be updated because it did not - // match the expected value. - fail("Test NetworkAgents can only be connected once"); - } - mNetworkAgent.markConnected(); - } - - public void suspend() { - removeCapability(NET_CAPABILITY_NOT_SUSPENDED); - } - - public void resume() { - addCapability(NET_CAPABILITY_NOT_SUSPENDED); - } - - public void disconnect() { - mNetworkAgent.unregister(); - } - - @Override - public Network getNetwork() { - return mNetworkAgent.getNetwork(); - } - - public void expectPreventReconnectReceived(long timeoutMs) { - assertTrue(mPreventReconnectReceived.block(timeoutMs)); - } - - public void expectDisconnected(long timeoutMs) { - assertTrue(mDisconnected.block(timeoutMs)); - } - - public void sendLinkProperties(LinkProperties lp) { - mNetworkAgent.sendLinkProperties(lp); - } - - public void setStartKeepaliveEvent(int reason) { - mStartKeepaliveError = reason; - } - - public void setStopKeepaliveEvent(int reason) { - mStopKeepaliveError = reason; - } - - public void setKeepaliveResponseDelay(long delay) { - mKeepaliveResponseDelay = delay; - } - - public void setExpectedKeepaliveSlot(Integer slot) { - mExpectedKeepaliveSlot = slot; - } - - public NetworkAgent getNetworkAgent() { - return mNetworkAgent; - } - - public NetworkCapabilities getNetworkCapabilities() { - return mNetworkCapabilities; - } - - public int getLegacyType() { - return mNetworkAgentConfig.getLegacyType(); - } - - public String getExtraInfo() { - return mNetworkAgentConfig.getLegacyExtraInfo(); - } - - public @NonNull ArrayTrackRecord.ReadHead getCallbackHistory() { - return mCallbackHistory; - } - - public void waitForIdle(long timeoutMs) { - HandlerUtils.waitForIdle(mHandlerThread, timeoutMs); - } - - abstract static class CallbackType { - final int mQosCallbackId; - - protected CallbackType(final int qosCallbackId) { - mQosCallbackId = qosCallbackId; - } - - static class OnQosCallbackRegister extends CallbackType { - final QosFilter mFilter; - OnQosCallbackRegister(final int qosCallbackId, final QosFilter filter) { - super(qosCallbackId); - mFilter = filter; - } - - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - final OnQosCallbackRegister that = (OnQosCallbackRegister) o; - return mQosCallbackId == that.mQosCallbackId - && Objects.equals(mFilter, that.mFilter); - } - - @Override - public int hashCode() { - return Objects.hash(mQosCallbackId, mFilter); - } - } - - static class OnQosCallbackUnregister extends CallbackType { - OnQosCallbackUnregister(final int qosCallbackId) { - super(qosCallbackId); - } - - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - final OnQosCallbackUnregister that = (OnQosCallbackUnregister) o; - return mQosCallbackId == that.mQosCallbackId; - } - - @Override - public int hashCode() { - return Objects.hash(mQosCallbackId); - } - } - } - - public boolean isBypassableVpn() { - return mNetworkAgentConfig.isBypassableVpn(); - } -} diff --git a/packages/Connectivity/tests/integration/util/com/android/server/TestNetIdManager.kt b/packages/Connectivity/tests/integration/util/com/android/server/TestNetIdManager.kt deleted file mode 100644 index 938a694e8ba98..0000000000000 --- a/packages/Connectivity/tests/integration/util/com/android/server/TestNetIdManager.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.server - -import java.util.concurrent.atomic.AtomicInteger - -/** - * A [NetIdManager] that generates ID starting from [NetIdManager.MAX_NET_ID] and decreasing, rather - * than starting from [NetIdManager.MIN_NET_ID] and increasing. - * - * Useful for testing ConnectivityService, to minimize the risk of test ConnectivityService netIDs - * overlapping with netIDs used by the real ConnectivityService on the device. - * - * IDs may still overlap if many networks have been used on the device (so the "real" netIDs - * are close to MAX_NET_ID), but this is typically not the case when running unit tests. Also, there - * is no way to fully solve the overlap issue without altering ID allocation in non-test code, as - * the real ConnectivityService could start using netIds that have been used by the test in the - * past. - */ -class TestNetIdManager : NetIdManager() { - private val nextId = AtomicInteger(MAX_NET_ID) - override fun reserveNetId() = nextId.decrementAndGet() - override fun releaseNetId(id: Int) = Unit - fun peekNextNetId() = nextId.get() - 1 -} diff --git a/packages/Connectivity/tests/smoketest/Android.bp b/packages/Connectivity/tests/smoketest/Android.bp deleted file mode 100644 index 1535f3ddcb385..0000000000000 --- a/packages/Connectivity/tests/smoketest/Android.bp +++ /dev/null @@ -1,31 +0,0 @@ -// This test exists only because the jni_libs list for these tests is difficult to -// maintain: the test itself only depends on libnetworkstatsfactorytestjni, but the test -// fails to load that library unless *all* the dependencies of that library are explicitly -// listed in jni_libs. This means that whenever any of the dependencies changes the test -// starts failing and breaking presubmits in frameworks/base. We cannot easily put -// FrameworksNetTests into global presubmit because they are at times flaky, but this -// test is effectively empty beyond validating that the libraries load correctly, and -// thus should be stable enough to put in global presubmit. -// -// TODO: remove this hack when there is a better solution for jni_libs that includes -// dependent libraries. -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_base_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_base_license"], -} - -android_test { - name: "FrameworksNetSmokeTests", - defaults: ["FrameworksNetTests-jni-defaults"], - srcs: ["java/SmokeTest.java"], - test_suites: ["device-tests"], - static_libs: [ - "androidx.test.rules", - "mockito-target-minus-junit4", - "services.core", - ], -} diff --git a/packages/Connectivity/tests/smoketest/AndroidManifest.xml b/packages/Connectivity/tests/smoketest/AndroidManifest.xml deleted file mode 100644 index f1b9febb9f578..0000000000000 --- a/packages/Connectivity/tests/smoketest/AndroidManifest.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - diff --git a/packages/Connectivity/tests/smoketest/AndroidTest.xml b/packages/Connectivity/tests/smoketest/AndroidTest.xml deleted file mode 100644 index ac366e4ac544f..0000000000000 --- a/packages/Connectivity/tests/smoketest/AndroidTest.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - diff --git a/packages/Connectivity/tests/smoketest/java/SmokeTest.java b/packages/Connectivity/tests/smoketest/java/SmokeTest.java deleted file mode 100644 index 7d6655fde15e0..0000000000000 --- a/packages/Connectivity/tests/smoketest/java/SmokeTest.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.net; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public final class SmokeTest { - - @Test - public void testLoadJni() { - System.loadLibrary("networkstatsfactorytestjni"); - assertEquals(0, 0x00); - } -} diff --git a/packages/Connectivity/tests/unit/Android.bp b/packages/Connectivity/tests/unit/Android.bp deleted file mode 100644 index 6f503ace037fd..0000000000000 --- a/packages/Connectivity/tests/unit/Android.bp +++ /dev/null @@ -1,89 +0,0 @@ -//######################################################################## -// Build FrameworksNetTests package -//######################################################################## -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_base_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_base_license"], -} - -java_defaults { - name: "FrameworksNetTests-jni-defaults", - jni_libs: [ - "ld-android", - "libbacktrace", - "libbase", - "libbinder", - "libbpf", - "libbpf_android", - "libc++", - "libcgrouprc", - "libcrypto", - "libcutils", - "libdl_android", - "libhidl-gen-utils", - "libhidlbase", - "libjsoncpp", - "liblog", - "liblzma", - "libnativehelper", - "libnetdbpf", - "libnetdutils", - "libnetworkstatsfactorytestjni", - "libpackagelistparser", - "libpcre2", - "libprocessgroup", - "libselinux", - "libtinyxml2", - "libui", - "libunwindstack", - "libutils", - "libutilscallstack", - "libvndksupport", - "libziparchive", - "libz", - "netd_aidl_interface-V5-cpp", - ], -} - -android_test { - name: "FrameworksNetTests", - defaults: [ - "framework-connectivity-test-defaults", - "FrameworksNetTests-jni-defaults", - ], - srcs: [ - "java/**/*.java", - "java/**/*.kt", - ], - test_suites: ["device-tests"], - certificate: "platform", - jarjar_rules: "jarjar-rules.txt", - static_libs: [ - "androidx.test.rules", - "bouncycastle-repackaged-unbundled", - "FrameworksNetCommonTests", - "frameworks-base-testutils", - "frameworks-net-integration-testutils", - "framework-protos", - "mockito-target-minus-junit4", - "net-tests-utils", - "platform-test-annotations", - "service-connectivity-pre-jarjar", - "services.core", - "services.net", - ], - libs: [ - "android.net.ipsec.ike.stubs.module_lib", - "android.test.runner", - "android.test.base", - "android.test.mock", - "ServiceConnectivityResources", - ], - jni_libs: [ - "libservice-connectivity", - ], -} diff --git a/packages/Connectivity/tests/unit/AndroidManifest.xml b/packages/Connectivity/tests/unit/AndroidManifest.xml deleted file mode 100644 index 4c60ccf606156..0000000000000 --- a/packages/Connectivity/tests/unit/AndroidManifest.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/Connectivity/tests/unit/AndroidTest.xml b/packages/Connectivity/tests/unit/AndroidTest.xml deleted file mode 100644 index 939ae493b280a..0000000000000 --- a/packages/Connectivity/tests/unit/AndroidTest.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - diff --git a/packages/Connectivity/tests/unit/jarjar-rules.txt b/packages/Connectivity/tests/unit/jarjar-rules.txt deleted file mode 100644 index ca8867206dda1..0000000000000 --- a/packages/Connectivity/tests/unit/jarjar-rules.txt +++ /dev/null @@ -1,2 +0,0 @@ -# Module library in frameworks/libs/net -rule com.android.net.module.util.** android.net.frameworktests.util.@1 diff --git a/packages/Connectivity/tests/unit/java/android/app/usage/NetworkStatsManagerTest.java b/packages/Connectivity/tests/unit/java/android/app/usage/NetworkStatsManagerTest.java deleted file mode 100644 index 899295a019d2a..0000000000000 --- a/packages/Connectivity/tests/unit/java/android/app/usage/NetworkStatsManagerTest.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.app.usage; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertTrue; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.net.ConnectivityManager; -import android.net.INetworkStatsService; -import android.net.INetworkStatsSession; -import android.net.NetworkStats.Entry; -import android.net.NetworkStatsHistory; -import android.net.NetworkTemplate; -import android.os.RemoteException; - -import androidx.test.InstrumentationRegistry; -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.invocation.InvocationOnMock; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class NetworkStatsManagerTest { - - private @Mock INetworkStatsService mService; - private @Mock INetworkStatsSession mStatsSession; - - private NetworkStatsManager mManager; - - // TODO: change to NetworkTemplate.MATCH_MOBILE once internal constant rename is merged to aosp. - private static final int MATCH_MOBILE_ALL = 1; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mManager = new NetworkStatsManager(InstrumentationRegistry.getContext(), mService); - } - - @Test - public void testQueryDetails() throws RemoteException { - final String subscriberId = "subid"; - final long startTime = 1; - final long endTime = 100; - final int uid1 = 10001; - final int uid2 = 10002; - final int uid3 = 10003; - - Entry uid1Entry1 = new Entry("if1", uid1, - android.net.NetworkStats.SET_DEFAULT, android.net.NetworkStats.TAG_NONE, - 100, 10, 200, 20, 0); - - Entry uid1Entry2 = new Entry( - "if2", uid1, - android.net.NetworkStats.SET_DEFAULT, android.net.NetworkStats.TAG_NONE, - 100, 10, 200, 20, 0); - - Entry uid2Entry1 = new Entry("if1", uid2, - android.net.NetworkStats.SET_DEFAULT, android.net.NetworkStats.TAG_NONE, - 150, 10, 250, 20, 0); - - Entry uid2Entry2 = new Entry( - "if2", uid2, - android.net.NetworkStats.SET_DEFAULT, android.net.NetworkStats.TAG_NONE, - 150, 10, 250, 20, 0); - - NetworkStatsHistory history1 = new NetworkStatsHistory(10, 2); - history1.recordData(10, 20, uid1Entry1); - history1.recordData(20, 30, uid1Entry2); - - NetworkStatsHistory history2 = new NetworkStatsHistory(10, 2); - history1.recordData(30, 40, uid2Entry1); - history1.recordData(35, 45, uid2Entry2); - - - when(mService.openSessionForUsageStats(anyInt(), anyString())).thenReturn(mStatsSession); - when(mStatsSession.getRelevantUids()).thenReturn(new int[] { uid1, uid2, uid3 }); - - when(mStatsSession.getHistoryIntervalForUid(any(NetworkTemplate.class), - eq(uid1), eq(android.net.NetworkStats.SET_ALL), - eq(android.net.NetworkStats.TAG_NONE), - eq(NetworkStatsHistory.FIELD_ALL), eq(startTime), eq(endTime))) - .then((InvocationOnMock inv) -> { - NetworkTemplate template = inv.getArgument(0); - assertEquals(MATCH_MOBILE_ALL, template.getMatchRule()); - assertEquals(subscriberId, template.getSubscriberId()); - return history1; - }); - - when(mStatsSession.getHistoryIntervalForUid(any(NetworkTemplate.class), - eq(uid2), eq(android.net.NetworkStats.SET_ALL), - eq(android.net.NetworkStats.TAG_NONE), - eq(NetworkStatsHistory.FIELD_ALL), eq(startTime), eq(endTime))) - .then((InvocationOnMock inv) -> { - NetworkTemplate template = inv.getArgument(0); - assertEquals(MATCH_MOBILE_ALL, template.getMatchRule()); - assertEquals(subscriberId, template.getSubscriberId()); - return history2; - }); - - - NetworkStats stats = mManager.queryDetails( - ConnectivityManager.TYPE_MOBILE, subscriberId, startTime, endTime); - - NetworkStats.Bucket bucket = new NetworkStats.Bucket(); - - // First 2 buckets exactly match entry timings - assertTrue(stats.getNextBucket(bucket)); - assertEquals(10, bucket.getStartTimeStamp()); - assertEquals(20, bucket.getEndTimeStamp()); - assertBucketMatches(uid1Entry1, bucket); - - assertTrue(stats.getNextBucket(bucket)); - assertEquals(20, bucket.getStartTimeStamp()); - assertEquals(30, bucket.getEndTimeStamp()); - assertBucketMatches(uid1Entry2, bucket); - - // 30 -> 40: contains uid2Entry1 and half of uid2Entry2 - assertTrue(stats.getNextBucket(bucket)); - assertEquals(30, bucket.getStartTimeStamp()); - assertEquals(40, bucket.getEndTimeStamp()); - assertEquals(225, bucket.getRxBytes()); - assertEquals(15, bucket.getRxPackets()); - assertEquals(375, bucket.getTxBytes()); - assertEquals(30, bucket.getTxPackets()); - - // 40 -> 50: contains half of uid2Entry2 - assertTrue(stats.getNextBucket(bucket)); - assertEquals(40, bucket.getStartTimeStamp()); - assertEquals(50, bucket.getEndTimeStamp()); - assertEquals(75, bucket.getRxBytes()); - assertEquals(5, bucket.getRxPackets()); - assertEquals(125, bucket.getTxBytes()); - assertEquals(10, bucket.getTxPackets()); - - assertFalse(stats.hasNextBucket()); - } - - @Test - public void testQueryDetails_NoSubscriberId() throws RemoteException { - final long startTime = 1; - final long endTime = 100; - final int uid1 = 10001; - final int uid2 = 10002; - - when(mService.openSessionForUsageStats(anyInt(), anyString())).thenReturn(mStatsSession); - when(mStatsSession.getRelevantUids()).thenReturn(new int[] { uid1, uid2 }); - - NetworkStats stats = mManager.queryDetails( - ConnectivityManager.TYPE_MOBILE, null, startTime, endTime); - - when(mStatsSession.getHistoryIntervalForUid(any(NetworkTemplate.class), - anyInt(), anyInt(), anyInt(), anyInt(), anyLong(), anyLong())) - .thenReturn(new NetworkStatsHistory(10, 0)); - - verify(mStatsSession, times(1)).getHistoryIntervalForUid( - argThat((NetworkTemplate t) -> - // No subscriberId: MATCH_MOBILE_WILDCARD template - t.getMatchRule() == NetworkTemplate.MATCH_MOBILE_WILDCARD), - eq(uid1), eq(android.net.NetworkStats.SET_ALL), - eq(android.net.NetworkStats.TAG_NONE), - eq(NetworkStatsHistory.FIELD_ALL), eq(startTime), eq(endTime)); - - verify(mStatsSession, times(1)).getHistoryIntervalForUid( - argThat((NetworkTemplate t) -> - // No subscriberId: MATCH_MOBILE_WILDCARD template - t.getMatchRule() == NetworkTemplate.MATCH_MOBILE_WILDCARD), - eq(uid2), eq(android.net.NetworkStats.SET_ALL), - eq(android.net.NetworkStats.TAG_NONE), - eq(NetworkStatsHistory.FIELD_ALL), eq(startTime), eq(endTime)); - - assertFalse(stats.hasNextBucket()); - } - - private void assertBucketMatches(Entry expected, NetworkStats.Bucket actual) { - assertEquals(expected.uid, actual.getUid()); - assertEquals(expected.rxBytes, actual.getRxBytes()); - assertEquals(expected.rxPackets, actual.getRxPackets()); - assertEquals(expected.txBytes, actual.getTxBytes()); - assertEquals(expected.txPackets, actual.getTxPackets()); - } -} diff --git a/packages/Connectivity/tests/unit/java/android/net/ConnectivityDiagnosticsManagerTest.java b/packages/Connectivity/tests/unit/java/android/net/ConnectivityDiagnosticsManagerTest.java deleted file mode 100644 index 06e9405a6a795..0000000000000 --- a/packages/Connectivity/tests/unit/java/android/net/ConnectivityDiagnosticsManagerTest.java +++ /dev/null @@ -1,384 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsBinder; -import static android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback; -import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport; -import static android.net.ConnectivityDiagnosticsManager.DataStallReport; - -import static com.android.testutils.ParcelUtils.assertParcelSane; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; - -import android.content.Context; -import android.os.PersistableBundle; - -import androidx.test.InstrumentationRegistry; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mock; - -import java.util.concurrent.Executor; - -@RunWith(JUnit4.class) -public class ConnectivityDiagnosticsManagerTest { - private static final int NET_ID = 1; - private static final int DETECTION_METHOD = 2; - private static final long TIMESTAMP = 10L; - private static final String INTERFACE_NAME = "interface"; - private static final String BUNDLE_KEY = "key"; - private static final String BUNDLE_VALUE = "value"; - - private static final Executor INLINE_EXECUTOR = x -> x.run(); - - @Mock private IConnectivityManager mService; - @Mock private ConnectivityDiagnosticsCallback mCb; - - private Context mContext; - private ConnectivityDiagnosticsBinder mBinder; - private ConnectivityDiagnosticsManager mManager; - - private String mPackageName; - - @Before - public void setUp() { - mContext = InstrumentationRegistry.getContext(); - - mService = mock(IConnectivityManager.class); - mCb = mock(ConnectivityDiagnosticsCallback.class); - - mBinder = new ConnectivityDiagnosticsBinder(mCb, INLINE_EXECUTOR); - mManager = new ConnectivityDiagnosticsManager(mContext, mService); - - mPackageName = mContext.getOpPackageName(); - } - - @After - public void tearDown() { - // clear ConnectivityDiagnosticsManager callbacks map - ConnectivityDiagnosticsManager.sCallbacks.clear(); - } - - private ConnectivityReport createSampleConnectivityReport() { - final LinkProperties linkProperties = new LinkProperties(); - linkProperties.setInterfaceName(INTERFACE_NAME); - - final NetworkCapabilities networkCapabilities = new NetworkCapabilities(); - networkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS); - - final PersistableBundle bundle = new PersistableBundle(); - bundle.putString(BUNDLE_KEY, BUNDLE_VALUE); - - return new ConnectivityReport( - new Network(NET_ID), TIMESTAMP, linkProperties, networkCapabilities, bundle); - } - - private ConnectivityReport createDefaultConnectivityReport() { - return new ConnectivityReport( - new Network(0), - 0L, - new LinkProperties(), - new NetworkCapabilities(), - PersistableBundle.EMPTY); - } - - @Test - public void testPersistableBundleEquals() { - assertFalse( - ConnectivityDiagnosticsManager.persistableBundleEquals( - null, PersistableBundle.EMPTY)); - assertFalse( - ConnectivityDiagnosticsManager.persistableBundleEquals( - PersistableBundle.EMPTY, null)); - assertTrue( - ConnectivityDiagnosticsManager.persistableBundleEquals( - PersistableBundle.EMPTY, PersistableBundle.EMPTY)); - - final PersistableBundle a = new PersistableBundle(); - a.putString(BUNDLE_KEY, BUNDLE_VALUE); - - final PersistableBundle b = new PersistableBundle(); - b.putString(BUNDLE_KEY, BUNDLE_VALUE); - - final PersistableBundle c = new PersistableBundle(); - c.putString(BUNDLE_KEY, null); - - assertFalse( - ConnectivityDiagnosticsManager.persistableBundleEquals(PersistableBundle.EMPTY, a)); - assertFalse( - ConnectivityDiagnosticsManager.persistableBundleEquals(a, PersistableBundle.EMPTY)); - - assertTrue(ConnectivityDiagnosticsManager.persistableBundleEquals(a, b)); - assertTrue(ConnectivityDiagnosticsManager.persistableBundleEquals(b, a)); - - assertFalse(ConnectivityDiagnosticsManager.persistableBundleEquals(a, c)); - assertFalse(ConnectivityDiagnosticsManager.persistableBundleEquals(c, a)); - } - - @Test - public void testConnectivityReportEquals() { - final ConnectivityReport defaultReport = createDefaultConnectivityReport(); - final ConnectivityReport sampleReport = createSampleConnectivityReport(); - assertEquals(sampleReport, createSampleConnectivityReport()); - assertEquals(defaultReport, createDefaultConnectivityReport()); - - final LinkProperties linkProperties = sampleReport.getLinkProperties(); - final NetworkCapabilities networkCapabilities = sampleReport.getNetworkCapabilities(); - final PersistableBundle bundle = sampleReport.getAdditionalInfo(); - - assertNotEquals( - createDefaultConnectivityReport(), - new ConnectivityReport( - new Network(NET_ID), - 0L, - new LinkProperties(), - new NetworkCapabilities(), - PersistableBundle.EMPTY)); - assertNotEquals( - createDefaultConnectivityReport(), - new ConnectivityReport( - new Network(0), - TIMESTAMP, - new LinkProperties(), - new NetworkCapabilities(), - PersistableBundle.EMPTY)); - assertNotEquals( - createDefaultConnectivityReport(), - new ConnectivityReport( - new Network(0), - 0L, - linkProperties, - new NetworkCapabilities(), - PersistableBundle.EMPTY)); - assertNotEquals( - createDefaultConnectivityReport(), - new ConnectivityReport( - new Network(0), - TIMESTAMP, - new LinkProperties(), - networkCapabilities, - PersistableBundle.EMPTY)); - assertNotEquals( - createDefaultConnectivityReport(), - new ConnectivityReport( - new Network(0), - TIMESTAMP, - new LinkProperties(), - new NetworkCapabilities(), - bundle)); - } - - @Test - public void testConnectivityReportParcelUnparcel() { - assertParcelSane(createSampleConnectivityReport(), 5); - } - - private DataStallReport createSampleDataStallReport() { - final LinkProperties linkProperties = new LinkProperties(); - linkProperties.setInterfaceName(INTERFACE_NAME); - - final PersistableBundle bundle = new PersistableBundle(); - bundle.putString(BUNDLE_KEY, BUNDLE_VALUE); - - final NetworkCapabilities networkCapabilities = new NetworkCapabilities(); - networkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS); - - return new DataStallReport( - new Network(NET_ID), - TIMESTAMP, - DETECTION_METHOD, - linkProperties, - networkCapabilities, - bundle); - } - - private DataStallReport createDefaultDataStallReport() { - return new DataStallReport( - new Network(0), - 0L, - 0, - new LinkProperties(), - new NetworkCapabilities(), - PersistableBundle.EMPTY); - } - - @Test - public void testDataStallReportEquals() { - final DataStallReport defaultReport = createDefaultDataStallReport(); - final DataStallReport sampleReport = createSampleDataStallReport(); - assertEquals(sampleReport, createSampleDataStallReport()); - assertEquals(defaultReport, createDefaultDataStallReport()); - - final LinkProperties linkProperties = sampleReport.getLinkProperties(); - final NetworkCapabilities networkCapabilities = sampleReport.getNetworkCapabilities(); - final PersistableBundle bundle = sampleReport.getStallDetails(); - - assertNotEquals( - defaultReport, - new DataStallReport( - new Network(NET_ID), - 0L, - 0, - new LinkProperties(), - new NetworkCapabilities(), - PersistableBundle.EMPTY)); - assertNotEquals( - defaultReport, - new DataStallReport( - new Network(0), - TIMESTAMP, - 0, - new LinkProperties(), - new NetworkCapabilities(), - PersistableBundle.EMPTY)); - assertNotEquals( - defaultReport, - new DataStallReport( - new Network(0), - 0L, - DETECTION_METHOD, - new LinkProperties(), - new NetworkCapabilities(), - PersistableBundle.EMPTY)); - assertNotEquals( - defaultReport, - new DataStallReport( - new Network(0), - 0L, - 0, - linkProperties, - new NetworkCapabilities(), - PersistableBundle.EMPTY)); - assertNotEquals( - defaultReport, - new DataStallReport( - new Network(0), - 0L, - 0, - new LinkProperties(), - networkCapabilities, - PersistableBundle.EMPTY)); - assertNotEquals( - defaultReport, - new DataStallReport( - new Network(0), - 0L, - 0, - new LinkProperties(), - new NetworkCapabilities(), - bundle)); - } - - @Test - public void testDataStallReportParcelUnparcel() { - assertParcelSane(createSampleDataStallReport(), 6); - } - - @Test - public void testConnectivityDiagnosticsCallbackOnConnectivityReportAvailable() { - mBinder.onConnectivityReportAvailable(createSampleConnectivityReport()); - - // The callback will be invoked synchronously by inline executor. Immediately check the - // latch without waiting. - verify(mCb).onConnectivityReportAvailable(eq(createSampleConnectivityReport())); - } - - @Test - public void testConnectivityDiagnosticsCallbackOnDataStallSuspected() { - mBinder.onDataStallSuspected(createSampleDataStallReport()); - - // The callback will be invoked synchronously by inline executor. Immediately check the - // latch without waiting. - verify(mCb).onDataStallSuspected(eq(createSampleDataStallReport())); - } - - @Test - public void testConnectivityDiagnosticsCallbackOnNetworkConnectivityReported() { - final Network n = new Network(NET_ID); - final boolean connectivity = true; - - mBinder.onNetworkConnectivityReported(n, connectivity); - - // The callback will be invoked synchronously by inline executor. Immediately check the - // latch without waiting. - verify(mCb).onNetworkConnectivityReported(eq(n), eq(connectivity)); - } - - @Test - public void testRegisterConnectivityDiagnosticsCallback() throws Exception { - final NetworkRequest request = new NetworkRequest.Builder().build(); - - mManager.registerConnectivityDiagnosticsCallback(request, INLINE_EXECUTOR, mCb); - - verify(mService).registerConnectivityDiagnosticsCallback( - any(ConnectivityDiagnosticsBinder.class), eq(request), eq(mPackageName)); - assertTrue(ConnectivityDiagnosticsManager.sCallbacks.containsKey(mCb)); - } - - @Test - public void testRegisterDuplicateConnectivityDiagnosticsCallback() throws Exception { - final NetworkRequest request = new NetworkRequest.Builder().build(); - - mManager.registerConnectivityDiagnosticsCallback(request, INLINE_EXECUTOR, mCb); - - try { - mManager.registerConnectivityDiagnosticsCallback(request, INLINE_EXECUTOR, mCb); - fail("Duplicate callback registration should fail"); - } catch (IllegalArgumentException expected) { - } - } - - @Test - public void testUnregisterConnectivityDiagnosticsCallback() throws Exception { - final NetworkRequest request = new NetworkRequest.Builder().build(); - mManager.registerConnectivityDiagnosticsCallback(request, INLINE_EXECUTOR, mCb); - - mManager.unregisterConnectivityDiagnosticsCallback(mCb); - - verify(mService).unregisterConnectivityDiagnosticsCallback( - any(ConnectivityDiagnosticsBinder.class)); - assertFalse(ConnectivityDiagnosticsManager.sCallbacks.containsKey(mCb)); - - // verify that re-registering is successful - mManager.registerConnectivityDiagnosticsCallback(request, INLINE_EXECUTOR, mCb); - verify(mService, times(2)).registerConnectivityDiagnosticsCallback( - any(ConnectivityDiagnosticsBinder.class), eq(request), eq(mPackageName)); - assertTrue(ConnectivityDiagnosticsManager.sCallbacks.containsKey(mCb)); - } - - @Test - public void testUnregisterUnknownConnectivityDiagnosticsCallback() throws Exception { - mManager.unregisterConnectivityDiagnosticsCallback(mCb); - - verifyNoMoreInteractions(mService); - } -} diff --git a/packages/Connectivity/tests/unit/java/android/net/ConnectivityManagerTest.java b/packages/Connectivity/tests/unit/java/android/net/ConnectivityManagerTest.java deleted file mode 100644 index c804e10038872..0000000000000 --- a/packages/Connectivity/tests/unit/java/android/net/ConnectivityManagerTest.java +++ /dev/null @@ -1,438 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static android.net.ConnectivityManager.TYPE_NONE; -import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS; -import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN; -import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA; -import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS; -import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; -import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; -import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL; -import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P; -import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH; -import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; -import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET; -import static android.net.NetworkCapabilities.TRANSPORT_WIFI; -import static android.net.NetworkRequest.Type.BACKGROUND_REQUEST; -import static android.net.NetworkRequest.Type.REQUEST; -import static android.net.NetworkRequest.Type.TRACK_DEFAULT; -import static android.net.NetworkRequest.Type.TRACK_SYSTEM_DEFAULT; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.nullable; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.timeout; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.app.PendingIntent; -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.net.ConnectivityManager.NetworkCallback; -import android.os.Build.VERSION_CODES; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.os.Messenger; -import android.os.Process; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class ConnectivityManagerTest { - - @Mock Context mCtx; - @Mock IConnectivityManager mService; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - } - - static NetworkCapabilities verifyNetworkCapabilities( - int legacyType, int transportType, int... capabilities) { - final NetworkCapabilities nc = ConnectivityManager.networkCapabilitiesForType(legacyType); - assertNotNull(nc); - assertTrue(nc.hasTransport(transportType)); - for (int capability : capabilities) { - assertTrue(nc.hasCapability(capability)); - } - - return nc; - } - - static void verifyUnrestrictedNetworkCapabilities(int legacyType, int transportType) { - verifyNetworkCapabilities( - legacyType, - transportType, - NET_CAPABILITY_INTERNET, - NET_CAPABILITY_NOT_RESTRICTED, - NET_CAPABILITY_NOT_VPN, - NET_CAPABILITY_TRUSTED); - } - - static void verifyRestrictedMobileNetworkCapabilities(int legacyType, int capability) { - final NetworkCapabilities nc = verifyNetworkCapabilities( - legacyType, - TRANSPORT_CELLULAR, - capability, - NET_CAPABILITY_NOT_VPN, - NET_CAPABILITY_TRUSTED); - - assertFalse(nc.hasCapability(NET_CAPABILITY_INTERNET)); - assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); - } - - @Test - public void testNetworkCapabilitiesForTypeMobile() { - verifyUnrestrictedNetworkCapabilities( - ConnectivityManager.TYPE_MOBILE, TRANSPORT_CELLULAR); - } - - @Test - public void testNetworkCapabilitiesForTypeMobileCbs() { - verifyRestrictedMobileNetworkCapabilities( - ConnectivityManager.TYPE_MOBILE_CBS, NET_CAPABILITY_CBS); - } - - @Test - public void testNetworkCapabilitiesForTypeMobileDun() { - verifyRestrictedMobileNetworkCapabilities( - ConnectivityManager.TYPE_MOBILE_DUN, NET_CAPABILITY_DUN); - } - - @Test - public void testNetworkCapabilitiesForTypeMobileFota() { - verifyRestrictedMobileNetworkCapabilities( - ConnectivityManager.TYPE_MOBILE_FOTA, NET_CAPABILITY_FOTA); - } - - @Test - public void testNetworkCapabilitiesForTypeMobileHipri() { - verifyUnrestrictedNetworkCapabilities( - ConnectivityManager.TYPE_MOBILE_HIPRI, TRANSPORT_CELLULAR); - } - - @Test - public void testNetworkCapabilitiesForTypeMobileIms() { - verifyRestrictedMobileNetworkCapabilities( - ConnectivityManager.TYPE_MOBILE_IMS, NET_CAPABILITY_IMS); - } - - @Test - public void testNetworkCapabilitiesForTypeMobileMms() { - final NetworkCapabilities nc = verifyNetworkCapabilities( - ConnectivityManager.TYPE_MOBILE_MMS, - TRANSPORT_CELLULAR, - NET_CAPABILITY_MMS, - NET_CAPABILITY_NOT_VPN, - NET_CAPABILITY_TRUSTED); - - assertFalse(nc.hasCapability(NET_CAPABILITY_INTERNET)); - } - - @Test - public void testNetworkCapabilitiesForTypeMobileSupl() { - final NetworkCapabilities nc = verifyNetworkCapabilities( - ConnectivityManager.TYPE_MOBILE_SUPL, - TRANSPORT_CELLULAR, - NET_CAPABILITY_SUPL, - NET_CAPABILITY_NOT_VPN, - NET_CAPABILITY_TRUSTED); - - assertFalse(nc.hasCapability(NET_CAPABILITY_INTERNET)); - } - - @Test - public void testNetworkCapabilitiesForTypeWifi() { - verifyUnrestrictedNetworkCapabilities( - ConnectivityManager.TYPE_WIFI, TRANSPORT_WIFI); - } - - @Test - public void testNetworkCapabilitiesForTypeWifiP2p() { - final NetworkCapabilities nc = verifyNetworkCapabilities( - ConnectivityManager.TYPE_WIFI_P2P, - TRANSPORT_WIFI, - NET_CAPABILITY_NOT_RESTRICTED, NET_CAPABILITY_NOT_VPN, - NET_CAPABILITY_TRUSTED, NET_CAPABILITY_WIFI_P2P); - - assertFalse(nc.hasCapability(NET_CAPABILITY_INTERNET)); - } - - @Test - public void testNetworkCapabilitiesForTypeBluetooth() { - verifyUnrestrictedNetworkCapabilities( - ConnectivityManager.TYPE_BLUETOOTH, TRANSPORT_BLUETOOTH); - } - - @Test - public void testNetworkCapabilitiesForTypeEthernet() { - verifyUnrestrictedNetworkCapabilities( - ConnectivityManager.TYPE_ETHERNET, TRANSPORT_ETHERNET); - } - - @Test - public void testCallbackRelease() throws Exception { - ConnectivityManager manager = new ConnectivityManager(mCtx, mService); - NetworkRequest request = makeRequest(1); - NetworkCallback callback = mock(ConnectivityManager.NetworkCallback.class); - Handler handler = new Handler(Looper.getMainLooper()); - ArgumentCaptor captor = ArgumentCaptor.forClass(Messenger.class); - - // register callback - when(mService.requestNetwork(anyInt(), any(), anyInt(), captor.capture(), anyInt(), any(), - anyInt(), anyInt(), any(), nullable(String.class))).thenReturn(request); - manager.requestNetwork(request, callback, handler); - - // callback triggers - captor.getValue().send(makeMessage(request, ConnectivityManager.CALLBACK_AVAILABLE)); - verify(callback, timeout(500).times(1)).onAvailable(any(Network.class), - any(NetworkCapabilities.class), any(LinkProperties.class), anyBoolean()); - - // unregister callback - manager.unregisterNetworkCallback(callback); - verify(mService, times(1)).releaseNetworkRequest(request); - - // callback does not trigger anymore. - captor.getValue().send(makeMessage(request, ConnectivityManager.CALLBACK_LOSING)); - verify(callback, timeout(500).times(0)).onLosing(any(), anyInt()); - } - - @Test - public void testCallbackRecycling() throws Exception { - ConnectivityManager manager = new ConnectivityManager(mCtx, mService); - NetworkRequest req1 = makeRequest(1); - NetworkRequest req2 = makeRequest(2); - NetworkCallback callback = mock(ConnectivityManager.NetworkCallback.class); - Handler handler = new Handler(Looper.getMainLooper()); - ArgumentCaptor captor = ArgumentCaptor.forClass(Messenger.class); - - // register callback - when(mService.requestNetwork(anyInt(), any(), anyInt(), captor.capture(), anyInt(), any(), - anyInt(), anyInt(), any(), nullable(String.class))).thenReturn(req1); - manager.requestNetwork(req1, callback, handler); - - // callback triggers - captor.getValue().send(makeMessage(req1, ConnectivityManager.CALLBACK_AVAILABLE)); - verify(callback, timeout(100).times(1)).onAvailable(any(Network.class), - any(NetworkCapabilities.class), any(LinkProperties.class), anyBoolean()); - - // unregister callback - manager.unregisterNetworkCallback(callback); - verify(mService, times(1)).releaseNetworkRequest(req1); - - // callback does not trigger anymore. - captor.getValue().send(makeMessage(req1, ConnectivityManager.CALLBACK_LOSING)); - verify(callback, timeout(100).times(0)).onLosing(any(), anyInt()); - - // callback can be registered again - when(mService.requestNetwork(anyInt(), any(), anyInt(), captor.capture(), anyInt(), any(), - anyInt(), anyInt(), any(), nullable(String.class))).thenReturn(req2); - manager.requestNetwork(req2, callback, handler); - - // callback triggers - captor.getValue().send(makeMessage(req2, ConnectivityManager.CALLBACK_LOST)); - verify(callback, timeout(100).times(1)).onLost(any()); - - // unregister callback - manager.unregisterNetworkCallback(callback); - verify(mService, times(1)).releaseNetworkRequest(req2); - } - - // TODO: turn on this test when request callback 1:1 mapping is enforced - //@Test - private void noDoubleCallbackRegistration() throws Exception { - ConnectivityManager manager = new ConnectivityManager(mCtx, mService); - NetworkRequest request = makeRequest(1); - NetworkCallback callback = new ConnectivityManager.NetworkCallback(); - ApplicationInfo info = new ApplicationInfo(); - // TODO: update version when starting to enforce 1:1 mapping - info.targetSdkVersion = VERSION_CODES.N_MR1 + 1; - - when(mCtx.getApplicationInfo()).thenReturn(info); - when(mService.requestNetwork(anyInt(), any(), anyInt(), any(), anyInt(), any(), anyInt(), - anyInt(), any(), nullable(String.class))).thenReturn(request); - - Handler handler = new Handler(Looper.getMainLooper()); - manager.requestNetwork(request, callback, handler); - - // callback is already registered, reregistration should fail. - Class wantException = IllegalArgumentException.class; - expectThrowable(() -> manager.requestNetwork(request, callback), wantException); - - manager.unregisterNetworkCallback(callback); - verify(mService, times(1)).releaseNetworkRequest(request); - - // unregistering the callback should make it registrable again. - manager.requestNetwork(request, callback); - } - - @Test - public void testArgumentValidation() throws Exception { - ConnectivityManager manager = new ConnectivityManager(mCtx, mService); - - NetworkRequest request = mock(NetworkRequest.class); - NetworkCallback callback = mock(NetworkCallback.class); - Handler handler = mock(Handler.class); - NetworkCallback nullCallback = null; - PendingIntent nullIntent = null; - - mustFail(() -> manager.requestNetwork(null, callback)); - mustFail(() -> manager.requestNetwork(request, nullCallback)); - mustFail(() -> manager.requestNetwork(request, callback, null)); - mustFail(() -> manager.requestNetwork(request, callback, -1)); - mustFail(() -> manager.requestNetwork(request, nullIntent)); - - mustFail(() -> manager.requestBackgroundNetwork(null, callback, handler)); - mustFail(() -> manager.requestBackgroundNetwork(request, null, handler)); - mustFail(() -> manager.requestBackgroundNetwork(request, callback, null)); - - mustFail(() -> manager.registerNetworkCallback(null, callback, handler)); - mustFail(() -> manager.registerNetworkCallback(request, null, handler)); - mustFail(() -> manager.registerNetworkCallback(request, callback, null)); - mustFail(() -> manager.registerNetworkCallback(request, nullIntent)); - - mustFail(() -> manager.registerDefaultNetworkCallback(null, handler)); - mustFail(() -> manager.registerDefaultNetworkCallback(callback, null)); - - mustFail(() -> manager.registerSystemDefaultNetworkCallback(null, handler)); - mustFail(() -> manager.registerSystemDefaultNetworkCallback(callback, null)); - - mustFail(() -> manager.registerBestMatchingNetworkCallback(null, callback, handler)); - mustFail(() -> manager.registerBestMatchingNetworkCallback(request, null, handler)); - mustFail(() -> manager.registerBestMatchingNetworkCallback(request, callback, null)); - - mustFail(() -> manager.unregisterNetworkCallback(nullCallback)); - mustFail(() -> manager.unregisterNetworkCallback(nullIntent)); - mustFail(() -> manager.releaseNetworkRequest(nullIntent)); - } - - static void mustFail(Runnable fn) { - try { - fn.run(); - fail(); - } catch (Exception expected) { - } - } - - @Test - public void testRequestType() throws Exception { - final String testPkgName = "MyPackage"; - final String testAttributionTag = "MyTag"; - final ConnectivityManager manager = new ConnectivityManager(mCtx, mService); - when(mCtx.getOpPackageName()).thenReturn(testPkgName); - when(mCtx.getAttributionTag()).thenReturn(testAttributionTag); - final NetworkRequest request = makeRequest(1); - final NetworkCallback callback = new ConnectivityManager.NetworkCallback(); - - manager.requestNetwork(request, callback); - verify(mService).requestNetwork(eq(Process.INVALID_UID), eq(request.networkCapabilities), - eq(REQUEST.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(), - eq(testPkgName), eq(testAttributionTag)); - reset(mService); - - // Verify that register network callback does not calls requestNetwork at all. - manager.registerNetworkCallback(request, callback); - verify(mService, never()).requestNetwork(anyInt(), any(), anyInt(), any(), anyInt(), any(), - anyInt(), anyInt(), any(), any()); - verify(mService).listenForNetwork(eq(request.networkCapabilities), any(), any(), anyInt(), - eq(testPkgName), eq(testAttributionTag)); - reset(mService); - - Handler handler = new Handler(ConnectivityThread.getInstanceLooper()); - - manager.registerDefaultNetworkCallback(callback); - verify(mService).requestNetwork(eq(Process.INVALID_UID), eq(null), - eq(TRACK_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(), - eq(testPkgName), eq(testAttributionTag)); - reset(mService); - - manager.registerDefaultNetworkCallbackForUid(42, callback, handler); - verify(mService).requestNetwork(eq(42), eq(null), - eq(TRACK_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(), - eq(testPkgName), eq(testAttributionTag)); - - manager.requestBackgroundNetwork(request, callback, handler); - verify(mService).requestNetwork(eq(Process.INVALID_UID), eq(request.networkCapabilities), - eq(BACKGROUND_REQUEST.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(), - eq(testPkgName), eq(testAttributionTag)); - reset(mService); - - manager.registerSystemDefaultNetworkCallback(callback, handler); - verify(mService).requestNetwork(eq(Process.INVALID_UID), eq(null), - eq(TRACK_SYSTEM_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(), - eq(testPkgName), eq(testAttributionTag)); - reset(mService); - } - - static Message makeMessage(NetworkRequest req, int messageType) { - Bundle bundle = new Bundle(); - bundle.putParcelable(NetworkRequest.class.getSimpleName(), req); - // Pass default objects as we don't care which get passed here - bundle.putParcelable(Network.class.getSimpleName(), new Network(1)); - bundle.putParcelable(NetworkCapabilities.class.getSimpleName(), new NetworkCapabilities()); - bundle.putParcelable(LinkProperties.class.getSimpleName(), new LinkProperties()); - Message msg = Message.obtain(); - msg.what = messageType; - msg.setData(bundle); - return msg; - } - - static NetworkRequest makeRequest(int requestId) { - NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build(); - return new NetworkRequest(request.networkCapabilities, ConnectivityManager.TYPE_NONE, - requestId, NetworkRequest.Type.NONE); - } - - static void expectThrowable(Runnable block, Class throwableType) { - try { - block.run(); - } catch (Throwable t) { - if (t.getClass().equals(throwableType)) { - return; - } - fail("expected exception of type " + throwableType + ", but was " + t.getClass()); - } - fail("expected exception of type " + throwableType); - } -} diff --git a/packages/Connectivity/tests/unit/java/android/net/Ikev2VpnProfileTest.java b/packages/Connectivity/tests/unit/java/android/net/Ikev2VpnProfileTest.java deleted file mode 100644 index 0707ef3ed1d63..0000000000000 --- a/packages/Connectivity/tests/unit/java/android/net/Ikev2VpnProfileTest.java +++ /dev/null @@ -1,447 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import android.test.mock.MockContext; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.internal.net.VpnProfile; -import com.android.internal.org.bouncycastle.x509.X509V1CertificateGenerator; -import com.android.net.module.util.ProxyUtils; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.math.BigInteger; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.PrivateKey; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import javax.security.auth.x500.X500Principal; - -/** Unit tests for {@link Ikev2VpnProfile.Builder}. */ -@SmallTest -@RunWith(AndroidJUnit4.class) -public class Ikev2VpnProfileTest { - private static final String SERVER_ADDR_STRING = "1.2.3.4"; - private static final String IDENTITY_STRING = "Identity"; - private static final String USERNAME_STRING = "username"; - private static final String PASSWORD_STRING = "pa55w0rd"; - private static final String EXCL_LIST = "exclList"; - private static final byte[] PSK_BYTES = "preSharedKey".getBytes(); - private static final int TEST_MTU = 1300; - - private final MockContext mMockContext = - new MockContext() { - @Override - public String getOpPackageName() { - return "fooPackage"; - } - }; - private final ProxyInfo mProxy = ProxyInfo.buildDirectProxy( - SERVER_ADDR_STRING, -1, ProxyUtils.exclusionStringAsList(EXCL_LIST)); - - private X509Certificate mUserCert; - private X509Certificate mServerRootCa; - private PrivateKey mPrivateKey; - - @Before - public void setUp() throws Exception { - mServerRootCa = generateRandomCertAndKeyPair().cert; - - final CertificateAndKey userCertKey = generateRandomCertAndKeyPair(); - mUserCert = userCertKey.cert; - mPrivateKey = userCertKey.key; - } - - private Ikev2VpnProfile.Builder getBuilderWithDefaultOptions() { - final Ikev2VpnProfile.Builder builder = - new Ikev2VpnProfile.Builder(SERVER_ADDR_STRING, IDENTITY_STRING); - - builder.setBypassable(true); - builder.setProxy(mProxy); - builder.setMaxMtu(TEST_MTU); - builder.setMetered(true); - - return builder; - } - - @Test - public void testBuildValidProfileWithOptions() throws Exception { - final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); - - builder.setAuthUsernamePassword(USERNAME_STRING, PASSWORD_STRING, mServerRootCa); - final Ikev2VpnProfile profile = builder.build(); - assertNotNull(profile); - - // Check non-auth parameters correctly stored - assertEquals(SERVER_ADDR_STRING, profile.getServerAddr()); - assertEquals(IDENTITY_STRING, profile.getUserIdentity()); - assertEquals(mProxy, profile.getProxyInfo()); - assertTrue(profile.isBypassable()); - assertTrue(profile.isMetered()); - assertEquals(TEST_MTU, profile.getMaxMtu()); - assertEquals(Ikev2VpnProfile.DEFAULT_ALGORITHMS, profile.getAllowedAlgorithms()); - } - - @Test - public void testBuildUsernamePasswordProfile() throws Exception { - final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); - - builder.setAuthUsernamePassword(USERNAME_STRING, PASSWORD_STRING, mServerRootCa); - final Ikev2VpnProfile profile = builder.build(); - assertNotNull(profile); - - assertEquals(USERNAME_STRING, profile.getUsername()); - assertEquals(PASSWORD_STRING, profile.getPassword()); - assertEquals(mServerRootCa, profile.getServerRootCaCert()); - - assertNull(profile.getPresharedKey()); - assertNull(profile.getRsaPrivateKey()); - assertNull(profile.getUserCert()); - } - - @Test - public void testBuildDigitalSignatureProfile() throws Exception { - final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); - - builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa); - final Ikev2VpnProfile profile = builder.build(); - assertNotNull(profile); - - assertEquals(profile.getUserCert(), mUserCert); - assertEquals(mPrivateKey, profile.getRsaPrivateKey()); - assertEquals(profile.getServerRootCaCert(), mServerRootCa); - - assertNull(profile.getPresharedKey()); - assertNull(profile.getUsername()); - assertNull(profile.getPassword()); - } - - @Test - public void testBuildPresharedKeyProfile() throws Exception { - final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); - - builder.setAuthPsk(PSK_BYTES); - final Ikev2VpnProfile profile = builder.build(); - assertNotNull(profile); - - assertArrayEquals(PSK_BYTES, profile.getPresharedKey()); - - assertNull(profile.getServerRootCaCert()); - assertNull(profile.getUsername()); - assertNull(profile.getPassword()); - assertNull(profile.getRsaPrivateKey()); - assertNull(profile.getUserCert()); - } - - @Test - public void testBuildWithAllowedAlgorithmsAead() throws Exception { - final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); - builder.setAuthPsk(PSK_BYTES); - - List allowedAlgorithms = - Arrays.asList( - IpSecAlgorithm.AUTH_CRYPT_AES_GCM, - IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305); - builder.setAllowedAlgorithms(allowedAlgorithms); - - final Ikev2VpnProfile profile = builder.build(); - assertEquals(allowedAlgorithms, profile.getAllowedAlgorithms()); - } - - @Test - public void testBuildWithAllowedAlgorithmsNormal() throws Exception { - final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); - builder.setAuthPsk(PSK_BYTES); - - List allowedAlgorithms = - Arrays.asList( - IpSecAlgorithm.AUTH_HMAC_SHA512, - IpSecAlgorithm.AUTH_AES_XCBC, - IpSecAlgorithm.AUTH_AES_CMAC, - IpSecAlgorithm.CRYPT_AES_CBC, - IpSecAlgorithm.CRYPT_AES_CTR); - builder.setAllowedAlgorithms(allowedAlgorithms); - - final Ikev2VpnProfile profile = builder.build(); - assertEquals(allowedAlgorithms, profile.getAllowedAlgorithms()); - } - - @Test - public void testSetAllowedAlgorithmsEmptyList() throws Exception { - final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); - - try { - builder.setAllowedAlgorithms(new ArrayList<>()); - fail("Expected exception due to no valid algorithm set"); - } catch (IllegalArgumentException expected) { - } - } - - @Test - public void testSetAllowedAlgorithmsInvalidList() throws Exception { - final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); - List allowedAlgorithms = new ArrayList<>(); - - try { - builder.setAllowedAlgorithms(Arrays.asList(IpSecAlgorithm.AUTH_HMAC_SHA256)); - fail("Expected exception due to missing encryption"); - } catch (IllegalArgumentException expected) { - } - - try { - builder.setAllowedAlgorithms(Arrays.asList(IpSecAlgorithm.CRYPT_AES_CBC)); - fail("Expected exception due to missing authentication"); - } catch (IllegalArgumentException expected) { - } - } - - @Test - public void testSetAllowedAlgorithmsInsecureAlgorithm() throws Exception { - final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); - List allowedAlgorithms = new ArrayList<>(); - - try { - builder.setAllowedAlgorithms(Arrays.asList(IpSecAlgorithm.AUTH_HMAC_MD5)); - fail("Expected exception due to insecure algorithm"); - } catch (IllegalArgumentException expected) { - } - - try { - builder.setAllowedAlgorithms(Arrays.asList(IpSecAlgorithm.AUTH_HMAC_SHA1)); - fail("Expected exception due to insecure algorithm"); - } catch (IllegalArgumentException expected) { - } - } - - @Test - public void testBuildNoAuthMethodSet() throws Exception { - final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); - - try { - builder.build(); - fail("Expected exception due to lack of auth method"); - } catch (IllegalArgumentException expected) { - } - } - - @Test - public void testBuildInvalidMtu() throws Exception { - final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); - - try { - builder.setMaxMtu(500); - fail("Expected exception due to too-small MTU"); - } catch (IllegalArgumentException expected) { - } - } - - private void verifyVpnProfileCommon(VpnProfile profile) { - assertEquals(SERVER_ADDR_STRING, profile.server); - assertEquals(IDENTITY_STRING, profile.ipsecIdentifier); - assertEquals(mProxy, profile.proxy); - assertTrue(profile.isBypassable); - assertTrue(profile.isMetered); - assertEquals(TEST_MTU, profile.maxMtu); - } - - @Test - public void testPskConvertToVpnProfile() throws Exception { - final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); - - builder.setAuthPsk(PSK_BYTES); - final VpnProfile profile = builder.build().toVpnProfile(); - - verifyVpnProfileCommon(profile); - assertEquals(Ikev2VpnProfile.encodeForIpsecSecret(PSK_BYTES), profile.ipsecSecret); - - // Check nothing else is set - assertEquals("", profile.username); - assertEquals("", profile.password); - assertEquals("", profile.ipsecUserCert); - assertEquals("", profile.ipsecCaCert); - } - - @Test - public void testUsernamePasswordConvertToVpnProfile() throws Exception { - final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); - - builder.setAuthUsernamePassword(USERNAME_STRING, PASSWORD_STRING, mServerRootCa); - final VpnProfile profile = builder.build().toVpnProfile(); - - verifyVpnProfileCommon(profile); - assertEquals(USERNAME_STRING, profile.username); - assertEquals(PASSWORD_STRING, profile.password); - assertEquals(Ikev2VpnProfile.certificateToPemString(mServerRootCa), profile.ipsecCaCert); - - // Check nothing else is set - assertEquals("", profile.ipsecUserCert); - assertEquals("", profile.ipsecSecret); - } - - @Test - public void testRsaConvertToVpnProfile() throws Exception { - final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); - - builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa); - final VpnProfile profile = builder.build().toVpnProfile(); - - final String expectedSecret = Ikev2VpnProfile.PREFIX_INLINE - + Ikev2VpnProfile.encodeForIpsecSecret(mPrivateKey.getEncoded()); - verifyVpnProfileCommon(profile); - assertEquals(Ikev2VpnProfile.certificateToPemString(mUserCert), profile.ipsecUserCert); - assertEquals( - expectedSecret, - profile.ipsecSecret); - assertEquals(Ikev2VpnProfile.certificateToPemString(mServerRootCa), profile.ipsecCaCert); - - // Check nothing else is set - assertEquals("", profile.username); - assertEquals("", profile.password); - } - - @Test - public void testPskFromVpnProfileDiscardsIrrelevantValues() throws Exception { - final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); - - builder.setAuthPsk(PSK_BYTES); - final VpnProfile profile = builder.build().toVpnProfile(); - profile.username = USERNAME_STRING; - profile.password = PASSWORD_STRING; - profile.ipsecCaCert = Ikev2VpnProfile.certificateToPemString(mServerRootCa); - profile.ipsecUserCert = Ikev2VpnProfile.certificateToPemString(mUserCert); - - final Ikev2VpnProfile result = Ikev2VpnProfile.fromVpnProfile(profile); - assertNull(result.getUsername()); - assertNull(result.getPassword()); - assertNull(result.getUserCert()); - assertNull(result.getRsaPrivateKey()); - assertNull(result.getServerRootCaCert()); - } - - @Test - public void testUsernamePasswordFromVpnProfileDiscardsIrrelevantValues() throws Exception { - final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); - - builder.setAuthUsernamePassword(USERNAME_STRING, PASSWORD_STRING, mServerRootCa); - final VpnProfile profile = builder.build().toVpnProfile(); - profile.ipsecSecret = new String(PSK_BYTES); - profile.ipsecUserCert = Ikev2VpnProfile.certificateToPemString(mUserCert); - - final Ikev2VpnProfile result = Ikev2VpnProfile.fromVpnProfile(profile); - assertNull(result.getPresharedKey()); - assertNull(result.getUserCert()); - assertNull(result.getRsaPrivateKey()); - } - - @Test - public void testRsaFromVpnProfileDiscardsIrrelevantValues() throws Exception { - final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); - - builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa); - final VpnProfile profile = builder.build().toVpnProfile(); - profile.username = USERNAME_STRING; - profile.password = PASSWORD_STRING; - - final Ikev2VpnProfile result = Ikev2VpnProfile.fromVpnProfile(profile); - assertNull(result.getUsername()); - assertNull(result.getPassword()); - assertNull(result.getPresharedKey()); - } - - @Test - public void testPskConversionIsLossless() throws Exception { - final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); - - builder.setAuthPsk(PSK_BYTES); - final Ikev2VpnProfile ikeProfile = builder.build(); - - assertEquals(ikeProfile, Ikev2VpnProfile.fromVpnProfile(ikeProfile.toVpnProfile())); - } - - @Test - public void testUsernamePasswordConversionIsLossless() throws Exception { - final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); - - builder.setAuthUsernamePassword(USERNAME_STRING, PASSWORD_STRING, mServerRootCa); - final Ikev2VpnProfile ikeProfile = builder.build(); - - assertEquals(ikeProfile, Ikev2VpnProfile.fromVpnProfile(ikeProfile.toVpnProfile())); - } - - @Test - public void testRsaConversionIsLossless() throws Exception { - final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); - - builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa); - final Ikev2VpnProfile ikeProfile = builder.build(); - - assertEquals(ikeProfile, Ikev2VpnProfile.fromVpnProfile(ikeProfile.toVpnProfile())); - } - - private static class CertificateAndKey { - public final X509Certificate cert; - public final PrivateKey key; - - CertificateAndKey(X509Certificate cert, PrivateKey key) { - this.cert = cert; - this.key = key; - } - } - - private static CertificateAndKey generateRandomCertAndKeyPair() throws Exception { - final Date validityBeginDate = - new Date(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1L)); - final Date validityEndDate = - new Date(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(1L)); - - // Generate a keypair - final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); - keyPairGenerator.initialize(512); - final KeyPair keyPair = keyPairGenerator.generateKeyPair(); - - final X500Principal dnName = new X500Principal("CN=test.android.com"); - final X509V1CertificateGenerator certGen = new X509V1CertificateGenerator(); - certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis())); - certGen.setSubjectDN(dnName); - certGen.setIssuerDN(dnName); - certGen.setNotBefore(validityBeginDate); - certGen.setNotAfter(validityEndDate); - certGen.setPublicKey(keyPair.getPublic()); - certGen.setSignatureAlgorithm("SHA256WithRSAEncryption"); - - final X509Certificate cert = certGen.generate(keyPair.getPrivate(), "AndroidOpenSSL"); - return new CertificateAndKey(cert, keyPair.getPrivate()); - } -} diff --git a/packages/Connectivity/tests/unit/java/android/net/IpMemoryStoreTest.java b/packages/Connectivity/tests/unit/java/android/net/IpMemoryStoreTest.java deleted file mode 100644 index 0b13800bc5c95..0000000000000 --- a/packages/Connectivity/tests/unit/java/android/net/IpMemoryStoreTest.java +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import android.content.Context; -import android.net.ipmemorystore.Blob; -import android.net.ipmemorystore.IOnStatusListener; -import android.net.ipmemorystore.NetworkAttributes; -import android.net.ipmemorystore.NetworkAttributesParcelable; -import android.net.ipmemorystore.Status; -import android.net.networkstack.ModuleNetworkStackClient; -import android.os.RemoteException; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.net.UnknownHostException; -import java.util.Arrays; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class IpMemoryStoreTest { - private static final String TAG = IpMemoryStoreTest.class.getSimpleName(); - private static final String TEST_CLIENT_ID = "testClientId"; - private static final String TEST_DATA_NAME = "testData"; - private static final String TEST_OTHER_DATA_NAME = TEST_DATA_NAME + "Other"; - private static final byte[] TEST_BLOB_DATA = new byte[] { -3, 6, 8, -9, 12, - -128, 0, 89, 112, 91, -34 }; - private static final NetworkAttributes TEST_NETWORK_ATTRIBUTES = buildTestNetworkAttributes( - "hint", 219); - - @Mock - Context mMockContext; - @Mock - ModuleNetworkStackClient mModuleNetworkStackClient; - @Mock - IIpMemoryStore mMockService; - @Mock - IOnStatusListener mIOnStatusListener; - IpMemoryStore mStore; - - @Captor - ArgumentCaptor mCbCaptor; - @Captor - ArgumentCaptor mNapCaptor; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - } - - private void startIpMemoryStore(boolean supplyService) { - if (supplyService) { - doAnswer(invocation -> { - ((IIpMemoryStoreCallbacks) invocation.getArgument(0)) - .onIpMemoryStoreFetched(mMockService); - return null; - }).when(mModuleNetworkStackClient).fetchIpMemoryStore(any()); - } else { - doNothing().when(mModuleNetworkStackClient).fetchIpMemoryStore(mCbCaptor.capture()); - } - mStore = new IpMemoryStore(mMockContext) { - @Override - protected ModuleNetworkStackClient getModuleNetworkStackClient(Context ctx) { - return mModuleNetworkStackClient; - } - }; - } - - private static NetworkAttributes buildTestNetworkAttributes(String hint, int mtu) { - return new NetworkAttributes.Builder() - .setCluster(hint) - .setMtu(mtu) - .build(); - } - - @Test - public void testNetworkAttributes() throws Exception { - startIpMemoryStore(true /* supplyService */); - final String l2Key = "fakeKey"; - - mStore.storeNetworkAttributes(l2Key, TEST_NETWORK_ATTRIBUTES, - status -> assertTrue("Store not successful : " + status.resultCode, - status.isSuccess())); - verify(mMockService, times(1)).storeNetworkAttributes(eq(l2Key), - mNapCaptor.capture(), any()); - assertEquals(TEST_NETWORK_ATTRIBUTES, new NetworkAttributes(mNapCaptor.getValue())); - - mStore.retrieveNetworkAttributes(l2Key, - (status, key, attr) -> { - assertTrue("Retrieve network attributes not successful : " - + status.resultCode, status.isSuccess()); - assertEquals(l2Key, key); - assertEquals(TEST_NETWORK_ATTRIBUTES, attr); - }); - - verify(mMockService, times(1)).retrieveNetworkAttributes(eq(l2Key), any()); - } - - @Test - public void testPrivateData() throws RemoteException { - startIpMemoryStore(true /* supplyService */); - final Blob b = new Blob(); - b.data = TEST_BLOB_DATA; - final String l2Key = "fakeKey"; - - mStore.storeBlob(l2Key, TEST_CLIENT_ID, TEST_DATA_NAME, b, - status -> { - assertTrue("Store not successful : " + status.resultCode, status.isSuccess()); - }); - verify(mMockService, times(1)).storeBlob(eq(l2Key), eq(TEST_CLIENT_ID), eq(TEST_DATA_NAME), - eq(b), any()); - - mStore.retrieveBlob(l2Key, TEST_CLIENT_ID, TEST_OTHER_DATA_NAME, - (status, key, name, data) -> { - assertTrue("Retrieve blob status not successful : " + status.resultCode, - status.isSuccess()); - assertEquals(l2Key, key); - assertEquals(name, TEST_DATA_NAME); - assertTrue(Arrays.equals(b.data, data.data)); - }); - verify(mMockService, times(1)).retrieveBlob(eq(l2Key), eq(TEST_CLIENT_ID), - eq(TEST_OTHER_DATA_NAME), any()); - } - - @Test - public void testFindL2Key() - throws UnknownHostException, RemoteException, Exception { - startIpMemoryStore(true /* supplyService */); - final String l2Key = "fakeKey"; - - mStore.findL2Key(TEST_NETWORK_ATTRIBUTES, - (status, key) -> { - assertTrue("Retrieve network sameness not successful : " + status.resultCode, - status.isSuccess()); - assertEquals(l2Key, key); - }); - verify(mMockService, times(1)).findL2Key(mNapCaptor.capture(), any()); - assertEquals(TEST_NETWORK_ATTRIBUTES, new NetworkAttributes(mNapCaptor.getValue())); - } - - @Test - public void testIsSameNetwork() throws UnknownHostException, RemoteException { - startIpMemoryStore(true /* supplyService */); - final String l2Key1 = "fakeKey1"; - final String l2Key2 = "fakeKey2"; - - mStore.isSameNetwork(l2Key1, l2Key2, - (status, answer) -> { - assertFalse("Retrieve network sameness suspiciously successful : " - + status.resultCode, status.isSuccess()); - assertEquals(Status.ERROR_ILLEGAL_ARGUMENT, status.resultCode); - assertNull(answer); - }); - verify(mMockService, times(1)).isSameNetwork(eq(l2Key1), eq(l2Key2), any()); - } - - @Test - public void testEnqueuedIpMsRequests() throws Exception { - startIpMemoryStore(false /* supplyService */); - - final Blob b = new Blob(); - b.data = TEST_BLOB_DATA; - final String l2Key = "fakeKey"; - - // enqueue multiple ipms requests - mStore.storeNetworkAttributes(l2Key, TEST_NETWORK_ATTRIBUTES, - status -> assertTrue("Store not successful : " + status.resultCode, - status.isSuccess())); - mStore.retrieveNetworkAttributes(l2Key, - (status, key, attr) -> { - assertTrue("Retrieve network attributes not successful : " - + status.resultCode, status.isSuccess()); - assertEquals(l2Key, key); - assertEquals(TEST_NETWORK_ATTRIBUTES, attr); - }); - mStore.storeBlob(l2Key, TEST_CLIENT_ID, TEST_DATA_NAME, b, - status -> assertTrue("Store not successful : " + status.resultCode, - status.isSuccess())); - mStore.retrieveBlob(l2Key, TEST_CLIENT_ID, TEST_OTHER_DATA_NAME, - (status, key, name, data) -> { - assertTrue("Retrieve blob status not successful : " + status.resultCode, - status.isSuccess()); - assertEquals(l2Key, key); - assertEquals(name, TEST_DATA_NAME); - assertTrue(Arrays.equals(b.data, data.data)); - }); - - // get ipms service ready - mCbCaptor.getValue().onIpMemoryStoreFetched(mMockService); - - InOrder inOrder = inOrder(mMockService); - - inOrder.verify(mMockService).storeNetworkAttributes(eq(l2Key), mNapCaptor.capture(), any()); - inOrder.verify(mMockService).retrieveNetworkAttributes(eq(l2Key), any()); - inOrder.verify(mMockService).storeBlob(eq(l2Key), eq(TEST_CLIENT_ID), eq(TEST_DATA_NAME), - eq(b), any()); - inOrder.verify(mMockService).retrieveBlob(eq(l2Key), eq(TEST_CLIENT_ID), - eq(TEST_OTHER_DATA_NAME), any()); - assertEquals(TEST_NETWORK_ATTRIBUTES, new NetworkAttributes(mNapCaptor.getValue())); - } - - @Test - public void testEnqueuedIpMsRequestsWithException() throws Exception { - startIpMemoryStore(true /* supplyService */); - doThrow(RemoteException.class).when(mMockService).retrieveNetworkAttributes(any(), any()); - - final Blob b = new Blob(); - b.data = TEST_BLOB_DATA; - final String l2Key = "fakeKey"; - - // enqueue multiple ipms requests - mStore.storeNetworkAttributes(l2Key, TEST_NETWORK_ATTRIBUTES, - status -> assertTrue("Store not successful : " + status.resultCode, - status.isSuccess())); - mStore.retrieveNetworkAttributes(l2Key, - (status, key, attr) -> { - assertTrue("Retrieve network attributes not successful : " - + status.resultCode, status.isSuccess()); - assertEquals(l2Key, key); - assertEquals(TEST_NETWORK_ATTRIBUTES, attr); - }); - mStore.storeBlob(l2Key, TEST_CLIENT_ID, TEST_DATA_NAME, b, - status -> assertTrue("Store not successful : " + status.resultCode, - status.isSuccess())); - mStore.retrieveBlob(l2Key, TEST_CLIENT_ID, TEST_OTHER_DATA_NAME, - (status, key, name, data) -> { - assertTrue("Retrieve blob status not successful : " + status.resultCode, - status.isSuccess()); - assertEquals(l2Key, key); - assertEquals(name, TEST_DATA_NAME); - assertTrue(Arrays.equals(b.data, data.data)); - }); - - // verify the rest of the queue is still processed in order even if the remote exception - // occurs when calling one or more requests - InOrder inOrder = inOrder(mMockService); - - inOrder.verify(mMockService).storeNetworkAttributes(eq(l2Key), mNapCaptor.capture(), any()); - inOrder.verify(mMockService).storeBlob(eq(l2Key), eq(TEST_CLIENT_ID), eq(TEST_DATA_NAME), - eq(b), any()); - inOrder.verify(mMockService).retrieveBlob(eq(l2Key), eq(TEST_CLIENT_ID), - eq(TEST_OTHER_DATA_NAME), any()); - assertEquals(TEST_NETWORK_ATTRIBUTES, new NetworkAttributes(mNapCaptor.getValue())); - } - - @Test - public void testEnqueuedIpMsRequestsCallbackFunctionWithException() throws Exception { - startIpMemoryStore(true /* supplyService */); - - final Blob b = new Blob(); - b.data = TEST_BLOB_DATA; - final String l2Key = "fakeKey"; - - // enqueue multiple ipms requests - mStore.storeNetworkAttributes(l2Key, TEST_NETWORK_ATTRIBUTES, - status -> assertTrue("Store not successful : " + status.resultCode, - status.isSuccess())); - mStore.retrieveNetworkAttributes(l2Key, - (status, key, attr) -> { - throw new RuntimeException("retrieveNetworkAttributes test"); - }); - mStore.storeBlob(l2Key, TEST_CLIENT_ID, TEST_DATA_NAME, b, - status -> { - throw new RuntimeException("storeBlob test"); - }); - mStore.retrieveBlob(l2Key, TEST_CLIENT_ID, TEST_OTHER_DATA_NAME, - (status, key, name, data) -> { - assertTrue("Retrieve blob status not successful : " + status.resultCode, - status.isSuccess()); - assertEquals(l2Key, key); - assertEquals(name, TEST_DATA_NAME); - assertTrue(Arrays.equals(b.data, data.data)); - }); - - // verify the rest of the queue is still processed in order even if when one or more - // callback throw the remote exception - InOrder inOrder = inOrder(mMockService); - - inOrder.verify(mMockService).storeNetworkAttributes(eq(l2Key), mNapCaptor.capture(), - any()); - inOrder.verify(mMockService).retrieveNetworkAttributes(eq(l2Key), any()); - inOrder.verify(mMockService).storeBlob(eq(l2Key), eq(TEST_CLIENT_ID), eq(TEST_DATA_NAME), - eq(b), any()); - inOrder.verify(mMockService).retrieveBlob(eq(l2Key), eq(TEST_CLIENT_ID), - eq(TEST_OTHER_DATA_NAME), any()); - assertEquals(TEST_NETWORK_ATTRIBUTES, new NetworkAttributes(mNapCaptor.getValue())); - } - - @Test - public void testFactoryReset() throws RemoteException { - startIpMemoryStore(true /* supplyService */); - mStore.factoryReset(); - verify(mMockService, times(1)).factoryReset(); - } -} diff --git a/packages/Connectivity/tests/unit/java/android/net/IpSecAlgorithmTest.java b/packages/Connectivity/tests/unit/java/android/net/IpSecAlgorithmTest.java deleted file mode 100644 index 5bd2214774122..0000000000000 --- a/packages/Connectivity/tests/unit/java/android/net/IpSecAlgorithmTest.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static android.net.IpSecAlgorithm.ALGO_TO_REQUIRED_FIRST_SDK; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; - -import android.content.res.Resources; -import android.os.Build; -import android.os.Parcel; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.internal.util.CollectionUtils; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.AbstractMap.SimpleEntry; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Map.Entry; -import java.util.Random; -import java.util.Set; - -/** Unit tests for {@link IpSecAlgorithm}. */ -@SmallTest -@RunWith(AndroidJUnit4.class) -public class IpSecAlgorithmTest { - private static final byte[] KEY_MATERIAL; - - private final Resources mMockResources = mock(Resources.class); - - static { - KEY_MATERIAL = new byte[128]; - new Random().nextBytes(KEY_MATERIAL); - }; - - private static byte[] generateKey(int keyLenInBits) { - return Arrays.copyOf(KEY_MATERIAL, keyLenInBits / 8); - } - - @Test - public void testNoTruncLen() throws Exception { - Entry[] authAndAeadList = - new Entry[] { - new SimpleEntry<>(IpSecAlgorithm.AUTH_HMAC_MD5, 128), - new SimpleEntry<>(IpSecAlgorithm.AUTH_HMAC_SHA1, 160), - new SimpleEntry<>(IpSecAlgorithm.AUTH_HMAC_SHA256, 256), - new SimpleEntry<>(IpSecAlgorithm.AUTH_HMAC_SHA384, 384), - new SimpleEntry<>(IpSecAlgorithm.AUTH_HMAC_SHA512, 512), - new SimpleEntry<>(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, 224), - }; - - // Expect auth and aead algorithms to throw errors if trunclen is omitted. - for (Entry algData : authAndAeadList) { - try { - new IpSecAlgorithm( - algData.getKey(), Arrays.copyOf(KEY_MATERIAL, algData.getValue() / 8)); - fail("Expected exception on unprovided auth trunclen"); - } catch (IllegalArgumentException expected) { - } - } - - // Ensure crypt works with no truncation length supplied. - new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, Arrays.copyOf(KEY_MATERIAL, 256 / 8)); - } - - private void checkAuthKeyAndTruncLenValidation(String algoName, int keyLen, int truncLen) - throws Exception { - new IpSecAlgorithm(algoName, generateKey(keyLen), truncLen); - - try { - new IpSecAlgorithm(algoName, generateKey(keyLen)); - fail("Expected exception on unprovided auth trunclen"); - } catch (IllegalArgumentException pass) { - } - - try { - new IpSecAlgorithm(algoName, generateKey(keyLen + 8), truncLen); - fail("Invalid key length not validated"); - } catch (IllegalArgumentException pass) { - } - - try { - new IpSecAlgorithm(algoName, generateKey(keyLen), truncLen + 1); - fail("Invalid truncation length not validated"); - } catch (IllegalArgumentException pass) { - } - } - - private void checkCryptKeyLenValidation(String algoName, int keyLen) throws Exception { - new IpSecAlgorithm(algoName, generateKey(keyLen)); - - try { - new IpSecAlgorithm(algoName, generateKey(keyLen + 8)); - fail("Invalid key length not validated"); - } catch (IllegalArgumentException pass) { - } - } - - @Test - public void testValidationForAlgosAddedInS() throws Exception { - if (Build.VERSION.DEVICE_INITIAL_SDK_INT <= Build.VERSION_CODES.R) { - return; - } - - for (int len : new int[] {160, 224, 288}) { - checkCryptKeyLenValidation(IpSecAlgorithm.CRYPT_AES_CTR, len); - } - checkAuthKeyAndTruncLenValidation(IpSecAlgorithm.AUTH_AES_XCBC, 128, 96); - checkAuthKeyAndTruncLenValidation(IpSecAlgorithm.AUTH_AES_CMAC, 128, 96); - checkAuthKeyAndTruncLenValidation(IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305, 288, 128); - } - - @Test - public void testTruncLenValidation() throws Exception { - for (int truncLen : new int[] {256, 512}) { - new IpSecAlgorithm( - IpSecAlgorithm.AUTH_HMAC_SHA512, - Arrays.copyOf(KEY_MATERIAL, 512 / 8), - truncLen); - } - - for (int truncLen : new int[] {255, 513}) { - try { - new IpSecAlgorithm( - IpSecAlgorithm.AUTH_HMAC_SHA512, - Arrays.copyOf(KEY_MATERIAL, 512 / 8), - truncLen); - fail("Invalid truncation length not validated"); - } catch (IllegalArgumentException pass) { - } - } - } - - @Test - public void testLenValidation() throws Exception { - for (int len : new int[] {128, 192, 256}) { - new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, Arrays.copyOf(KEY_MATERIAL, len / 8)); - } - try { - new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, Arrays.copyOf(KEY_MATERIAL, 384 / 8)); - fail("Invalid key length not validated"); - } catch (IllegalArgumentException pass) { - } - } - - @Test - public void testAlgoNameValidation() throws Exception { - try { - new IpSecAlgorithm("rot13", Arrays.copyOf(KEY_MATERIAL, 128 / 8)); - fail("Invalid algorithm name not validated"); - } catch (IllegalArgumentException pass) { - } - } - - @Test - public void testParcelUnparcel() throws Exception { - IpSecAlgorithm init = - new IpSecAlgorithm( - IpSecAlgorithm.AUTH_HMAC_SHA512, Arrays.copyOf(KEY_MATERIAL, 512 / 8), 256); - - Parcel p = Parcel.obtain(); - p.setDataPosition(0); - init.writeToParcel(p, 0); - - p.setDataPosition(0); - IpSecAlgorithm fin = IpSecAlgorithm.CREATOR.createFromParcel(p); - assertTrue("Parcel/Unparcel failed!", IpSecAlgorithm.equals(init, fin)); - p.recycle(); - } - - private static Set getMandatoryAlgos() { - return CollectionUtils.filter( - ALGO_TO_REQUIRED_FIRST_SDK.keySet(), - i -> Build.VERSION.DEVICE_INITIAL_SDK_INT >= ALGO_TO_REQUIRED_FIRST_SDK.get(i)); - } - - private static Set getOptionalAlgos() { - return CollectionUtils.filter( - ALGO_TO_REQUIRED_FIRST_SDK.keySet(), - i -> Build.VERSION.DEVICE_INITIAL_SDK_INT < ALGO_TO_REQUIRED_FIRST_SDK.get(i)); - } - - @Test - public void testGetSupportedAlgorithms() throws Exception { - assertTrue(IpSecAlgorithm.getSupportedAlgorithms().containsAll(getMandatoryAlgos())); - assertTrue(ALGO_TO_REQUIRED_FIRST_SDK.keySet().containsAll( - IpSecAlgorithm.getSupportedAlgorithms())); - } - - @Test - public void testLoadAlgos() throws Exception { - final Set optionalAlgoSet = getOptionalAlgos(); - final String[] optionalAlgos = optionalAlgoSet.toArray(new String[0]); - - doReturn(optionalAlgos).when(mMockResources) - .getStringArray(com.android.internal.R.array.config_optionalIpSecAlgorithms); - - final Set enabledAlgos = new HashSet<>(IpSecAlgorithm.loadAlgos(mMockResources)); - final Set expectedAlgos = ALGO_TO_REQUIRED_FIRST_SDK.keySet(); - - assertEquals(expectedAlgos, enabledAlgos); - } -} diff --git a/packages/Connectivity/tests/unit/java/android/net/IpSecConfigTest.java b/packages/Connectivity/tests/unit/java/android/net/IpSecConfigTest.java deleted file mode 100644 index 25e225ef303ac..0000000000000 --- a/packages/Connectivity/tests/unit/java/android/net/IpSecConfigTest.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static com.android.testutils.ParcelUtils.assertParcelSane; -import static com.android.testutils.ParcelUtils.assertParcelingIsLossless; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertNull; - -import androidx.test.filters.SmallTest; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link IpSecConfig}. */ -@SmallTest -@RunWith(JUnit4.class) -public class IpSecConfigTest { - - @Test - public void testDefaults() throws Exception { - IpSecConfig c = new IpSecConfig(); - assertEquals(IpSecTransform.MODE_TRANSPORT, c.getMode()); - assertEquals("", c.getSourceAddress()); - assertEquals("", c.getDestinationAddress()); - assertNull(c.getNetwork()); - assertEquals(IpSecTransform.ENCAP_NONE, c.getEncapType()); - assertEquals(IpSecManager.INVALID_RESOURCE_ID, c.getEncapSocketResourceId()); - assertEquals(0, c.getEncapRemotePort()); - assertEquals(0, c.getNattKeepaliveInterval()); - assertNull(c.getEncryption()); - assertNull(c.getAuthentication()); - assertEquals(IpSecManager.INVALID_RESOURCE_ID, c.getSpiResourceId()); - assertEquals(0, c.getXfrmInterfaceId()); - } - - private IpSecConfig getSampleConfig() { - IpSecConfig c = new IpSecConfig(); - c.setMode(IpSecTransform.MODE_TUNNEL); - c.setSourceAddress("0.0.0.0"); - c.setDestinationAddress("1.2.3.4"); - c.setSpiResourceId(1984); - c.setEncryption( - new IpSecAlgorithm( - IpSecAlgorithm.CRYPT_AES_CBC, - new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF})); - c.setAuthentication( - new IpSecAlgorithm( - IpSecAlgorithm.AUTH_HMAC_MD5, - new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0}, - 128)); - c.setAuthenticatedEncryption( - new IpSecAlgorithm( - IpSecAlgorithm.AUTH_CRYPT_AES_GCM, - new byte[] { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0, 1, 2, 3, 4 - }, - 128)); - c.setEncapType(android.system.OsConstants.UDP_ENCAP_ESPINUDP); - c.setEncapSocketResourceId(7); - c.setEncapRemotePort(22); - c.setNattKeepaliveInterval(42); - c.setMarkValue(12); - c.setMarkMask(23); - c.setXfrmInterfaceId(34); - - return c; - } - - @Test - public void testCopyConstructor() { - IpSecConfig original = getSampleConfig(); - IpSecConfig copy = new IpSecConfig(original); - - assertEquals(original, copy); - assertNotSame(original, copy); - } - - @Test - public void testParcelUnparcel() { - assertParcelingIsLossless(new IpSecConfig()); - - IpSecConfig c = getSampleConfig(); - assertParcelSane(c, 15); - } -} diff --git a/packages/Connectivity/tests/unit/java/android/net/IpSecManagerTest.java b/packages/Connectivity/tests/unit/java/android/net/IpSecManagerTest.java deleted file mode 100644 index 730e2d56bd780..0000000000000 --- a/packages/Connectivity/tests/unit/java/android/net/IpSecManagerTest.java +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static android.system.OsConstants.AF_INET; -import static android.system.OsConstants.IPPROTO_UDP; -import static android.system.OsConstants.SOCK_DGRAM; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyObject; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.system.Os; -import android.test.mock.MockContext; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.server.IpSecService; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.net.InetAddress; -import java.net.Socket; -import java.net.UnknownHostException; - -/** Unit tests for {@link IpSecManager}. */ -@SmallTest -@RunWith(AndroidJUnit4.class) -public class IpSecManagerTest { - - private static final int TEST_UDP_ENCAP_PORT = 34567; - private static final int DROID_SPI = 0xD1201D; - private static final int DUMMY_RESOURCE_ID = 0x1234; - - private static final InetAddress GOOGLE_DNS_4; - private static final String VTI_INTF_NAME = "ipsec_test"; - private static final InetAddress VTI_LOCAL_ADDRESS; - private static final LinkAddress VTI_INNER_ADDRESS = new LinkAddress("10.0.1.1/24"); - - static { - try { - // Google Public DNS Addresses; - GOOGLE_DNS_4 = InetAddress.getByName("8.8.8.8"); - VTI_LOCAL_ADDRESS = InetAddress.getByName("8.8.4.4"); - } catch (UnknownHostException e) { - throw new RuntimeException("Could not resolve DNS Addresses", e); - } - } - - private IpSecService mMockIpSecService; - private IpSecManager mIpSecManager; - private MockContext mMockContext = new MockContext() { - @Override - public String getOpPackageName() { - return "fooPackage"; - } - }; - - @Before - public void setUp() throws Exception { - mMockIpSecService = mock(IpSecService.class); - mIpSecManager = new IpSecManager(mMockContext, mMockIpSecService); - } - - /* - * Allocate a specific SPI - * Close SPIs - */ - @Test - public void testAllocSpi() throws Exception { - IpSecSpiResponse spiResp = - new IpSecSpiResponse(IpSecManager.Status.OK, DUMMY_RESOURCE_ID, DROID_SPI); - when(mMockIpSecService.allocateSecurityParameterIndex( - eq(GOOGLE_DNS_4.getHostAddress()), - eq(DROID_SPI), - anyObject())) - .thenReturn(spiResp); - - IpSecManager.SecurityParameterIndex droidSpi = - mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4, DROID_SPI); - assertEquals(DROID_SPI, droidSpi.getSpi()); - - droidSpi.close(); - - verify(mMockIpSecService).releaseSecurityParameterIndex(DUMMY_RESOURCE_ID); - } - - @Test - public void testAllocRandomSpi() throws Exception { - IpSecSpiResponse spiResp = - new IpSecSpiResponse(IpSecManager.Status.OK, DUMMY_RESOURCE_ID, DROID_SPI); - when(mMockIpSecService.allocateSecurityParameterIndex( - eq(GOOGLE_DNS_4.getHostAddress()), - eq(IpSecManager.INVALID_SECURITY_PARAMETER_INDEX), - anyObject())) - .thenReturn(spiResp); - - IpSecManager.SecurityParameterIndex randomSpi = - mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4); - - assertEquals(DROID_SPI, randomSpi.getSpi()); - - randomSpi.close(); - - verify(mMockIpSecService).releaseSecurityParameterIndex(DUMMY_RESOURCE_ID); - } - - /* - * Throws resource unavailable exception - */ - @Test - public void testAllocSpiResUnavailableException() throws Exception { - IpSecSpiResponse spiResp = - new IpSecSpiResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE, 0, 0); - when(mMockIpSecService.allocateSecurityParameterIndex( - anyString(), anyInt(), anyObject())) - .thenReturn(spiResp); - - try { - mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4); - fail("ResourceUnavailableException was not thrown"); - } catch (IpSecManager.ResourceUnavailableException e) { - } - } - - /* - * Throws spi unavailable exception - */ - @Test - public void testAllocSpiSpiUnavailableException() throws Exception { - IpSecSpiResponse spiResp = new IpSecSpiResponse(IpSecManager.Status.SPI_UNAVAILABLE, 0, 0); - when(mMockIpSecService.allocateSecurityParameterIndex( - anyString(), anyInt(), anyObject())) - .thenReturn(spiResp); - - try { - mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4); - fail("ResourceUnavailableException was not thrown"); - } catch (IpSecManager.ResourceUnavailableException e) { - } - } - - /* - * Should throw exception when request spi 0 in IpSecManager - */ - @Test - public void testRequestAllocInvalidSpi() throws Exception { - try { - mIpSecManager.allocateSecurityParameterIndex(GOOGLE_DNS_4, 0); - fail("Able to allocate invalid spi"); - } catch (IllegalArgumentException e) { - } - } - - @Test - public void testOpenEncapsulationSocket() throws Exception { - IpSecUdpEncapResponse udpEncapResp = - new IpSecUdpEncapResponse( - IpSecManager.Status.OK, - DUMMY_RESOURCE_ID, - TEST_UDP_ENCAP_PORT, - Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)); - when(mMockIpSecService.openUdpEncapsulationSocket(eq(TEST_UDP_ENCAP_PORT), anyObject())) - .thenReturn(udpEncapResp); - - IpSecManager.UdpEncapsulationSocket encapSocket = - mIpSecManager.openUdpEncapsulationSocket(TEST_UDP_ENCAP_PORT); - assertNotNull(encapSocket.getFileDescriptor()); - assertEquals(TEST_UDP_ENCAP_PORT, encapSocket.getPort()); - - encapSocket.close(); - - verify(mMockIpSecService).closeUdpEncapsulationSocket(DUMMY_RESOURCE_ID); - } - - @Test - public void testApplyTransportModeTransformEnsuresSocketCreation() throws Exception { - Socket socket = new Socket(); - IpSecConfig dummyConfig = new IpSecConfig(); - IpSecTransform dummyTransform = new IpSecTransform(null, dummyConfig); - - // Even if underlying SocketImpl is not initalized, this should force the init, and - // thereby succeed. - mIpSecManager.applyTransportModeTransform( - socket, IpSecManager.DIRECTION_IN, dummyTransform); - - // Check to make sure the FileDescriptor is non-null - assertNotNull(socket.getFileDescriptor$()); - } - - @Test - public void testRemoveTransportModeTransformsForcesSocketCreation() throws Exception { - Socket socket = new Socket(); - - // Even if underlying SocketImpl is not initalized, this should force the init, and - // thereby succeed. - mIpSecManager.removeTransportModeTransforms(socket); - - // Check to make sure the FileDescriptor is non-null - assertNotNull(socket.getFileDescriptor$()); - } - - @Test - public void testOpenEncapsulationSocketOnRandomPort() throws Exception { - IpSecUdpEncapResponse udpEncapResp = - new IpSecUdpEncapResponse( - IpSecManager.Status.OK, - DUMMY_RESOURCE_ID, - TEST_UDP_ENCAP_PORT, - Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)); - - when(mMockIpSecService.openUdpEncapsulationSocket(eq(0), anyObject())) - .thenReturn(udpEncapResp); - - IpSecManager.UdpEncapsulationSocket encapSocket = - mIpSecManager.openUdpEncapsulationSocket(); - - assertNotNull(encapSocket.getFileDescriptor()); - assertEquals(TEST_UDP_ENCAP_PORT, encapSocket.getPort()); - - encapSocket.close(); - - verify(mMockIpSecService).closeUdpEncapsulationSocket(DUMMY_RESOURCE_ID); - } - - @Test - public void testOpenEncapsulationSocketWithInvalidPort() throws Exception { - try { - mIpSecManager.openUdpEncapsulationSocket(IpSecManager.INVALID_SECURITY_PARAMETER_INDEX); - fail("IllegalArgumentException was not thrown"); - } catch (IllegalArgumentException e) { - } - } - - // TODO: add test when applicable transform builder interface is available - - private IpSecManager.IpSecTunnelInterface createAndValidateVti(int resourceId, String intfName) - throws Exception { - IpSecTunnelInterfaceResponse dummyResponse = - new IpSecTunnelInterfaceResponse(IpSecManager.Status.OK, resourceId, intfName); - when(mMockIpSecService.createTunnelInterface( - eq(VTI_LOCAL_ADDRESS.getHostAddress()), eq(GOOGLE_DNS_4.getHostAddress()), - anyObject(), anyObject(), anyString())) - .thenReturn(dummyResponse); - - IpSecManager.IpSecTunnelInterface tunnelIntf = mIpSecManager.createIpSecTunnelInterface( - VTI_LOCAL_ADDRESS, GOOGLE_DNS_4, mock(Network.class)); - - assertNotNull(tunnelIntf); - return tunnelIntf; - } - - @Test - public void testCreateVti() throws Exception { - IpSecManager.IpSecTunnelInterface tunnelIntf = - createAndValidateVti(DUMMY_RESOURCE_ID, VTI_INTF_NAME); - - assertEquals(VTI_INTF_NAME, tunnelIntf.getInterfaceName()); - - tunnelIntf.close(); - verify(mMockIpSecService).deleteTunnelInterface(eq(DUMMY_RESOURCE_ID), anyString()); - } - - @Test - public void testAddRemoveAddressesFromVti() throws Exception { - IpSecManager.IpSecTunnelInterface tunnelIntf = - createAndValidateVti(DUMMY_RESOURCE_ID, VTI_INTF_NAME); - - tunnelIntf.addAddress(VTI_INNER_ADDRESS.getAddress(), - VTI_INNER_ADDRESS.getPrefixLength()); - verify(mMockIpSecService) - .addAddressToTunnelInterface( - eq(DUMMY_RESOURCE_ID), eq(VTI_INNER_ADDRESS), anyString()); - - tunnelIntf.removeAddress(VTI_INNER_ADDRESS.getAddress(), - VTI_INNER_ADDRESS.getPrefixLength()); - verify(mMockIpSecService) - .addAddressToTunnelInterface( - eq(DUMMY_RESOURCE_ID), eq(VTI_INNER_ADDRESS), anyString()); - } -} diff --git a/packages/Connectivity/tests/unit/java/android/net/IpSecTransformTest.java b/packages/Connectivity/tests/unit/java/android/net/IpSecTransformTest.java deleted file mode 100644 index 424f23dbbaf63..0000000000000 --- a/packages/Connectivity/tests/unit/java/android/net/IpSecTransformTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; - -import androidx.test.filters.SmallTest; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link IpSecTransform}. */ -@SmallTest -@RunWith(JUnit4.class) -public class IpSecTransformTest { - - @Test - public void testCreateTransformCopiesConfig() { - // Create a config with a few parameters to make sure it's not empty - IpSecConfig config = new IpSecConfig(); - config.setSourceAddress("0.0.0.0"); - config.setDestinationAddress("1.2.3.4"); - config.setSpiResourceId(1984); - - IpSecTransform preModification = new IpSecTransform(null, config); - - config.setSpiResourceId(1985); - IpSecTransform postModification = new IpSecTransform(null, config); - - assertNotEquals(preModification, postModification); - } - - @Test - public void testCreateTransformsWithSameConfigEqual() { - // Create a config with a few parameters to make sure it's not empty - IpSecConfig config = new IpSecConfig(); - config.setSourceAddress("0.0.0.0"); - config.setDestinationAddress("1.2.3.4"); - config.setSpiResourceId(1984); - - IpSecTransform config1 = new IpSecTransform(null, config); - IpSecTransform config2 = new IpSecTransform(null, config); - - assertEquals(config1, config2); - } -} diff --git a/packages/Connectivity/tests/unit/java/android/net/KeepalivePacketDataUtilTest.java b/packages/Connectivity/tests/unit/java/android/net/KeepalivePacketDataUtilTest.java deleted file mode 100644 index fc739fbfac617..0000000000000 --- a/packages/Connectivity/tests/unit/java/android/net/KeepalivePacketDataUtilTest.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static com.android.testutils.ParcelUtils.assertParcelingIsLossless; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import android.net.util.KeepalivePacketDataUtil; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -import java.net.InetAddress; -import java.nio.ByteBuffer; - -@RunWith(JUnit4.class) -public final class KeepalivePacketDataUtilTest { - private static final byte[] IPV4_KEEPALIVE_SRC_ADDR = {10, 0, 0, 1}; - private static final byte[] IPV4_KEEPALIVE_DST_ADDR = {10, 0, 0, 5}; - - @Before - public void setUp() {} - - @Test - public void testFromTcpKeepaliveStableParcelable() throws Exception { - final int srcPort = 1234; - final int dstPort = 4321; - final int seq = 0x11111111; - final int ack = 0x22222222; - final int wnd = 8000; - final int wndScale = 2; - final int tos = 4; - final int ttl = 64; - TcpKeepalivePacketData resultData = null; - final TcpKeepalivePacketDataParcelable testInfo = new TcpKeepalivePacketDataParcelable(); - testInfo.srcAddress = IPV4_KEEPALIVE_SRC_ADDR; - testInfo.srcPort = srcPort; - testInfo.dstAddress = IPV4_KEEPALIVE_DST_ADDR; - testInfo.dstPort = dstPort; - testInfo.seq = seq; - testInfo.ack = ack; - testInfo.rcvWnd = wnd; - testInfo.rcvWndScale = wndScale; - testInfo.tos = tos; - testInfo.ttl = ttl; - try { - resultData = KeepalivePacketDataUtil.fromStableParcelable(testInfo); - } catch (InvalidPacketException e) { - fail("InvalidPacketException: " + e); - } - - assertEquals(InetAddress.getByAddress(testInfo.srcAddress), resultData.getSrcAddress()); - assertEquals(InetAddress.getByAddress(testInfo.dstAddress), resultData.getDstAddress()); - assertEquals(testInfo.srcPort, resultData.getSrcPort()); - assertEquals(testInfo.dstPort, resultData.getDstPort()); - assertEquals(testInfo.seq, resultData.tcpSeq); - assertEquals(testInfo.ack, resultData.tcpAck); - assertEquals(testInfo.rcvWnd, resultData.tcpWindow); - assertEquals(testInfo.rcvWndScale, resultData.tcpWindowScale); - assertEquals(testInfo.tos, resultData.ipTos); - assertEquals(testInfo.ttl, resultData.ipTtl); - - assertParcelingIsLossless(resultData); - - final byte[] packet = resultData.getPacket(); - // IP version and IHL - assertEquals(packet[0], 0x45); - // TOS - assertEquals(packet[1], tos); - // TTL - assertEquals(packet[8], ttl); - // Source IP address. - byte[] ip = new byte[4]; - ByteBuffer buf = ByteBuffer.wrap(packet, 12, 4); - buf.get(ip); - assertArrayEquals(ip, IPV4_KEEPALIVE_SRC_ADDR); - // Destination IP address. - buf = ByteBuffer.wrap(packet, 16, 4); - buf.get(ip); - assertArrayEquals(ip, IPV4_KEEPALIVE_DST_ADDR); - - buf = ByteBuffer.wrap(packet, 20, 12); - // Source port. - assertEquals(buf.getShort(), srcPort); - // Destination port. - assertEquals(buf.getShort(), dstPort); - // Sequence number. - assertEquals(buf.getInt(), seq); - // Ack. - assertEquals(buf.getInt(), ack); - // Window size. - buf = ByteBuffer.wrap(packet, 34, 2); - assertEquals(buf.getShort(), wnd >> wndScale); - } - - //TODO: add ipv6 test when ipv6 supported - - @Test - public void testToTcpKeepaliveStableParcelable() throws Exception { - final int srcPort = 1234; - final int dstPort = 4321; - final int sequence = 0x11111111; - final int ack = 0x22222222; - final int wnd = 48_000; - final int wndScale = 2; - final int tos = 4; - final int ttl = 64; - final TcpKeepalivePacketDataParcelable testInfo = new TcpKeepalivePacketDataParcelable(); - testInfo.srcAddress = IPV4_KEEPALIVE_SRC_ADDR; - testInfo.srcPort = srcPort; - testInfo.dstAddress = IPV4_KEEPALIVE_DST_ADDR; - testInfo.dstPort = dstPort; - testInfo.seq = sequence; - testInfo.ack = ack; - testInfo.rcvWnd = wnd; - testInfo.rcvWndScale = wndScale; - testInfo.tos = tos; - testInfo.ttl = ttl; - TcpKeepalivePacketData testData = null; - TcpKeepalivePacketDataParcelable resultData = null; - testData = KeepalivePacketDataUtil.fromStableParcelable(testInfo); - resultData = KeepalivePacketDataUtil.toStableParcelable(testData); - assertArrayEquals(resultData.srcAddress, IPV4_KEEPALIVE_SRC_ADDR); - assertArrayEquals(resultData.dstAddress, IPV4_KEEPALIVE_DST_ADDR); - assertEquals(resultData.srcPort, srcPort); - assertEquals(resultData.dstPort, dstPort); - assertEquals(resultData.seq, sequence); - assertEquals(resultData.ack, ack); - assertEquals(resultData.rcvWnd, wnd); - assertEquals(resultData.rcvWndScale, wndScale); - assertEquals(resultData.tos, tos); - assertEquals(resultData.ttl, ttl); - - final String expected = "" - + "android.net.TcpKeepalivePacketDataParcelable{srcAddress: [10, 0, 0, 1]," - + " srcPort: 1234, dstAddress: [10, 0, 0, 5], dstPort: 4321, seq: 286331153," - + " ack: 572662306, rcvWnd: 48000, rcvWndScale: 2, tos: 4, ttl: 64}"; - assertEquals(expected, resultData.toString()); - } - - @Test - public void testParseTcpKeepalivePacketData() throws Exception { - final int srcPort = 1234; - final int dstPort = 4321; - final int sequence = 0x11111111; - final int ack = 0x22222222; - final int wnd = 4800; - final int wndScale = 2; - final int tos = 4; - final int ttl = 64; - final TcpKeepalivePacketDataParcelable testParcel = new TcpKeepalivePacketDataParcelable(); - testParcel.srcAddress = IPV4_KEEPALIVE_SRC_ADDR; - testParcel.srcPort = srcPort; - testParcel.dstAddress = IPV4_KEEPALIVE_DST_ADDR; - testParcel.dstPort = dstPort; - testParcel.seq = sequence; - testParcel.ack = ack; - testParcel.rcvWnd = wnd; - testParcel.rcvWndScale = wndScale; - testParcel.tos = tos; - testParcel.ttl = ttl; - - final KeepalivePacketData testData = - KeepalivePacketDataUtil.fromStableParcelable(testParcel); - final TcpKeepalivePacketDataParcelable parsedParcelable = - KeepalivePacketDataUtil.parseTcpKeepalivePacketData(testData); - final TcpKeepalivePacketData roundTripData = - KeepalivePacketDataUtil.fromStableParcelable(parsedParcelable); - - // Generated packet is the same, but rcvWnd / wndScale will differ if scale is non-zero - assertTrue(testData.getPacket().length > 0); - assertArrayEquals(testData.getPacket(), roundTripData.getPacket()); - - testParcel.rcvWndScale = 0; - final KeepalivePacketData noScaleTestData = - KeepalivePacketDataUtil.fromStableParcelable(testParcel); - final TcpKeepalivePacketDataParcelable noScaleParsedParcelable = - KeepalivePacketDataUtil.parseTcpKeepalivePacketData(noScaleTestData); - final TcpKeepalivePacketData noScaleRoundTripData = - KeepalivePacketDataUtil.fromStableParcelable(noScaleParsedParcelable); - assertEquals(noScaleTestData, noScaleRoundTripData); - assertTrue(noScaleTestData.getPacket().length > 0); - assertArrayEquals(noScaleTestData.getPacket(), noScaleRoundTripData.getPacket()); - } -} diff --git a/packages/Connectivity/tests/unit/java/android/net/MacAddressTest.java b/packages/Connectivity/tests/unit/java/android/net/MacAddressTest.java deleted file mode 100644 index 6de31f6b4be12..0000000000000 --- a/packages/Connectivity/tests/unit/java/android/net/MacAddressTest.java +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.net.module.util.MacAddressUtils; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.net.Inet6Address; -import java.util.Arrays; -import java.util.Random; - -@SmallTest -@RunWith(AndroidJUnit4.class) -public class MacAddressTest { - - static class AddrTypeTestCase { - byte[] addr; - int expectedType; - - static AddrTypeTestCase of(int expectedType, int... addr) { - AddrTypeTestCase t = new AddrTypeTestCase(); - t.expectedType = expectedType; - t.addr = toByteArray(addr); - return t; - } - } - - @Test - public void testMacAddrTypes() { - AddrTypeTestCase[] testcases = { - AddrTypeTestCase.of(MacAddress.TYPE_UNKNOWN), - AddrTypeTestCase.of(MacAddress.TYPE_UNKNOWN, 0), - AddrTypeTestCase.of(MacAddress.TYPE_UNKNOWN, 1, 2, 3, 4, 5), - AddrTypeTestCase.of(MacAddress.TYPE_UNKNOWN, 1, 2, 3, 4, 5, 6, 7), - AddrTypeTestCase.of(MacAddress.TYPE_UNICAST, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0), - AddrTypeTestCase.of(MacAddress.TYPE_BROADCAST, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff), - AddrTypeTestCase.of(MacAddress.TYPE_MULTICAST, 1, 2, 3, 4, 5, 6), - AddrTypeTestCase.of(MacAddress.TYPE_MULTICAST, 11, 22, 33, 44, 55, 66), - AddrTypeTestCase.of(MacAddress.TYPE_MULTICAST, 33, 33, 0xaa, 0xbb, 0xcc, 0xdd) - }; - - for (AddrTypeTestCase t : testcases) { - int got = MacAddress.macAddressType(t.addr); - String msg = String.format("expected type of %s to be %s, but got %s", - Arrays.toString(t.addr), t.expectedType, got); - assertEquals(msg, t.expectedType, got); - - if (got != MacAddress.TYPE_UNKNOWN) { - assertEquals(got, MacAddress.fromBytes(t.addr).getAddressType()); - } - } - } - - @Test - public void testToOuiString() { - String[][] macs = { - {"07:00:d3:56:8a:c4", "07:00:d3"}, - {"33:33:aa:bb:cc:dd", "33:33:aa"}, - {"06:00:00:00:00:00", "06:00:00"}, - {"07:00:d3:56:8a:c4", "07:00:d3"} - }; - - for (String[] pair : macs) { - String mac = pair[0]; - String expected = pair[1]; - assertEquals(expected, MacAddress.fromString(mac).toOuiString()); - } - } - - @Test - public void testHexPaddingWhenPrinting() { - String[] macs = { - "07:00:d3:56:8a:c4", - "33:33:aa:bb:cc:dd", - "06:00:00:00:00:00", - "07:00:d3:56:8a:c4" - }; - - for (String mac : macs) { - assertEquals(mac, MacAddress.fromString(mac).toString()); - assertEquals(mac, - MacAddress.stringAddrFromByteAddr(MacAddress.byteAddrFromStringAddr(mac))); - } - } - - @Test - public void testIsMulticastAddress() { - MacAddress[] multicastAddresses = { - MacAddress.BROADCAST_ADDRESS, - MacAddress.fromString("07:00:d3:56:8a:c4"), - MacAddress.fromString("33:33:aa:bb:cc:dd"), - }; - MacAddress[] unicastAddresses = { - MacAddress.ALL_ZEROS_ADDRESS, - MacAddress.fromString("00:01:44:55:66:77"), - MacAddress.fromString("08:00:22:33:44:55"), - MacAddress.fromString("06:00:00:00:00:00"), - }; - - for (MacAddress mac : multicastAddresses) { - String msg = mac.toString() + " expected to be a multicast address"; - assertTrue(msg, MacAddressUtils.isMulticastAddress(mac)); - } - for (MacAddress mac : unicastAddresses) { - String msg = mac.toString() + " expected not to be a multicast address"; - assertFalse(msg, MacAddressUtils.isMulticastAddress(mac)); - } - } - - @Test - public void testIsLocallyAssignedAddress() { - MacAddress[] localAddresses = { - MacAddress.fromString("06:00:00:00:00:00"), - MacAddress.fromString("07:00:d3:56:8a:c4"), - MacAddress.fromString("33:33:aa:bb:cc:dd"), - }; - MacAddress[] universalAddresses = { - MacAddress.fromString("00:01:44:55:66:77"), - MacAddress.fromString("08:00:22:33:44:55"), - }; - - for (MacAddress mac : localAddresses) { - String msg = mac.toString() + " expected to be a locally assigned address"; - assertTrue(msg, mac.isLocallyAssigned()); - } - for (MacAddress mac : universalAddresses) { - String msg = mac.toString() + " expected not to be globally unique address"; - assertFalse(msg, mac.isLocallyAssigned()); - } - } - - @Test - public void testMacAddressConversions() { - final int iterations = 10000; - for (int i = 0; i < iterations; i++) { - MacAddress mac = MacAddressUtils.createRandomUnicastAddress(); - - String stringRepr = mac.toString(); - byte[] bytesRepr = mac.toByteArray(); - - assertEquals(mac, MacAddress.fromString(stringRepr)); - assertEquals(mac, MacAddress.fromBytes(bytesRepr)); - - assertEquals(mac, MacAddress.fromString(MacAddress.stringAddrFromByteAddr(bytesRepr))); - assertEquals(mac, MacAddress.fromBytes(MacAddress.byteAddrFromStringAddr(stringRepr))); - } - } - - @Test - public void testMacAddressRandomGeneration() { - final int iterations = 1000; - final String expectedAndroidOui = "da:a1:19"; - for (int i = 0; i < iterations; i++) { - MacAddress mac = MacAddress.createRandomUnicastAddressWithGoogleBase(); - String stringRepr = mac.toString(); - - assertTrue(stringRepr + " expected to be a locally assigned address", - mac.isLocallyAssigned()); - assertTrue(stringRepr + " expected to begin with " + expectedAndroidOui, - stringRepr.startsWith(expectedAndroidOui)); - } - - final Random r = new Random(); - final String anotherOui = "24:5f:78"; - final String expectedLocalOui = "26:5f:78"; - final MacAddress base = MacAddress.fromString(anotherOui + ":0:0:0"); - for (int i = 0; i < iterations; i++) { - MacAddress mac = MacAddressUtils.createRandomUnicastAddress(base, r); - String stringRepr = mac.toString(); - - assertTrue(stringRepr + " expected to be a locally assigned address", - mac.isLocallyAssigned()); - assertEquals(MacAddress.TYPE_UNICAST, mac.getAddressType()); - assertTrue(stringRepr + " expected to begin with " + expectedLocalOui, - stringRepr.startsWith(expectedLocalOui)); - } - - for (int i = 0; i < iterations; i++) { - MacAddress mac = MacAddressUtils.createRandomUnicastAddress(); - String stringRepr = mac.toString(); - - assertTrue(stringRepr + " expected to be a locally assigned address", - mac.isLocallyAssigned()); - assertEquals(MacAddress.TYPE_UNICAST, mac.getAddressType()); - } - } - - @Test - public void testConstructorInputValidation() { - String[] invalidStringAddresses = { - "", - "abcd", - "1:2:3:4:5", - "1:2:3:4:5:6:7", - "10000:2:3:4:5:6", - }; - - for (String s : invalidStringAddresses) { - try { - MacAddress mac = MacAddress.fromString(s); - fail("MacAddress.fromString(" + s + ") should have failed, but returned " + mac); - } catch (IllegalArgumentException excepted) { - } - } - - try { - MacAddress mac = MacAddress.fromString(null); - fail("MacAddress.fromString(null) should have failed, but returned " + mac); - } catch (NullPointerException excepted) { - } - - byte[][] invalidBytesAddresses = { - {}, - {1,2,3,4,5}, - {1,2,3,4,5,6,7}, - }; - - for (byte[] b : invalidBytesAddresses) { - try { - MacAddress mac = MacAddress.fromBytes(b); - fail("MacAddress.fromBytes(" + Arrays.toString(b) - + ") should have failed, but returned " + mac); - } catch (IllegalArgumentException excepted) { - } - } - - try { - MacAddress mac = MacAddress.fromBytes(null); - fail("MacAddress.fromBytes(null) should have failed, but returned " + mac); - } catch (NullPointerException excepted) { - } - } - - @Test - public void testMatches() { - // match 4 bytes prefix - assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches( - MacAddress.fromString("aa:bb:cc:dd:00:00"), - MacAddress.fromString("ff:ff:ff:ff:00:00"))); - - // match bytes 0,1,2 and 5 - assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches( - MacAddress.fromString("aa:bb:cc:00:00:11"), - MacAddress.fromString("ff:ff:ff:00:00:ff"))); - - // match 34 bit prefix - assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches( - MacAddress.fromString("aa:bb:cc:dd:c0:00"), - MacAddress.fromString("ff:ff:ff:ff:c0:00"))); - - // fail to match 36 bit prefix - assertFalse(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches( - MacAddress.fromString("aa:bb:cc:dd:40:00"), - MacAddress.fromString("ff:ff:ff:ff:f0:00"))); - - // match all 6 bytes - assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches( - MacAddress.fromString("aa:bb:cc:dd:ee:11"), - MacAddress.fromString("ff:ff:ff:ff:ff:ff"))); - - // match none of 6 bytes - assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches( - MacAddress.fromString("00:00:00:00:00:00"), - MacAddress.fromString("00:00:00:00:00:00"))); - } - - /** - * Tests that link-local address generation from MAC is valid. - */ - @Test - public void testLinkLocalFromMacGeneration() { - MacAddress mac = MacAddress.fromString("52:74:f2:b1:a8:7f"); - byte[] inet6ll = {(byte) 0xfe, (byte) 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x74, - (byte) 0xf2, (byte) 0xff, (byte) 0xfe, (byte) 0xb1, (byte) 0xa8, 0x7f}; - Inet6Address llv6 = mac.getLinkLocalIpv6FromEui48Mac(); - assertTrue(llv6.isLinkLocalAddress()); - assertArrayEquals(inet6ll, llv6.getAddress()); - } - - static byte[] toByteArray(int... in) { - byte[] out = new byte[in.length]; - for (int i = 0; i < in.length; i++) { - out[i] = (byte) in[i]; - } - return out; - } -} diff --git a/packages/Connectivity/tests/unit/java/android/net/NetworkIdentityTest.kt b/packages/Connectivity/tests/unit/java/android/net/NetworkIdentityTest.kt deleted file mode 100644 index eb2b85c145783..0000000000000 --- a/packages/Connectivity/tests/unit/java/android/net/NetworkIdentityTest.kt +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net - -import android.net.NetworkIdentity.OEM_NONE -import android.net.NetworkIdentity.OEM_PAID -import android.net.NetworkIdentity.OEM_PRIVATE -import android.net.NetworkIdentity.getOemBitfield -import org.junit.Test -import org.junit.runner.RunWith -import org.junit.runners.JUnit4 -import kotlin.test.assertEquals - -@RunWith(JUnit4::class) -class NetworkIdentityTest { - @Test - fun testGetOemBitfield() { - val oemNone = NetworkCapabilities().apply { - setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID, false) - setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE, false) - } - val oemPaid = NetworkCapabilities().apply { - setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID, true) - setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE, false) - } - val oemPrivate = NetworkCapabilities().apply { - setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID, false) - setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE, true) - } - val oemAll = NetworkCapabilities().apply { - setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID, true) - setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE, true) - } - - assertEquals(getOemBitfield(oemNone), OEM_NONE) - assertEquals(getOemBitfield(oemPaid), OEM_PAID) - assertEquals(getOemBitfield(oemPrivate), OEM_PRIVATE) - assertEquals(getOemBitfield(oemAll), OEM_PAID or OEM_PRIVATE) - } -} diff --git a/packages/Connectivity/tests/unit/java/android/net/NetworkStatsHistoryTest.java b/packages/Connectivity/tests/unit/java/android/net/NetworkStatsHistoryTest.java deleted file mode 100644 index 13558cd51c28f..0000000000000 --- a/packages/Connectivity/tests/unit/java/android/net/NetworkStatsHistoryTest.java +++ /dev/null @@ -1,599 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static android.net.NetworkStatsHistory.DataStreamUtils.readVarLong; -import static android.net.NetworkStatsHistory.DataStreamUtils.writeVarLong; -import static android.net.NetworkStatsHistory.Entry.UNKNOWN; -import static android.net.NetworkStatsHistory.FIELD_ALL; -import static android.net.NetworkStatsHistory.FIELD_OPERATIONS; -import static android.net.NetworkStatsHistory.FIELD_RX_BYTES; -import static android.net.NetworkStatsHistory.FIELD_RX_PACKETS; -import static android.net.NetworkStatsHistory.FIELD_TX_BYTES; -import static android.net.TrafficStats.GB_IN_BYTES; -import static android.net.TrafficStats.MB_IN_BYTES; -import static android.text.format.DateUtils.DAY_IN_MILLIS; -import static android.text.format.DateUtils.HOUR_IN_MILLIS; -import static android.text.format.DateUtils.MINUTE_IN_MILLIS; -import static android.text.format.DateUtils.SECOND_IN_MILLIS; -import static android.text.format.DateUtils.WEEK_IN_MILLIS; -import static android.text.format.DateUtils.YEAR_IN_MILLIS; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import android.content.Context; -import android.util.Log; - -import androidx.test.InstrumentationRegistry; -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.frameworks.tests.net.R; - -import org.junit.After; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.util.Random; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class NetworkStatsHistoryTest { - private static final String TAG = "NetworkStatsHistoryTest"; - - private static final long TEST_START = 1194220800000L; - - private NetworkStatsHistory stats; - - @After - public void tearDown() throws Exception { - if (stats != null) { - assertConsistent(stats); - } - } - - @Test - public void testReadOriginalVersion() throws Exception { - final Context context = InstrumentationRegistry.getContext(); - final DataInputStream in = - new DataInputStream(context.getResources().openRawResource(R.raw.history_v1)); - - NetworkStatsHistory.Entry entry = null; - try { - final NetworkStatsHistory history = new NetworkStatsHistory(in); - assertEquals(15 * SECOND_IN_MILLIS, history.getBucketDuration()); - - entry = history.getValues(0, entry); - assertEquals(29143L, entry.rxBytes); - assertEquals(6223L, entry.txBytes); - - entry = history.getValues(history.size() - 1, entry); - assertEquals(1476L, entry.rxBytes); - assertEquals(838L, entry.txBytes); - - entry = history.getValues(Long.MIN_VALUE, Long.MAX_VALUE, entry); - assertEquals(332401L, entry.rxBytes); - assertEquals(64314L, entry.txBytes); - - } finally { - in.close(); - } - } - - @Test - public void testRecordSingleBucket() throws Exception { - final long BUCKET_SIZE = HOUR_IN_MILLIS; - stats = new NetworkStatsHistory(BUCKET_SIZE); - - // record data into narrow window to get single bucket - stats.recordData(TEST_START, TEST_START + SECOND_IN_MILLIS, - new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 2L)); - - assertEquals(1, stats.size()); - assertValues(stats, 0, SECOND_IN_MILLIS, 1024L, 10L, 2048L, 20L, 2L); - } - - @Test - public void testRecordEqualBuckets() throws Exception { - final long bucketDuration = HOUR_IN_MILLIS; - stats = new NetworkStatsHistory(bucketDuration); - - // split equally across two buckets - final long recordStart = TEST_START + (bucketDuration / 2); - stats.recordData(recordStart, recordStart + bucketDuration, - new NetworkStats.Entry(1024L, 10L, 128L, 2L, 2L)); - - assertEquals(2, stats.size()); - assertValues(stats, 0, HOUR_IN_MILLIS / 2, 512L, 5L, 64L, 1L, 1L); - assertValues(stats, 1, HOUR_IN_MILLIS / 2, 512L, 5L, 64L, 1L, 1L); - } - - @Test - public void testRecordTouchingBuckets() throws Exception { - final long BUCKET_SIZE = 15 * MINUTE_IN_MILLIS; - stats = new NetworkStatsHistory(BUCKET_SIZE); - - // split almost completely into middle bucket, but with a few minutes - // overlap into neighboring buckets. total record is 20 minutes. - final long recordStart = (TEST_START + BUCKET_SIZE) - MINUTE_IN_MILLIS; - final long recordEnd = (TEST_START + (BUCKET_SIZE * 2)) + (MINUTE_IN_MILLIS * 4); - stats.recordData(recordStart, recordEnd, - new NetworkStats.Entry(1000L, 2000L, 5000L, 10000L, 100L)); - - assertEquals(3, stats.size()); - // first bucket should have (1/20 of value) - assertValues(stats, 0, MINUTE_IN_MILLIS, 50L, 100L, 250L, 500L, 5L); - // second bucket should have (15/20 of value) - assertValues(stats, 1, 15 * MINUTE_IN_MILLIS, 750L, 1500L, 3750L, 7500L, 75L); - // final bucket should have (4/20 of value) - assertValues(stats, 2, 4 * MINUTE_IN_MILLIS, 200L, 400L, 1000L, 2000L, 20L); - } - - @Test - public void testRecordGapBuckets() throws Exception { - final long BUCKET_SIZE = HOUR_IN_MILLIS; - stats = new NetworkStatsHistory(BUCKET_SIZE); - - // record some data today and next week with large gap - final long firstStart = TEST_START; - final long lastStart = TEST_START + WEEK_IN_MILLIS; - stats.recordData(firstStart, firstStart + SECOND_IN_MILLIS, - new NetworkStats.Entry(128L, 2L, 256L, 4L, 1L)); - stats.recordData(lastStart, lastStart + SECOND_IN_MILLIS, - new NetworkStats.Entry(64L, 1L, 512L, 8L, 2L)); - - // we should have two buckets, far apart from each other - assertEquals(2, stats.size()); - assertValues(stats, 0, SECOND_IN_MILLIS, 128L, 2L, 256L, 4L, 1L); - assertValues(stats, 1, SECOND_IN_MILLIS, 64L, 1L, 512L, 8L, 2L); - - // now record something in middle, spread across two buckets - final long middleStart = TEST_START + DAY_IN_MILLIS; - final long middleEnd = middleStart + (HOUR_IN_MILLIS * 2); - stats.recordData(middleStart, middleEnd, - new NetworkStats.Entry(2048L, 4L, 2048L, 4L, 2L)); - - // now should have four buckets, with new record in middle two buckets - assertEquals(4, stats.size()); - assertValues(stats, 0, SECOND_IN_MILLIS, 128L, 2L, 256L, 4L, 1L); - assertValues(stats, 1, HOUR_IN_MILLIS, 1024L, 2L, 1024L, 2L, 1L); - assertValues(stats, 2, HOUR_IN_MILLIS, 1024L, 2L, 1024L, 2L, 1L); - assertValues(stats, 3, SECOND_IN_MILLIS, 64L, 1L, 512L, 8L, 2L); - } - - @Test - public void testRecordOverlapBuckets() throws Exception { - final long BUCKET_SIZE = HOUR_IN_MILLIS; - stats = new NetworkStatsHistory(BUCKET_SIZE); - - // record some data in one bucket, and another overlapping buckets - stats.recordData(TEST_START, TEST_START + SECOND_IN_MILLIS, - new NetworkStats.Entry(256L, 2L, 256L, 2L, 1L)); - final long midStart = TEST_START + (HOUR_IN_MILLIS / 2); - stats.recordData(midStart, midStart + HOUR_IN_MILLIS, - new NetworkStats.Entry(1024L, 10L, 1024L, 10L, 10L)); - - // should have two buckets, with some data mixed together - assertEquals(2, stats.size()); - assertValues(stats, 0, SECOND_IN_MILLIS + (HOUR_IN_MILLIS / 2), 768L, 7L, 768L, 7L, 6L); - assertValues(stats, 1, (HOUR_IN_MILLIS / 2), 512L, 5L, 512L, 5L, 5L); - } - - @Test - public void testRecordEntireGapIdentical() throws Exception { - // first, create two separate histories far apart - final NetworkStatsHistory stats1 = new NetworkStatsHistory(HOUR_IN_MILLIS); - stats1.recordData(TEST_START, TEST_START + 2 * HOUR_IN_MILLIS, 2000L, 1000L); - - final long TEST_START_2 = TEST_START + DAY_IN_MILLIS; - final NetworkStatsHistory stats2 = new NetworkStatsHistory(HOUR_IN_MILLIS); - stats2.recordData(TEST_START_2, TEST_START_2 + 2 * HOUR_IN_MILLIS, 1000L, 500L); - - // combine together with identical bucket size - stats = new NetworkStatsHistory(HOUR_IN_MILLIS); - stats.recordEntireHistory(stats1); - stats.recordEntireHistory(stats2); - - // first verify that totals match up - assertValues(stats, TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, 3000L, 1500L); - - // now inspect internal buckets - assertValues(stats, 0, 1000L, 500L); - assertValues(stats, 1, 1000L, 500L); - assertValues(stats, 2, 500L, 250L); - assertValues(stats, 3, 500L, 250L); - } - - @Test - public void testRecordEntireOverlapVaryingBuckets() throws Exception { - // create history just over hour bucket boundary - final NetworkStatsHistory stats1 = new NetworkStatsHistory(HOUR_IN_MILLIS); - stats1.recordData(TEST_START, TEST_START + MINUTE_IN_MILLIS * 60, 600L, 600L); - - final long TEST_START_2 = TEST_START + MINUTE_IN_MILLIS; - final NetworkStatsHistory stats2 = new NetworkStatsHistory(MINUTE_IN_MILLIS); - stats2.recordData(TEST_START_2, TEST_START_2 + MINUTE_IN_MILLIS * 5, 50L, 50L); - - // combine together with minute bucket size - stats = new NetworkStatsHistory(MINUTE_IN_MILLIS); - stats.recordEntireHistory(stats1); - stats.recordEntireHistory(stats2); - - // first verify that totals match up - assertValues(stats, TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, 650L, 650L); - - // now inspect internal buckets - assertValues(stats, 0, 10L, 10L); - assertValues(stats, 1, 20L, 20L); - assertValues(stats, 2, 20L, 20L); - assertValues(stats, 3, 20L, 20L); - assertValues(stats, 4, 20L, 20L); - assertValues(stats, 5, 20L, 20L); - assertValues(stats, 6, 10L, 10L); - - // now combine using 15min buckets - stats = new NetworkStatsHistory(HOUR_IN_MILLIS / 4); - stats.recordEntireHistory(stats1); - stats.recordEntireHistory(stats2); - - // first verify that totals match up - assertValues(stats, TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, 650L, 650L); - - // and inspect buckets - assertValues(stats, 0, 200L, 200L); - assertValues(stats, 1, 150L, 150L); - assertValues(stats, 2, 150L, 150L); - assertValues(stats, 3, 150L, 150L); - } - - @Test - public void testRemove() throws Exception { - stats = new NetworkStatsHistory(HOUR_IN_MILLIS); - - // record some data across 24 buckets - stats.recordData(TEST_START, TEST_START + DAY_IN_MILLIS, 24L, 24L); - assertEquals(24, stats.size()); - - // try removing invalid data; should be no change - stats.removeBucketsBefore(0 - DAY_IN_MILLIS); - assertEquals(24, stats.size()); - - // try removing far before buckets; should be no change - stats.removeBucketsBefore(TEST_START - YEAR_IN_MILLIS); - assertEquals(24, stats.size()); - - // try removing just moments into first bucket; should be no change - // since that bucket contains data beyond the cutoff - stats.removeBucketsBefore(TEST_START + SECOND_IN_MILLIS); - assertEquals(24, stats.size()); - - // try removing single bucket - stats.removeBucketsBefore(TEST_START + HOUR_IN_MILLIS); - assertEquals(23, stats.size()); - - // try removing multiple buckets - stats.removeBucketsBefore(TEST_START + (4 * HOUR_IN_MILLIS)); - assertEquals(20, stats.size()); - - // try removing all buckets - stats.removeBucketsBefore(TEST_START + YEAR_IN_MILLIS); - assertEquals(0, stats.size()); - } - - @Test - public void testTotalData() throws Exception { - final long BUCKET_SIZE = HOUR_IN_MILLIS; - stats = new NetworkStatsHistory(BUCKET_SIZE); - - // record uniform data across day - stats.recordData(TEST_START, TEST_START + DAY_IN_MILLIS, 2400L, 4800L); - - // verify that total outside range is 0 - assertValues(stats, TEST_START - WEEK_IN_MILLIS, TEST_START - DAY_IN_MILLIS, 0L, 0L); - - // verify total in first hour - assertValues(stats, TEST_START, TEST_START + HOUR_IN_MILLIS, 100L, 200L); - - // verify total across 1.5 hours - assertValues(stats, TEST_START, TEST_START + (long) (1.5 * HOUR_IN_MILLIS), 150L, 300L); - - // verify total beyond end - assertValues(stats, TEST_START + (23 * HOUR_IN_MILLIS), TEST_START + WEEK_IN_MILLIS, 100L, 200L); - - // verify everything total - assertValues(stats, TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, 2400L, 4800L); - - } - - @Test - public void testFuzzing() throws Exception { - try { - // fuzzing with random events, looking for crashes - final NetworkStats.Entry entry = new NetworkStats.Entry(); - final Random r = new Random(); - for (int i = 0; i < 500; i++) { - stats = new NetworkStatsHistory(r.nextLong()); - for (int j = 0; j < 10000; j++) { - if (r.nextBoolean()) { - // add range - final long start = r.nextLong(); - final long end = start + r.nextInt(); - entry.rxBytes = nextPositiveLong(r); - entry.rxPackets = nextPositiveLong(r); - entry.txBytes = nextPositiveLong(r); - entry.txPackets = nextPositiveLong(r); - entry.operations = nextPositiveLong(r); - stats.recordData(start, end, entry); - } else { - // trim something - stats.removeBucketsBefore(r.nextLong()); - } - } - assertConsistent(stats); - } - } catch (Throwable e) { - Log.e(TAG, String.valueOf(stats)); - throw new RuntimeException(e); - } - } - - private static long nextPositiveLong(Random r) { - final long value = r.nextLong(); - return value < 0 ? -value : value; - } - - @Test - public void testIgnoreFields() throws Exception { - final NetworkStatsHistory history = new NetworkStatsHistory( - MINUTE_IN_MILLIS, 0, FIELD_RX_BYTES | FIELD_TX_BYTES); - - history.recordData(0, MINUTE_IN_MILLIS, - new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 4L)); - history.recordData(0, 2 * MINUTE_IN_MILLIS, - new NetworkStats.Entry(2L, 2L, 2L, 2L, 2L)); - - assertFullValues(history, UNKNOWN, 1026L, UNKNOWN, 2050L, UNKNOWN, UNKNOWN); - } - - @Test - public void testIgnoreFieldsRecordIn() throws Exception { - final NetworkStatsHistory full = new NetworkStatsHistory(MINUTE_IN_MILLIS, 0, FIELD_ALL); - final NetworkStatsHistory partial = new NetworkStatsHistory( - MINUTE_IN_MILLIS, 0, FIELD_RX_PACKETS | FIELD_OPERATIONS); - - full.recordData(0, MINUTE_IN_MILLIS, - new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 4L)); - partial.recordEntireHistory(full); - - assertFullValues(partial, UNKNOWN, UNKNOWN, 10L, UNKNOWN, UNKNOWN, 4L); - } - - @Test - public void testIgnoreFieldsRecordOut() throws Exception { - final NetworkStatsHistory full = new NetworkStatsHistory(MINUTE_IN_MILLIS, 0, FIELD_ALL); - final NetworkStatsHistory partial = new NetworkStatsHistory( - MINUTE_IN_MILLIS, 0, FIELD_RX_PACKETS | FIELD_OPERATIONS); - - partial.recordData(0, MINUTE_IN_MILLIS, - new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 4L)); - full.recordEntireHistory(partial); - - assertFullValues(full, MINUTE_IN_MILLIS, 0L, 10L, 0L, 0L, 4L); - } - - @Test - public void testSerialize() throws Exception { - final NetworkStatsHistory before = new NetworkStatsHistory(MINUTE_IN_MILLIS, 40, FIELD_ALL); - before.recordData(0, 4 * MINUTE_IN_MILLIS, - new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 4L)); - before.recordData(DAY_IN_MILLIS, DAY_IN_MILLIS + MINUTE_IN_MILLIS, - new NetworkStats.Entry(10L, 20L, 30L, 40L, 50L)); - - final ByteArrayOutputStream out = new ByteArrayOutputStream(); - before.writeToStream(new DataOutputStream(out)); - out.close(); - - final ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); - final NetworkStatsHistory after = new NetworkStatsHistory(new DataInputStream(in)); - - // must have identical totals before and after - assertFullValues(before, 5 * MINUTE_IN_MILLIS, 1034L, 30L, 2078L, 60L, 54L); - assertFullValues(after, 5 * MINUTE_IN_MILLIS, 1034L, 30L, 2078L, 60L, 54L); - } - - @Test - public void testVarLong() throws Exception { - assertEquals(0L, performVarLong(0L)); - assertEquals(-1L, performVarLong(-1L)); - assertEquals(1024L, performVarLong(1024L)); - assertEquals(-1024L, performVarLong(-1024L)); - assertEquals(40 * MB_IN_BYTES, performVarLong(40 * MB_IN_BYTES)); - assertEquals(512 * GB_IN_BYTES, performVarLong(512 * GB_IN_BYTES)); - assertEquals(Long.MIN_VALUE, performVarLong(Long.MIN_VALUE)); - assertEquals(Long.MAX_VALUE, performVarLong(Long.MAX_VALUE)); - assertEquals(Long.MIN_VALUE + 40, performVarLong(Long.MIN_VALUE + 40)); - assertEquals(Long.MAX_VALUE - 40, performVarLong(Long.MAX_VALUE - 40)); - } - - @Test - public void testIndexBeforeAfter() throws Exception { - final long BUCKET_SIZE = HOUR_IN_MILLIS; - stats = new NetworkStatsHistory(BUCKET_SIZE); - - final long FIRST_START = TEST_START; - final long FIRST_END = FIRST_START + (2 * HOUR_IN_MILLIS); - final long SECOND_START = TEST_START + WEEK_IN_MILLIS; - final long SECOND_END = SECOND_START + HOUR_IN_MILLIS; - final long THIRD_START = TEST_START + (2 * WEEK_IN_MILLIS); - final long THIRD_END = THIRD_START + (2 * HOUR_IN_MILLIS); - - stats.recordData(FIRST_START, FIRST_END, - new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 2L)); - stats.recordData(SECOND_START, SECOND_END, - new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 2L)); - stats.recordData(THIRD_START, THIRD_END, - new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 2L)); - - // should have buckets: 2+1+2 - assertEquals(5, stats.size()); - - assertIndexBeforeAfter(stats, 0, 0, Long.MIN_VALUE); - assertIndexBeforeAfter(stats, 0, 1, FIRST_START); - assertIndexBeforeAfter(stats, 0, 1, FIRST_START + MINUTE_IN_MILLIS); - assertIndexBeforeAfter(stats, 0, 2, FIRST_START + HOUR_IN_MILLIS); - assertIndexBeforeAfter(stats, 1, 2, FIRST_START + HOUR_IN_MILLIS + MINUTE_IN_MILLIS); - assertIndexBeforeAfter(stats, 1, 2, FIRST_END - MINUTE_IN_MILLIS); - assertIndexBeforeAfter(stats, 1, 2, FIRST_END); - assertIndexBeforeAfter(stats, 1, 2, FIRST_END + MINUTE_IN_MILLIS); - assertIndexBeforeAfter(stats, 1, 2, SECOND_START - MINUTE_IN_MILLIS); - assertIndexBeforeAfter(stats, 1, 3, SECOND_START); - assertIndexBeforeAfter(stats, 2, 3, SECOND_END); - assertIndexBeforeAfter(stats, 2, 3, SECOND_END + MINUTE_IN_MILLIS); - assertIndexBeforeAfter(stats, 2, 3, THIRD_START - MINUTE_IN_MILLIS); - assertIndexBeforeAfter(stats, 2, 4, THIRD_START); - assertIndexBeforeAfter(stats, 3, 4, THIRD_START + MINUTE_IN_MILLIS); - assertIndexBeforeAfter(stats, 3, 4, THIRD_START + HOUR_IN_MILLIS); - assertIndexBeforeAfter(stats, 4, 4, THIRD_END); - assertIndexBeforeAfter(stats, 4, 4, THIRD_END + MINUTE_IN_MILLIS); - assertIndexBeforeAfter(stats, 4, 4, Long.MAX_VALUE); - } - - @Test - public void testIntersects() throws Exception { - final long BUCKET_SIZE = HOUR_IN_MILLIS; - stats = new NetworkStatsHistory(BUCKET_SIZE); - - final long FIRST_START = TEST_START; - final long FIRST_END = FIRST_START + (2 * HOUR_IN_MILLIS); - final long SECOND_START = TEST_START + WEEK_IN_MILLIS; - final long SECOND_END = SECOND_START + HOUR_IN_MILLIS; - final long THIRD_START = TEST_START + (2 * WEEK_IN_MILLIS); - final long THIRD_END = THIRD_START + (2 * HOUR_IN_MILLIS); - - stats.recordData(FIRST_START, FIRST_END, - new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 2L)); - stats.recordData(SECOND_START, SECOND_END, - new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 2L)); - stats.recordData(THIRD_START, THIRD_END, - new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 2L)); - - assertFalse(stats.intersects(10, 20)); - assertFalse(stats.intersects(TEST_START + YEAR_IN_MILLIS, TEST_START + YEAR_IN_MILLIS + 1)); - assertFalse(stats.intersects(Long.MAX_VALUE, Long.MIN_VALUE)); - - assertTrue(stats.intersects(Long.MIN_VALUE, Long.MAX_VALUE)); - assertTrue(stats.intersects(10, TEST_START + YEAR_IN_MILLIS)); - assertTrue(stats.intersects(TEST_START, TEST_START)); - assertTrue(stats.intersects(TEST_START + DAY_IN_MILLIS, TEST_START + DAY_IN_MILLIS + 1)); - assertTrue(stats.intersects(TEST_START + DAY_IN_MILLIS, Long.MAX_VALUE)); - assertTrue(stats.intersects(TEST_START + 1, Long.MAX_VALUE)); - - assertFalse(stats.intersects(Long.MIN_VALUE, TEST_START - 1)); - assertTrue(stats.intersects(Long.MIN_VALUE, TEST_START)); - assertTrue(stats.intersects(Long.MIN_VALUE, TEST_START + 1)); - } - - @Test - public void testSetValues() throws Exception { - stats = new NetworkStatsHistory(HOUR_IN_MILLIS); - stats.recordData(TEST_START, TEST_START + 1, - new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 2L)); - - assertEquals(1024L + 2048L, stats.getTotalBytes()); - - final NetworkStatsHistory.Entry entry = stats.getValues(0, null); - entry.rxBytes /= 2; - entry.txBytes *= 2; - stats.setValues(0, entry); - - assertEquals(512L + 4096L, stats.getTotalBytes()); - } - - private static void assertIndexBeforeAfter( - NetworkStatsHistory stats, int before, int after, long time) { - assertEquals("unexpected before", before, stats.getIndexBefore(time)); - assertEquals("unexpected after", after, stats.getIndexAfter(time)); - } - - private static long performVarLong(long before) throws Exception { - final ByteArrayOutputStream out = new ByteArrayOutputStream(); - writeVarLong(new DataOutputStream(out), before); - - final ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); - return readVarLong(new DataInputStream(in)); - } - - private static void assertConsistent(NetworkStatsHistory stats) { - // verify timestamps are monotonic - long lastStart = Long.MIN_VALUE; - NetworkStatsHistory.Entry entry = null; - for (int i = 0; i < stats.size(); i++) { - entry = stats.getValues(i, entry); - assertTrue(lastStart < entry.bucketStart); - lastStart = entry.bucketStart; - } - } - - private static void assertValues( - NetworkStatsHistory stats, int index, long rxBytes, long txBytes) { - final NetworkStatsHistory.Entry entry = stats.getValues(index, null); - assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); - assertEquals("unexpected txBytes", txBytes, entry.txBytes); - } - - private static void assertValues( - NetworkStatsHistory stats, long start, long end, long rxBytes, long txBytes) { - final NetworkStatsHistory.Entry entry = stats.getValues(start, end, null); - assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); - assertEquals("unexpected txBytes", txBytes, entry.txBytes); - } - - private static void assertValues(NetworkStatsHistory stats, int index, long activeTime, - long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { - final NetworkStatsHistory.Entry entry = stats.getValues(index, null); - assertEquals("unexpected activeTime", activeTime, entry.activeTime); - assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); - assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets); - assertEquals("unexpected txBytes", txBytes, entry.txBytes); - assertEquals("unexpected txPackets", txPackets, entry.txPackets); - assertEquals("unexpected operations", operations, entry.operations); - } - - private static void assertFullValues(NetworkStatsHistory stats, long activeTime, long rxBytes, - long rxPackets, long txBytes, long txPackets, long operations) { - assertValues(stats, Long.MIN_VALUE, Long.MAX_VALUE, activeTime, rxBytes, rxPackets, txBytes, - txPackets, operations); - } - - private static void assertValues(NetworkStatsHistory stats, long start, long end, - long activeTime, long rxBytes, long rxPackets, long txBytes, long txPackets, - long operations) { - final NetworkStatsHistory.Entry entry = stats.getValues(start, end, null); - assertEquals("unexpected activeTime", activeTime, entry.activeTime); - assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); - assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets); - assertEquals("unexpected txBytes", txBytes, entry.txBytes); - assertEquals("unexpected txPackets", txPackets, entry.txPackets); - assertEquals("unexpected operations", operations, entry.operations); - } -} diff --git a/packages/Connectivity/tests/unit/java/android/net/NetworkStatsTest.java b/packages/Connectivity/tests/unit/java/android/net/NetworkStatsTest.java deleted file mode 100644 index 23d5a7e5d5f89..0000000000000 --- a/packages/Connectivity/tests/unit/java/android/net/NetworkStatsTest.java +++ /dev/null @@ -1,1024 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; -import static android.net.NetworkStats.DEFAULT_NETWORK_NO; -import static android.net.NetworkStats.DEFAULT_NETWORK_YES; -import static android.net.NetworkStats.IFACE_ALL; -import static android.net.NetworkStats.INTERFACES_ALL; -import static android.net.NetworkStats.METERED_ALL; -import static android.net.NetworkStats.METERED_NO; -import static android.net.NetworkStats.METERED_YES; -import static android.net.NetworkStats.ROAMING_ALL; -import static android.net.NetworkStats.ROAMING_NO; -import static android.net.NetworkStats.ROAMING_YES; -import static android.net.NetworkStats.SET_ALL; -import static android.net.NetworkStats.SET_DBG_VPN_IN; -import static android.net.NetworkStats.SET_DBG_VPN_OUT; -import static android.net.NetworkStats.SET_DEFAULT; -import static android.net.NetworkStats.SET_FOREGROUND; -import static android.net.NetworkStats.TAG_ALL; -import static android.net.NetworkStats.TAG_NONE; -import static android.net.NetworkStats.UID_ALL; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import android.os.Process; -import android.util.ArrayMap; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.google.android.collect.Sets; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.Arrays; -import java.util.HashSet; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class NetworkStatsTest { - - private static final String TEST_IFACE = "test0"; - private static final String TEST_IFACE2 = "test2"; - private static final int TEST_UID = 1001; - private static final long TEST_START = 1194220800000L; - - @Test - public void testFindIndex() throws Exception { - final NetworkStats stats = new NetworkStats(TEST_START, 5) - .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 1024L, 8L, 0L, 0L, 10) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 0L, 0L, 1024L, 8L, 11) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, - DEFAULT_NETWORK_YES, 0L, 0L, 1024L, 8L, 11) - .insertEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 1024L, 8L, 1024L, 8L, 12) - .insertEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES, - DEFAULT_NETWORK_YES, 1024L, 8L, 1024L, 8L, 12); - - assertEquals(4, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_YES, - ROAMING_YES, DEFAULT_NETWORK_YES)); - assertEquals(3, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO)); - assertEquals(2, stats.findIndex(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, - ROAMING_NO, DEFAULT_NETWORK_YES)); - assertEquals(1, stats.findIndex(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO)); - assertEquals(0, stats.findIndex(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_YES)); - assertEquals(-1, stats.findIndex(TEST_IFACE, 6, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO)); - assertEquals(-1, stats.findIndex(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO)); - } - - @Test - public void testFindIndexHinted() { - final NetworkStats stats = new NetworkStats(TEST_START, 3) - .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 1024L, 8L, 0L, 0L, 10) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 0L, 0L, 1024L, 8L, 11) - .insertEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 1024L, 8L, 1024L, 8L, 12) - .insertEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 1024L, 8L, 0L, 0L, 10) - .insertEntry(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 0L, 0L, 1024L, 8L, 11) - .insertEntry(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO, - DEFAULT_NETWORK_NO, 0L, 0L, 1024L, 8L, 11) - .insertEntry(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 1024L, 8L, 1024L, 8L, 12) - .insertEntry(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES, - DEFAULT_NETWORK_NO, 1024L, 8L, 1024L, 8L, 12); - - // verify that we correctly find across regardless of hinting - for (int hint = 0; hint < stats.size(); hint++) { - assertEquals(0, stats.findIndexHinted(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, hint)); - assertEquals(1, stats.findIndexHinted(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, hint)); - assertEquals(2, stats.findIndexHinted(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, hint)); - assertEquals(3, stats.findIndexHinted(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, hint)); - assertEquals(4, stats.findIndexHinted(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, hint)); - assertEquals(5, stats.findIndexHinted(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, - METERED_YES, ROAMING_NO, DEFAULT_NETWORK_NO, hint)); - assertEquals(6, stats.findIndexHinted(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, hint)); - assertEquals(7, stats.findIndexHinted(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, - METERED_YES, ROAMING_YES, DEFAULT_NETWORK_NO, hint)); - assertEquals(-1, stats.findIndexHinted(TEST_IFACE, 6, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, hint)); - assertEquals(-1, stats.findIndexHinted(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, - METERED_YES, ROAMING_YES, DEFAULT_NETWORK_YES, hint)); - } - } - - @Test - public void testAddEntryGrow() throws Exception { - final NetworkStats stats = new NetworkStats(TEST_START, 4); - - assertEquals(0, stats.size()); - assertEquals(4, stats.internalSize()); - - stats.insertEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 1L, 1L, 2L, 2L, 3); - stats.insertEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 2L, 2L, 2L, 2L, 4); - stats.insertEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, - DEFAULT_NETWORK_YES, 3L, 3L, 2L, 2L, 5); - stats.insertEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES, - DEFAULT_NETWORK_NO, 3L, 3L, 2L, 2L, 5); - - assertEquals(4, stats.size()); - assertEquals(4, stats.internalSize()); - - stats.insertEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 4L, 40L, 4L, 40L, 7); - stats.insertEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 5L, 50L, 4L, 40L, 8); - stats.insertEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 6L, 60L, 5L, 50L, 10); - stats.insertEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, - DEFAULT_NETWORK_YES, 7L, 70L, 5L, 50L, 11); - stats.insertEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES, - DEFAULT_NETWORK_NO, 7L, 70L, 5L, 50L, 11); - - assertEquals(9, stats.size()); - assertTrue(stats.internalSize() >= 9); - - assertValues(stats, 0, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 1L, 1L, 2L, 2L, 3); - assertValues(stats, 1, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 2L, 2L, 2L, 2L, 4); - assertValues(stats, 2, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, - DEFAULT_NETWORK_YES, 3L, 3L, 2L, 2L, 5); - assertValues(stats, 3, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, - ROAMING_YES, DEFAULT_NETWORK_NO, 3L, 3L, 2L, 2L, 5); - assertValues(stats, 4, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 4L, 40L, 4L, 40L, 7); - assertValues(stats, 5, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 5L, 50L, 4L, 40L, 8); - assertValues(stats, 6, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 6L, 60L, 5L, 50L, 10); - assertValues(stats, 7, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, - DEFAULT_NETWORK_YES, 7L, 70L, 5L, 50L, 11); - assertValues(stats, 8, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, - ROAMING_YES, DEFAULT_NETWORK_NO, 7L, 70L, 5L, 50L, 11); - } - - @Test - public void testCombineExisting() throws Exception { - final NetworkStats stats = new NetworkStats(TEST_START, 10); - - stats.insertEntry(TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 10); - stats.insertEntry(TEST_IFACE, 1001, SET_DEFAULT, 0xff, 128L, 1L, 128L, 1L, 2); - stats.combineValues(TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, -128L, -1L, - -128L, -1L, -1); - - assertValues(stats, 0, TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 384L, 3L, 128L, 1L, 9); - assertValues(stats, 1, TEST_IFACE, 1001, SET_DEFAULT, 0xff, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 128L, 1L, 128L, 1L, 2); - - // now try combining that should create row - stats.combineValues(TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 3); - assertValues(stats, 2, TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 128L, 1L, 128L, 1L, 3); - stats.combineValues(TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 3); - assertValues(stats, 2, TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 256L, 2L, 256L, 2L, 6); - } - - @Test - public void testSubtractIdenticalData() throws Exception { - final NetworkStats before = new NetworkStats(TEST_START, 2) - .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12); - - final NetworkStats after = new NetworkStats(TEST_START, 2) - .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12); - - final NetworkStats result = after.subtract(before); - - // identical data should result in zero delta - assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0); - assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0); - } - - @Test - public void testSubtractIdenticalRows() throws Exception { - final NetworkStats before = new NetworkStats(TEST_START, 2) - .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12); - - final NetworkStats after = new NetworkStats(TEST_START, 2) - .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1025L, 9L, 2L, 1L, 15) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 3L, 1L, 1028L, 9L, 20); - - final NetworkStats result = after.subtract(before); - - // expect delta between measurements - assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 1L, 1L, 2L, 1L, 4); - assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 3L, 1L, 4L, 1L, 8); - } - - @Test - public void testSubtractNewRows() throws Exception { - final NetworkStats before = new NetworkStats(TEST_START, 2) - .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12); - - final NetworkStats after = new NetworkStats(TEST_START, 3) - .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12) - .insertEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 20); - - final NetworkStats result = after.subtract(before); - - // its okay to have new rows - assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0); - assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0); - assertValues(result, 2, TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 1024L, 8L, 1024L, 8L, 20); - } - - @Test - public void testSubtractMissingRows() throws Exception { - final NetworkStats before = new NetworkStats(TEST_START, 2) - .insertEntry(TEST_IFACE, UID_ALL, SET_DEFAULT, TAG_NONE, 1024L, 0L, 0L, 0L, 0) - .insertEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 2048L, 0L, 0L, 0L, 0); - - final NetworkStats after = new NetworkStats(TEST_START, 1) - .insertEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 2049L, 2L, 3L, 4L, 0); - - final NetworkStats result = after.subtract(before); - - // should silently drop omitted rows - assertEquals(1, result.size()); - assertValues(result, 0, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO, 1L, 2L, 3L, 4L, 0); - assertEquals(4L, result.getTotalBytes()); - } - - @Test - public void testTotalBytes() throws Exception { - final NetworkStats iface = new NetworkStats(TEST_START, 2) - .insertEntry(TEST_IFACE, UID_ALL, SET_DEFAULT, TAG_NONE, 128L, 0L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 256L, 0L, 0L, 0L, 0L); - assertEquals(384L, iface.getTotalBytes()); - - final NetworkStats uidSet = new NetworkStats(TEST_START, 3) - .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE, 101, SET_FOREGROUND, TAG_NONE, 32L, 0L, 0L, 0L, 0L); - assertEquals(96L, uidSet.getTotalBytes()); - - final NetworkStats uidTag = new NetworkStats(TEST_START, 6) - .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 16L, 0L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L); - assertEquals(64L, uidTag.getTotalBytes()); - - final NetworkStats uidMetered = new NetworkStats(TEST_START, 3) - .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, - DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, - DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L); - assertEquals(96L, uidMetered.getTotalBytes()); - - final NetworkStats uidRoaming = new NetworkStats(TEST_START, 3) - .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, - DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, - DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L); - assertEquals(96L, uidRoaming.getTotalBytes()); - } - - @Test - public void testGroupedByIfaceEmpty() throws Exception { - final NetworkStats uidStats = new NetworkStats(TEST_START, 3); - final NetworkStats grouped = uidStats.groupedByIface(); - - assertEquals(0, uidStats.size()); - assertEquals(0, grouped.size()); - } - - @Test - public void testGroupedByIfaceAll() throws Exception { - final NetworkStats uidStats = new NetworkStats(TEST_START, 3) - .insertEntry(IFACE_ALL, 100, SET_ALL, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 128L, 8L, 0L, 2L, 20L) - .insertEntry(IFACE_ALL, 101, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_NO, - DEFAULT_NETWORK_NO, 128L, 8L, 0L, 2L, 20L) - .insertEntry(IFACE_ALL, 101, SET_ALL, TAG_NONE, METERED_NO, ROAMING_YES, - DEFAULT_NETWORK_YES, 128L, 8L, 0L, 2L, 20L); - final NetworkStats grouped = uidStats.groupedByIface(); - - assertEquals(3, uidStats.size()); - assertEquals(1, grouped.size()); - - assertValues(grouped, 0, IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, - DEFAULT_NETWORK_ALL, 384L, 24L, 0L, 6L, 0L); - } - - @Test - public void testGroupedByIface() throws Exception { - final NetworkStats uidStats = new NetworkStats(TEST_START, 7) - .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 128L, 8L, 0L, 2L, 20L) - .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 512L, 32L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 64L, 4L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 512L, 32L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 128L, 8L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO, - DEFAULT_NETWORK_NO, 128L, 8L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, - DEFAULT_NETWORK_YES, 128L, 8L, 0L, 0L, 0L); - - final NetworkStats grouped = uidStats.groupedByIface(); - - assertEquals(7, uidStats.size()); - - assertEquals(2, grouped.size()); - assertValues(grouped, 0, TEST_IFACE, UID_ALL, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, - DEFAULT_NETWORK_ALL, 384L, 24L, 0L, 2L, 0L); - assertValues(grouped, 1, TEST_IFACE2, UID_ALL, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, - DEFAULT_NETWORK_ALL, 1024L, 64L, 0L, 0L, 0L); - } - - @Test - public void testAddAllValues() { - final NetworkStats first = new NetworkStats(TEST_START, 5) - .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, - DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES, - DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L); - - final NetworkStats second = new NetworkStats(TEST_START, 2) - .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, - DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES, - DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L); - - first.combineAllValues(second); - - assertEquals(4, first.size()); - assertValues(first, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, - DEFAULT_NETWORK_YES, 64L, 0L, 0L, 0L, 0L); - assertValues(first, 1, TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L); - assertValues(first, 2, TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES, - DEFAULT_NETWORK_YES, 64L, 0L, 0L, 0L, 0L); - assertValues(first, 3, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L); - } - - @Test - public void testGetTotal() { - final NetworkStats stats = new NetworkStats(TEST_START, 7) - .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 128L, 8L, 0L, 2L, 20L) - .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 512L, 32L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 64L, 4L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 512L,32L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, - DEFAULT_NETWORK_YES, 128L, 8L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 128L, 8L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, - DEFAULT_NETWORK_NO, 128L, 8L, 0L, 0L, 0L); - - assertValues(stats.getTotal(null), 1408L, 88L, 0L, 2L, 20L); - assertValues(stats.getTotal(null, 100), 1280L, 80L, 0L, 2L, 20L); - assertValues(stats.getTotal(null, 101), 128L, 8L, 0L, 0L, 0L); - - final HashSet ifaces = Sets.newHashSet(); - assertValues(stats.getTotal(null, ifaces), 0L, 0L, 0L, 0L, 0L); - - ifaces.add(TEST_IFACE2); - assertValues(stats.getTotal(null, ifaces), 1024L, 64L, 0L, 0L, 0L); - } - - @Test - public void testRemoveUids() throws Exception { - final NetworkStats before = new NetworkStats(TEST_START, 3); - - // Test 0 item stats. - NetworkStats after = before.clone(); - after.removeUids(new int[0]); - assertEquals(0, after.size()); - after.removeUids(new int[] {100}); - assertEquals(0, after.size()); - - // Test 1 item stats. - before.insertEntry(TEST_IFACE, 99, SET_DEFAULT, TAG_NONE, 1L, 128L, 0L, 2L, 20L); - after = before.clone(); - after.removeUids(new int[0]); - assertEquals(1, after.size()); - assertValues(after, 0, TEST_IFACE, 99, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 1L, 128L, 0L, 2L, 20L); - after.removeUids(new int[] {99}); - assertEquals(0, after.size()); - - // Append remaining test items. - before.insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 2L, 64L, 0L, 2L, 20L) - .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 4L, 32L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 8L, 16L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 16L, 8L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 32L, 4L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 64L, 2L, 0L, 0L, 0L); - assertEquals(7, before.size()); - - // Test remove with empty uid list. - after = before.clone(); - after.removeUids(new int[0]); - assertValues(after.getTotalIncludingTags(null), 127L, 254L, 0L, 4L, 40L); - - // Test remove uids don't exist in stats. - after.removeUids(new int[] {98, 0, Integer.MIN_VALUE, Integer.MAX_VALUE}); - assertValues(after.getTotalIncludingTags(null), 127L, 254L, 0L, 4L, 40L); - - // Test remove all uids. - after.removeUids(new int[] {99, 100, 100, 101}); - assertEquals(0, after.size()); - - // Test remove in the middle. - after = before.clone(); - after.removeUids(new int[] {100}); - assertEquals(3, after.size()); - assertValues(after, 0, TEST_IFACE, 99, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 1L, 128L, 0L, 2L, 20L); - assertValues(after, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 32L, 4L, 0L, 0L, 0L); - assertValues(after, 2, TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 64L, 2L, 0L, 0L, 0L); - } - - @Test - public void testRemoveEmptyEntries() throws Exception { - // Test empty stats. - final NetworkStats statsEmpty = new NetworkStats(TEST_START, 3); - assertEquals(0, statsEmpty.removeEmptyEntries().size()); - - // Test stats with non-zero entry. - final NetworkStats statsNonZero = new NetworkStats(TEST_START, 1) - .insertEntry(TEST_IFACE, 99, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO, 1L, 128L, 0L, 2L, 20L); - assertEquals(1, statsNonZero.size()); - final NetworkStats expectedNonZero = statsNonZero.removeEmptyEntries(); - assertEquals(1, expectedNonZero.size()); - assertValues(expectedNonZero, 0, TEST_IFACE, 99, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO, 1L, 128L, 0L, 2L, 20L); - - // Test stats with empty entry. - final NetworkStats statsZero = new NetworkStats(TEST_START, 1) - .insertEntry(TEST_IFACE, 99, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L); - assertEquals(1, statsZero.size()); - final NetworkStats expectedZero = statsZero.removeEmptyEntries(); - assertEquals(1, statsZero.size()); // Assert immutable. - assertEquals(0, expectedZero.size()); - - // Test stats with multiple entries. - final NetworkStats statsMultiple = new NetworkStats(TEST_START, 0) - .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 2L, 64L, 0L, 2L, 20L) - .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 4L, 32L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 0L, 0L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 0L, 0L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 0L, 8L, 0L, 0L, 0L) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 4L, 0L, 0L) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 0L, 0L, 0L, 2L, 0L) - .insertEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 0L, 0L, 0L, 0L, 1L); - assertEquals(9, statsMultiple.size()); - final NetworkStats expectedMultiple = statsMultiple.removeEmptyEntries(); - assertEquals(9, statsMultiple.size()); // Assert immutable. - assertEquals(7, expectedMultiple.size()); - assertValues(expectedMultiple.getTotalIncludingTags(null), 14L, 104L, 4L, 4L, 21L); - - // Test stats with multiple empty entries. - assertEquals(statsMultiple.size(), statsMultiple.subtract(statsMultiple).size()); - assertEquals(0, statsMultiple.subtract(statsMultiple).removeEmptyEntries().size()); - } - - @Test - public void testClone() throws Exception { - final NetworkStats original = new NetworkStats(TEST_START, 5) - .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L) - .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 512L, 32L, 0L, 0L, 0L); - - // make clone and mutate original - final NetworkStats clone = original.clone(); - original.insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 0L, 0L); - - assertEquals(3, original.size()); - assertEquals(2, clone.size()); - - assertEquals(128L + 512L + 128L, original.getTotalBytes()); - assertEquals(128L + 512L, clone.getTotalBytes()); - } - - @Test - public void testAddWhenEmpty() throws Exception { - final NetworkStats red = new NetworkStats(TEST_START, -1); - final NetworkStats blue = new NetworkStats(TEST_START, 5) - .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L) - .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 512L, 32L, 0L, 0L, 0L); - - // We're mostly checking that we don't crash - red.combineAllValues(blue); - } - - @Test - public void testMigrateTun() throws Exception { - final int tunUid = 10030; - final String tunIface = "tun0"; - final String underlyingIface = "wlan0"; - final int testTag1 = 8888; - NetworkStats delta = new NetworkStats(TEST_START, 17) - .insertEntry(tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 39605L, 46L, 12259L, 55L, 0L) - .insertEntry(tunIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L) - .insertEntry(tunIface, 10120, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 72667L, 197L, 43909L, 241L, 0L) - .insertEntry(tunIface, 10120, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 9297L, 17L, 4128L, 21L, 0L) - // VPN package also uses some traffic through unprotected network. - .insertEntry(tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 4983L, 10L, 1801L, 12L, 0L) - .insertEntry(tunIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L) - // Tag entries - .insertEntry(tunIface, 10120, SET_DEFAULT, testTag1, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 21691L, 41L, 13820L, 51L, 0L) - .insertEntry(tunIface, 10120, SET_FOREGROUND, testTag1, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 1281L, 2L, 665L, 2L, 0L) - // Irrelevant entries - .insertEntry(TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 1685L, 5L, 2070L, 6L, 0L) - // Underlying Iface entries - .insertEntry(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 5178L, 8L, 2139L, 11L, 0L) - .insertEntry(underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L) - .insertEntry(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 149873L, 287L, 59217L /* smaller than sum(tun0) */, - 299L /* smaller than sum(tun0) */, 0L) - .insertEntry(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L); - - delta.migrateTun(tunUid, tunIface, Arrays.asList(underlyingIface)); - assertEquals(20, delta.size()); - - // tunIface and TEST_IFACE entries are not changed. - assertValues(delta, 0, tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 39605L, 46L, 12259L, 55L, 0L); - assertValues(delta, 1, tunIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L); - assertValues(delta, 2, tunIface, 10120, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 72667L, 197L, 43909L, 241L, 0L); - assertValues(delta, 3, tunIface, 10120, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 9297L, 17L, 4128L, 21L, 0L); - assertValues(delta, 4, tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 4983L, 10L, 1801L, 12L, 0L); - assertValues(delta, 5, tunIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L); - assertValues(delta, 6, tunIface, 10120, SET_DEFAULT, testTag1, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 21691L, 41L, 13820L, 51L, 0L); - assertValues(delta, 7, tunIface, 10120, SET_FOREGROUND, testTag1, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 1281L, 2L, 665L, 2L, 0L); - assertValues(delta, 8, TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 1685L, 5L, 2070L, 6L, 0L); - - // Existing underlying Iface entries are updated - assertValues(delta, 9, underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO, 44783L, 54L, 14178L, 62L, 0L); - assertValues(delta, 10, underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L); - - // VPN underlying Iface entries are updated - assertValues(delta, 11, underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO, 28304L, 27L, 1L, 2L, 0L); - assertValues(delta, 12, underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L); - - // New entries are added for new application's underlying Iface traffic - assertContains(delta, underlyingIface, 10120, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO, 72667L, 197L, 43123L, 227L, 0L); - assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO, 9297L, 17L, 4054, 19L, 0L); - assertContains(delta, underlyingIface, 10120, SET_DEFAULT, testTag1, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO, 21691L, 41L, 13572L, 48L, 0L); - assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, testTag1, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO, 1281L, 2L, 653L, 1L, 0L); - - // New entries are added for debug purpose - assertContains(delta, underlyingIface, 10100, SET_DBG_VPN_IN, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO, 39605L, 46L, 12039, 51, 0); - assertContains(delta, underlyingIface, 10120, SET_DBG_VPN_IN, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO, 81964, 214, 47177, 246, 0); - assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_OUT, TAG_NONE, METERED_ALL, - ROAMING_ALL, DEFAULT_NETWORK_ALL, 121569, 260, 59216, 297, 0); - - } - - // Tests a case where all of the data received by the tun0 interface is echo back into the tun0 - // interface by the vpn app before it's sent out of the underlying interface. The VPN app should - // not be charged for the echoed data but it should still be charged for any extra data it sends - // via the underlying interface. - @Test - public void testMigrateTun_VpnAsLoopback() { - final int tunUid = 10030; - final String tunIface = "tun0"; - final String underlyingIface = "wlan0"; - NetworkStats delta = new NetworkStats(TEST_START, 9) - // 2 different apps sent/receive data via tun0. - .insertEntry(tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L) - .insertEntry(tunIface, 20100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 500L, 2L, 200L, 5L, 0L) - // VPN package resends data through the tunnel (with exaggerated overhead) - .insertEntry(tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 240000, 100L, 120000L, 60L, 0L) - // 1 app already has some traffic on the underlying interface, the other doesn't yet - .insertEntry(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 1000L, 10L, 2000L, 20L, 0L) - // Traffic through the underlying interface via the vpn app. - // This test should redistribute this data correctly. - .insertEntry(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 75500L, 37L, 130000L, 70L, 0L); - - delta.migrateTun(tunUid, tunIface, Arrays.asList(underlyingIface)); - assertEquals(9, delta.size()); - - // tunIface entries should not be changed. - assertValues(delta, 0, tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); - assertValues(delta, 1, tunIface, 20100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 500L, 2L, 200L, 5L, 0L); - assertValues(delta, 2, tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 240000L, 100L, 120000L, 60L, 0L); - - // Existing underlying Iface entries are updated - assertValues(delta, 3, underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO, 51000L, 35L, 102000L, 70L, 0L); - - // VPN underlying Iface entries are updated - assertValues(delta, 4, underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO, 25000L, 10L, 29800L, 15L, 0L); - - // New entries are added for new application's underlying Iface traffic - assertContains(delta, underlyingIface, 20100, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO, 500L, 2L, 200L, 5L, 0L); - - // New entries are added for debug purpose - assertContains(delta, underlyingIface, 10100, SET_DBG_VPN_IN, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); - assertContains(delta, underlyingIface, 20100, SET_DBG_VPN_IN, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO, 500, 2L, 200L, 5L, 0L); - assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_OUT, TAG_NONE, METERED_ALL, - ROAMING_ALL, DEFAULT_NETWORK_ALL, 50500L, 27L, 100200L, 55, 0); - } - - @Test - public void testFilter_NoFilter() { - NetworkStats.Entry entry1 = new NetworkStats.Entry( - "test1", 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); - - NetworkStats.Entry entry2 = new NetworkStats.Entry( - "test2", 10101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); - - NetworkStats.Entry entry3 = new NetworkStats.Entry( - "test2", 10101, SET_DEFAULT, 123, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); - - NetworkStats stats = new NetworkStats(TEST_START, 3) - .insertEntry(entry1) - .insertEntry(entry2) - .insertEntry(entry3); - - stats.filter(UID_ALL, INTERFACES_ALL, TAG_ALL); - assertEquals(3, stats.size()); - assertEquals(entry1, stats.getValues(0, null)); - assertEquals(entry2, stats.getValues(1, null)); - assertEquals(entry3, stats.getValues(2, null)); - } - - @Test - public void testFilter_UidFilter() { - final int testUid = 10101; - NetworkStats.Entry entry1 = new NetworkStats.Entry( - "test1", 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); - - NetworkStats.Entry entry2 = new NetworkStats.Entry( - "test2", testUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); - - NetworkStats.Entry entry3 = new NetworkStats.Entry( - "test2", testUid, SET_DEFAULT, 123, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); - - NetworkStats stats = new NetworkStats(TEST_START, 3) - .insertEntry(entry1) - .insertEntry(entry2) - .insertEntry(entry3); - - stats.filter(testUid, INTERFACES_ALL, TAG_ALL); - assertEquals(2, stats.size()); - assertEquals(entry2, stats.getValues(0, null)); - assertEquals(entry3, stats.getValues(1, null)); - } - - @Test - public void testFilter_InterfaceFilter() { - final String testIf1 = "testif1"; - final String testIf2 = "testif2"; - NetworkStats.Entry entry1 = new NetworkStats.Entry( - testIf1, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); - - NetworkStats.Entry entry2 = new NetworkStats.Entry( - "otherif", 10101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); - - NetworkStats.Entry entry3 = new NetworkStats.Entry( - testIf1, 10101, SET_DEFAULT, 123, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); - - NetworkStats.Entry entry4 = new NetworkStats.Entry( - testIf2, 10101, SET_DEFAULT, 123, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); - - NetworkStats stats = new NetworkStats(TEST_START, 4) - .insertEntry(entry1) - .insertEntry(entry2) - .insertEntry(entry3) - .insertEntry(entry4); - - stats.filter(UID_ALL, new String[] { testIf1, testIf2 }, TAG_ALL); - assertEquals(3, stats.size()); - assertEquals(entry1, stats.getValues(0, null)); - assertEquals(entry3, stats.getValues(1, null)); - assertEquals(entry4, stats.getValues(2, null)); - } - - @Test - public void testFilter_EmptyInterfaceFilter() { - NetworkStats.Entry entry1 = new NetworkStats.Entry( - "if1", 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); - - NetworkStats.Entry entry2 = new NetworkStats.Entry( - "if2", 10101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); - - NetworkStats stats = new NetworkStats(TEST_START, 3) - .insertEntry(entry1) - .insertEntry(entry2); - - stats.filter(UID_ALL, new String[] { }, TAG_ALL); - assertEquals(0, stats.size()); - } - - @Test - public void testFilter_TagFilter() { - final int testTag = 123; - final int otherTag = 456; - NetworkStats.Entry entry1 = new NetworkStats.Entry( - "test1", 10100, SET_DEFAULT, testTag, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); - - NetworkStats.Entry entry2 = new NetworkStats.Entry( - "test2", 10101, SET_DEFAULT, testTag, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); - - NetworkStats.Entry entry3 = new NetworkStats.Entry( - "test2", 10101, SET_DEFAULT, otherTag, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); - - NetworkStats stats = new NetworkStats(TEST_START, 3) - .insertEntry(entry1) - .insertEntry(entry2) - .insertEntry(entry3); - - stats.filter(UID_ALL, INTERFACES_ALL, testTag); - assertEquals(2, stats.size()); - assertEquals(entry1, stats.getValues(0, null)); - assertEquals(entry2, stats.getValues(1, null)); - } - - @Test - public void testFilterDebugEntries() { - NetworkStats.Entry entry1 = new NetworkStats.Entry( - "test1", 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); - - NetworkStats.Entry entry2 = new NetworkStats.Entry( - "test2", 10101, SET_DBG_VPN_IN, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); - - NetworkStats.Entry entry3 = new NetworkStats.Entry( - "test2", 10101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); - - NetworkStats.Entry entry4 = new NetworkStats.Entry( - "test2", 10101, SET_DBG_VPN_OUT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); - - NetworkStats stats = new NetworkStats(TEST_START, 4) - .insertEntry(entry1) - .insertEntry(entry2) - .insertEntry(entry3) - .insertEntry(entry4); - - stats.filterDebugEntries(); - - assertEquals(2, stats.size()); - assertEquals(entry1, stats.getValues(0, null)); - assertEquals(entry3, stats.getValues(1, null)); - } - - @Test - public void testApply464xlatAdjustments() { - final String v4Iface = "v4-wlan0"; - final String baseIface = "wlan0"; - final String otherIface = "other"; - final int appUid = 10001; - final int rootUid = Process.ROOT_UID; - ArrayMap stackedIface = new ArrayMap<>(); - stackedIface.put(v4Iface, baseIface); - - // Ipv4 traffic sent/received by an app on stacked interface. - final NetworkStats.Entry appEntry = new NetworkStats.Entry( - v4Iface, appUid, SET_DEFAULT, TAG_NONE, - 30501490 /* rxBytes */, - 22401 /* rxPackets */, - 876235 /* txBytes */, - 13805 /* txPackets */, - 0 /* operations */); - - // Traffic measured for the root uid on the base interface. - final NetworkStats.Entry rootUidEntry = new NetworkStats.Entry( - baseIface, rootUid, SET_DEFAULT, TAG_NONE, - 163577 /* rxBytes */, - 187 /* rxPackets */, - 17607 /* txBytes */, - 97 /* txPackets */, - 0 /* operations */); - - final NetworkStats.Entry otherEntry = new NetworkStats.Entry( - otherIface, appUid, SET_DEFAULT, TAG_NONE, - 2600 /* rxBytes */, - 2 /* rxPackets */, - 3800 /* txBytes */, - 3 /* txPackets */, - 0 /* operations */); - - final NetworkStats stats = new NetworkStats(TEST_START, 3) - .insertEntry(appEntry) - .insertEntry(rootUidEntry) - .insertEntry(otherEntry); - - stats.apply464xlatAdjustments(stackedIface); - - assertEquals(3, stats.size()); - final NetworkStats.Entry expectedAppUid = new NetworkStats.Entry( - v4Iface, appUid, SET_DEFAULT, TAG_NONE, - 30949510, - 22401, - 1152335, - 13805, - 0); - final NetworkStats.Entry expectedRootUid = new NetworkStats.Entry( - baseIface, 0, SET_DEFAULT, TAG_NONE, - 163577, - 187, - 17607, - 97, - 0); - assertEquals(expectedAppUid, stats.getValues(0, null)); - assertEquals(expectedRootUid, stats.getValues(1, null)); - assertEquals(otherEntry, stats.getValues(2, null)); - } - - @Test - public void testApply464xlatAdjustments_noStackedIface() { - NetworkStats.Entry firstEntry = new NetworkStats.Entry( - "if1", 10002, SET_DEFAULT, TAG_NONE, - 2600 /* rxBytes */, - 2 /* rxPackets */, - 3800 /* txBytes */, - 3 /* txPackets */, - 0 /* operations */); - NetworkStats.Entry secondEntry = new NetworkStats.Entry( - "if2", 10002, SET_DEFAULT, TAG_NONE, - 5000 /* rxBytes */, - 3 /* rxPackets */, - 6000 /* txBytes */, - 4 /* txPackets */, - 0 /* operations */); - - NetworkStats stats = new NetworkStats(TEST_START, 2) - .insertEntry(firstEntry) - .insertEntry(secondEntry); - - // Empty map: no adjustment - stats.apply464xlatAdjustments(new ArrayMap<>()); - - assertEquals(2, stats.size()); - assertEquals(firstEntry, stats.getValues(0, null)); - assertEquals(secondEntry, stats.getValues(1, null)); - } - - private static void assertContains(NetworkStats stats, String iface, int uid, int set, - int tag, int metered, int roaming, int defaultNetwork, long rxBytes, long rxPackets, - long txBytes, long txPackets, long operations) { - int index = stats.findIndex(iface, uid, set, tag, metered, roaming, defaultNetwork); - assertTrue(index != -1); - assertValues(stats, index, iface, uid, set, tag, metered, roaming, defaultNetwork, - rxBytes, rxPackets, txBytes, txPackets, operations); - } - - private static void assertValues(NetworkStats stats, int index, String iface, int uid, int set, - int tag, int metered, int roaming, int defaultNetwork, long rxBytes, long rxPackets, - long txBytes, long txPackets, long operations) { - final NetworkStats.Entry entry = stats.getValues(index, null); - assertValues(entry, iface, uid, set, tag, metered, roaming, defaultNetwork); - assertValues(entry, rxBytes, rxPackets, txBytes, txPackets, operations); - } - - private static void assertValues( - NetworkStats.Entry entry, String iface, int uid, int set, int tag, int metered, - int roaming, int defaultNetwork) { - assertEquals(iface, entry.iface); - assertEquals(uid, entry.uid); - assertEquals(set, entry.set); - assertEquals(tag, entry.tag); - assertEquals(metered, entry.metered); - assertEquals(roaming, entry.roaming); - assertEquals(defaultNetwork, entry.defaultNetwork); - } - - private static void assertValues(NetworkStats.Entry entry, long rxBytes, long rxPackets, - long txBytes, long txPackets, long operations) { - assertEquals(rxBytes, entry.rxBytes); - assertEquals(rxPackets, entry.rxPackets); - assertEquals(txBytes, entry.txBytes); - assertEquals(txPackets, entry.txPackets); - assertEquals(operations, entry.operations); - } - -} diff --git a/packages/Connectivity/tests/unit/java/android/net/NetworkTemplateTest.kt b/packages/Connectivity/tests/unit/java/android/net/NetworkTemplateTest.kt deleted file mode 100644 index cb39a0c819f2a..0000000000000 --- a/packages/Connectivity/tests/unit/java/android/net/NetworkTemplateTest.kt +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net - -import android.content.Context -import android.net.ConnectivityManager.TYPE_MOBILE -import android.net.ConnectivityManager.TYPE_WIFI -import android.net.NetworkIdentity.SUBTYPE_COMBINED -import android.net.NetworkIdentity.OEM_NONE -import android.net.NetworkIdentity.OEM_PAID -import android.net.NetworkIdentity.OEM_PRIVATE -import android.net.NetworkIdentity.buildNetworkIdentity -import android.net.NetworkStats.DEFAULT_NETWORK_ALL -import android.net.NetworkStats.METERED_ALL -import android.net.NetworkStats.ROAMING_ALL -import android.net.NetworkTemplate.MATCH_MOBILE -import android.net.NetworkTemplate.MATCH_MOBILE_WILDCARD -import android.net.NetworkTemplate.MATCH_WIFI -import android.net.NetworkTemplate.MATCH_WIFI_WILDCARD -import android.net.NetworkTemplate.WIFI_NETWORKID_ALL -import android.net.NetworkTemplate.NETWORK_TYPE_5G_NSA -import android.net.NetworkTemplate.NETWORK_TYPE_ALL -import android.net.NetworkTemplate.OEM_MANAGED_ALL -import android.net.NetworkTemplate.OEM_MANAGED_NO -import android.net.NetworkTemplate.OEM_MANAGED_YES -import android.net.NetworkTemplate.SUBSCRIBER_ID_MATCH_RULE_EXACT -import android.net.NetworkTemplate.buildTemplateWifi -import android.net.NetworkTemplate.buildTemplateWifiWildcard -import android.net.NetworkTemplate.buildTemplateCarrierMetered -import android.net.NetworkTemplate.buildTemplateMobileWithRatType -import android.telephony.TelephonyManager -import com.android.testutils.assertParcelSane -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.junit.runners.JUnit4 -import org.mockito.Mockito.mock -import org.mockito.MockitoAnnotations -import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertNotEquals -import kotlin.test.assertTrue - -private const val TEST_IMSI1 = "imsi1" -private const val TEST_IMSI2 = "imsi2" -private const val TEST_SSID1 = "ssid1" -private const val TEST_SSID2 = "ssid2" - -@RunWith(JUnit4::class) -class NetworkTemplateTest { - private val mockContext = mock(Context::class.java) - - private fun buildMobileNetworkState(subscriberId: String): NetworkStateSnapshot = - buildNetworkState(TYPE_MOBILE, subscriberId = subscriberId) - private fun buildWifiNetworkState(subscriberId: String?, ssid: String?): NetworkStateSnapshot = - buildNetworkState(TYPE_WIFI, subscriberId = subscriberId, ssid = ssid) - - private fun buildNetworkState( - type: Int, - subscriberId: String? = null, - ssid: String? = null, - oemManaged: Int = OEM_NONE, - metered: Boolean = true - ): NetworkStateSnapshot { - val lp = LinkProperties() - val caps = NetworkCapabilities().apply { - setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, !metered) - setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true) - setSSID(ssid) - setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID, - (oemManaged and OEM_PAID) == OEM_PAID) - setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE, - (oemManaged and OEM_PRIVATE) == OEM_PRIVATE) - } - return NetworkStateSnapshot(mock(Network::class.java), caps, lp, subscriberId, type) - } - - private fun NetworkTemplate.assertMatches(ident: NetworkIdentity) = - assertTrue(matches(ident), "$this does not match $ident") - - private fun NetworkTemplate.assertDoesNotMatch(ident: NetworkIdentity) = - assertFalse(matches(ident), "$this should match $ident") - - @Before - fun setup() { - MockitoAnnotations.initMocks(this) - } - - @Test - fun testWifiWildcardMatches() { - val templateWifiWildcard = buildTemplateWifiWildcard() - - val identMobileImsi1 = buildNetworkIdentity(mockContext, - buildMobileNetworkState(TEST_IMSI1), - false, TelephonyManager.NETWORK_TYPE_UMTS) - val identWifiImsiNullSsid1 = buildNetworkIdentity( - mockContext, buildWifiNetworkState(null, TEST_SSID1), true, 0) - val identWifiImsi1Ssid1 = buildNetworkIdentity( - mockContext, buildWifiNetworkState(TEST_IMSI1, TEST_SSID1), true, 0) - - templateWifiWildcard.assertDoesNotMatch(identMobileImsi1) - templateWifiWildcard.assertMatches(identWifiImsiNullSsid1) - templateWifiWildcard.assertMatches(identWifiImsi1Ssid1) - } - - @Test - fun testWifiMatches() { - val templateWifiSsid1 = buildTemplateWifi(TEST_SSID1) - val templateWifiSsid1ImsiNull = buildTemplateWifi(TEST_SSID1, null) - val templateWifiSsid1Imsi1 = buildTemplateWifi(TEST_SSID1, TEST_IMSI1) - val templateWifiSsidAllImsi1 = buildTemplateWifi(WIFI_NETWORKID_ALL, TEST_IMSI1) - - val identMobile1 = buildNetworkIdentity(mockContext, buildMobileNetworkState(TEST_IMSI1), - false, TelephonyManager.NETWORK_TYPE_UMTS) - val identWifiImsiNullSsid1 = buildNetworkIdentity( - mockContext, buildWifiNetworkState(null, TEST_SSID1), true, 0) - val identWifiImsi1Ssid1 = buildNetworkIdentity( - mockContext, buildWifiNetworkState(TEST_IMSI1, TEST_SSID1), true, 0) - val identWifiImsi2Ssid1 = buildNetworkIdentity( - mockContext, buildWifiNetworkState(TEST_IMSI2, TEST_SSID1), true, 0) - val identWifiImsi1Ssid2 = buildNetworkIdentity( - mockContext, buildWifiNetworkState(TEST_IMSI1, TEST_SSID2), true, 0) - - // Verify that template with SSID only matches any subscriberId and specific SSID. - templateWifiSsid1.assertDoesNotMatch(identMobile1) - templateWifiSsid1.assertMatches(identWifiImsiNullSsid1) - templateWifiSsid1.assertMatches(identWifiImsi1Ssid1) - templateWifiSsid1.assertMatches(identWifiImsi2Ssid1) - templateWifiSsid1.assertDoesNotMatch(identWifiImsi1Ssid2) - - // Verify that template with SSID1 and null imsi matches any network with - // SSID1 and null imsi. - templateWifiSsid1ImsiNull.assertDoesNotMatch(identMobile1) - templateWifiSsid1ImsiNull.assertMatches(identWifiImsiNullSsid1) - templateWifiSsid1ImsiNull.assertDoesNotMatch(identWifiImsi1Ssid1) - templateWifiSsid1ImsiNull.assertDoesNotMatch(identWifiImsi2Ssid1) - templateWifiSsid1ImsiNull.assertDoesNotMatch(identWifiImsi1Ssid2) - - // Verify that template with SSID1 and imsi1 matches any network with - // SSID1 and imsi1. - templateWifiSsid1Imsi1.assertDoesNotMatch(identMobile1) - templateWifiSsid1Imsi1.assertDoesNotMatch(identWifiImsiNullSsid1) - templateWifiSsid1Imsi1.assertMatches(identWifiImsi1Ssid1) - templateWifiSsid1Imsi1.assertDoesNotMatch(identWifiImsi2Ssid1) - templateWifiSsid1Imsi1.assertDoesNotMatch(identWifiImsi1Ssid2) - - // Verify that template with SSID all and imsi1 matches any network with - // any SSID and imsi1. - templateWifiSsidAllImsi1.assertDoesNotMatch(identMobile1) - templateWifiSsidAllImsi1.assertDoesNotMatch(identWifiImsiNullSsid1) - templateWifiSsidAllImsi1.assertMatches(identWifiImsi1Ssid1) - templateWifiSsidAllImsi1.assertDoesNotMatch(identWifiImsi2Ssid1) - templateWifiSsidAllImsi1.assertMatches(identWifiImsi1Ssid2) - } - - @Test - fun testCarrierMeteredMatches() { - val templateCarrierImsi1Metered = buildTemplateCarrierMetered(TEST_IMSI1) - - val mobileImsi1 = buildMobileNetworkState(TEST_IMSI1) - val mobileImsi1Unmetered = buildNetworkState(TYPE_MOBILE, TEST_IMSI1, null /* ssid */, - OEM_NONE, false /* metered */) - val mobileImsi2 = buildMobileNetworkState(TEST_IMSI2) - val wifiSsid1 = buildWifiNetworkState(null /* subscriberId */, TEST_SSID1) - val wifiImsi1Ssid1 = buildWifiNetworkState(TEST_IMSI1, TEST_SSID1) - val wifiImsi1Ssid1Unmetered = buildNetworkState(TYPE_WIFI, TEST_IMSI1, TEST_SSID1, - OEM_NONE, false /* metered */) - - val identMobileImsi1Metered = buildNetworkIdentity(mockContext, - mobileImsi1, false /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS) - val identMobileImsi1Unmetered = buildNetworkIdentity(mockContext, - mobileImsi1Unmetered, false /* defaultNetwork */, - TelephonyManager.NETWORK_TYPE_UMTS) - val identMobileImsi2Metered = buildNetworkIdentity(mockContext, - mobileImsi2, false /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS) - val identWifiSsid1Metered = buildNetworkIdentity( - mockContext, wifiSsid1, true /* defaultNetwork */, 0 /* subType */) - val identCarrierWifiImsi1Metered = buildNetworkIdentity( - mockContext, wifiImsi1Ssid1, true /* defaultNetwork */, 0 /* subType */) - val identCarrierWifiImsi1NonMetered = buildNetworkIdentity(mockContext, - wifiImsi1Ssid1Unmetered, true /* defaultNetwork */, 0 /* subType */) - - templateCarrierImsi1Metered.assertMatches(identMobileImsi1Metered) - templateCarrierImsi1Metered.assertDoesNotMatch(identMobileImsi1Unmetered) - templateCarrierImsi1Metered.assertDoesNotMatch(identMobileImsi2Metered) - templateCarrierImsi1Metered.assertDoesNotMatch(identWifiSsid1Metered) - templateCarrierImsi1Metered.assertMatches(identCarrierWifiImsi1Metered) - templateCarrierImsi1Metered.assertDoesNotMatch(identCarrierWifiImsi1NonMetered) - } - - @Test - fun testRatTypeGroupMatches() { - val stateMobile = buildMobileNetworkState(TEST_IMSI1) - // Build UMTS template that matches mobile identities with RAT in the same - // group with any IMSI. See {@link NetworkTemplate#getCollapsedRatType}. - val templateUmts = buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_UMTS) - // Build normal template that matches mobile identities with any RAT and IMSI. - val templateAll = buildTemplateMobileWithRatType(null, NETWORK_TYPE_ALL) - // Build template with UNKNOWN RAT that matches mobile identities with RAT that - // cannot be determined. - val templateUnknown = - buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_UNKNOWN) - - val identUmts = buildNetworkIdentity( - mockContext, stateMobile, false, TelephonyManager.NETWORK_TYPE_UMTS) - val identHsdpa = buildNetworkIdentity( - mockContext, stateMobile, false, TelephonyManager.NETWORK_TYPE_HSDPA) - val identLte = buildNetworkIdentity( - mockContext, stateMobile, false, TelephonyManager.NETWORK_TYPE_LTE) - val identCombined = buildNetworkIdentity( - mockContext, stateMobile, false, SUBTYPE_COMBINED) - val identImsi2 = buildNetworkIdentity(mockContext, buildMobileNetworkState(TEST_IMSI2), - false, TelephonyManager.NETWORK_TYPE_UMTS) - val identWifi = buildNetworkIdentity( - mockContext, buildWifiNetworkState(null, TEST_SSID1), true, 0) - - // Assert that identity with the same RAT matches. - templateUmts.assertMatches(identUmts) - templateAll.assertMatches(identUmts) - templateUnknown.assertDoesNotMatch(identUmts) - // Assert that identity with the RAT within the same group matches. - templateUmts.assertMatches(identHsdpa) - templateAll.assertMatches(identHsdpa) - templateUnknown.assertDoesNotMatch(identHsdpa) - // Assert that identity with the RAT out of the same group only matches template with - // NETWORK_TYPE_ALL. - templateUmts.assertDoesNotMatch(identLte) - templateAll.assertMatches(identLte) - templateUnknown.assertDoesNotMatch(identLte) - // Assert that identity with combined RAT only matches with template with NETWORK_TYPE_ALL - // and NETWORK_TYPE_UNKNOWN. - templateUmts.assertDoesNotMatch(identCombined) - templateAll.assertMatches(identCombined) - templateUnknown.assertMatches(identCombined) - // Assert that identity with different IMSI matches. - templateUmts.assertMatches(identImsi2) - templateAll.assertMatches(identImsi2) - templateUnknown.assertDoesNotMatch(identImsi2) - // Assert that wifi identity does not match. - templateUmts.assertDoesNotMatch(identWifi) - templateAll.assertDoesNotMatch(identWifi) - templateUnknown.assertDoesNotMatch(identWifi) - } - - @Test - fun testParcelUnparcel() { - val templateMobile = NetworkTemplate(MATCH_MOBILE, TEST_IMSI1, null, null, METERED_ALL, - ROAMING_ALL, DEFAULT_NETWORK_ALL, TelephonyManager.NETWORK_TYPE_LTE, - OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT) - val templateWifi = NetworkTemplate(MATCH_WIFI, null, null, TEST_SSID1, METERED_ALL, - ROAMING_ALL, DEFAULT_NETWORK_ALL, 0, OEM_MANAGED_ALL, - SUBSCRIBER_ID_MATCH_RULE_EXACT) - val templateOem = NetworkTemplate(MATCH_MOBILE, null, null, null, METERED_ALL, - ROAMING_ALL, DEFAULT_NETWORK_ALL, 0, OEM_MANAGED_YES, - SUBSCRIBER_ID_MATCH_RULE_EXACT) - assertParcelSane(templateMobile, 10) - assertParcelSane(templateWifi, 10) - assertParcelSane(templateOem, 10) - } - - // Verify NETWORK_TYPE_* constants in NetworkTemplate do not conflict with - // TelephonyManager#NETWORK_TYPE_* constants. - @Test - fun testNetworkTypeConstants() { - for (ratType in TelephonyManager.getAllNetworkTypes()) { - assertNotEquals(NETWORK_TYPE_ALL, ratType) - assertNotEquals(NETWORK_TYPE_5G_NSA, ratType) - } - } - - @Test - fun testOemNetworkConstants() { - val constantValues = arrayOf(OEM_MANAGED_YES, OEM_MANAGED_ALL, OEM_MANAGED_NO, - OEM_PAID, OEM_PRIVATE, OEM_PAID or OEM_PRIVATE) - - // Verify that "not OEM managed network" constants are equal. - assertEquals(OEM_MANAGED_NO, OEM_NONE) - - // Verify the constants don't conflict. - assertEquals(constantValues.size, constantValues.distinct().count()) - } - - /** - * Helper to enumerate and assert OEM managed wifi and mobile {@code NetworkTemplate}s match - * their the appropriate OEM managed {@code NetworkIdentity}s. - * - * @param networkType {@code TYPE_MOBILE} or {@code TYPE_WIFI} - * @param matchType A match rule from {@code NetworkTemplate.MATCH_*} corresponding to the - * networkType. - * @param subscriberId To be populated with {@code TEST_IMSI*} only if networkType is - * {@code TYPE_MOBILE}. May be left as null when matchType is - * {@link NetworkTemplate.MATCH_MOBILE_WILDCARD}. - * @param templateSsid Top be populated with {@code TEST_SSID*} only if networkType is - * {@code TYPE_WIFI}. May be left as null when matchType is - * {@link NetworkTemplate.MATCH_WIFI_WILDCARD}. - * @param identSsid If networkType is {@code TYPE_WIFI}, this value must *NOT* be null. Provide - * one of {@code TEST_SSID*}. - */ - private fun matchOemManagedIdent( - networkType: Int, - matchType: Int, - subscriberId: String? = null, - templateSsid: String? = null, - identSsid: String? = null - ) { - val oemManagedStates = arrayOf(OEM_NONE, OEM_PAID, OEM_PRIVATE, OEM_PAID or OEM_PRIVATE) - val matchSubscriberIds = arrayOf(subscriberId) - - val templateOemYes = NetworkTemplate(matchType, subscriberId, matchSubscriberIds, - templateSsid, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, - OEM_MANAGED_YES, SUBSCRIBER_ID_MATCH_RULE_EXACT) - val templateOemAll = NetworkTemplate(matchType, subscriberId, matchSubscriberIds, - templateSsid, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, - OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT) - - for (identityOemManagedState in oemManagedStates) { - val ident = buildNetworkIdentity(mockContext, buildNetworkState(networkType, - subscriberId, identSsid, identityOemManagedState), /*defaultNetwork=*/false, - /*subType=*/0) - - // Create a template with each OEM managed type and match it against the NetworkIdentity - for (templateOemManagedState in oemManagedStates) { - val template = NetworkTemplate(matchType, subscriberId, matchSubscriberIds, - templateSsid, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, - NETWORK_TYPE_ALL, templateOemManagedState, SUBSCRIBER_ID_MATCH_RULE_EXACT) - if (identityOemManagedState == templateOemManagedState) { - template.assertMatches(ident) - } else { - template.assertDoesNotMatch(ident) - } - } - // OEM_MANAGED_ALL ignores OEM state. - templateOemAll.assertMatches(ident) - if (identityOemManagedState == OEM_NONE) { - // OEM_MANAGED_YES matches everything except OEM_NONE. - templateOemYes.assertDoesNotMatch(ident) - } else { - templateOemYes.assertMatches(ident) - } - } - } - - @Test - fun testOemManagedMatchesIdent() { - matchOemManagedIdent(TYPE_MOBILE, MATCH_MOBILE, subscriberId = TEST_IMSI1) - matchOemManagedIdent(TYPE_MOBILE, MATCH_MOBILE_WILDCARD) - matchOemManagedIdent(TYPE_WIFI, MATCH_WIFI, templateSsid = TEST_SSID1, - identSsid = TEST_SSID1) - matchOemManagedIdent(TYPE_WIFI, MATCH_WIFI_WILDCARD, identSsid = TEST_SSID1) - } -} diff --git a/packages/Connectivity/tests/unit/java/android/net/NetworkUtilsTest.java b/packages/Connectivity/tests/unit/java/android/net/NetworkUtilsTest.java deleted file mode 100644 index 7748288aeb050..0000000000000 --- a/packages/Connectivity/tests/unit/java/android/net/NetworkUtilsTest.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static junit.framework.Assert.assertEquals; - -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.math.BigInteger; -import java.util.TreeSet; - -@RunWith(AndroidJUnit4.class) -@androidx.test.filters.SmallTest -public class NetworkUtilsTest { - @Test - public void testRoutedIPv4AddressCount() { - final TreeSet set = new TreeSet<>(IpPrefix.lengthComparator()); - // No routes routes to no addresses. - assertEquals(0, NetworkUtils.routedIPv4AddressCount(set)); - - set.add(new IpPrefix("0.0.0.0/0")); - assertEquals(1l << 32, NetworkUtils.routedIPv4AddressCount(set)); - - set.add(new IpPrefix("20.18.0.0/16")); - set.add(new IpPrefix("20.18.0.0/24")); - set.add(new IpPrefix("20.18.0.0/8")); - // There is a default route, still covers everything - assertEquals(1l << 32, NetworkUtils.routedIPv4AddressCount(set)); - - set.clear(); - set.add(new IpPrefix("20.18.0.0/24")); - set.add(new IpPrefix("20.18.0.0/8")); - // The 8-length includes the 24-length prefix - assertEquals(1l << 24, NetworkUtils.routedIPv4AddressCount(set)); - - set.add(new IpPrefix("10.10.10.126/25")); - // The 8-length does not include this 25-length prefix - assertEquals((1l << 24) + (1 << 7), NetworkUtils.routedIPv4AddressCount(set)); - - set.clear(); - set.add(new IpPrefix("1.2.3.4/32")); - set.add(new IpPrefix("1.2.3.4/32")); - set.add(new IpPrefix("1.2.3.4/32")); - set.add(new IpPrefix("1.2.3.4/32")); - assertEquals(1l, NetworkUtils.routedIPv4AddressCount(set)); - - set.add(new IpPrefix("1.2.3.5/32")); - set.add(new IpPrefix("1.2.3.6/32")); - - set.add(new IpPrefix("1.2.3.7/32")); - set.add(new IpPrefix("1.2.3.8/32")); - set.add(new IpPrefix("1.2.3.9/32")); - set.add(new IpPrefix("1.2.3.0/32")); - assertEquals(7l, NetworkUtils.routedIPv4AddressCount(set)); - - // 1.2.3.4/30 eats 1.2.3.{4-7}/32 - set.add(new IpPrefix("1.2.3.4/30")); - set.add(new IpPrefix("6.2.3.4/28")); - set.add(new IpPrefix("120.2.3.4/16")); - assertEquals(7l - 4 + 4 + 16 + 65536, NetworkUtils.routedIPv4AddressCount(set)); - } - - @Test - public void testRoutedIPv6AddressCount() { - final TreeSet set = new TreeSet<>(IpPrefix.lengthComparator()); - // No routes routes to no addresses. - assertEquals(BigInteger.ZERO, NetworkUtils.routedIPv6AddressCount(set)); - - set.add(new IpPrefix("::/0")); - assertEquals(BigInteger.ONE.shiftLeft(128), NetworkUtils.routedIPv6AddressCount(set)); - - set.add(new IpPrefix("1234:622a::18/64")); - set.add(new IpPrefix("add4:f00:80:f7:1111::6adb/96")); - set.add(new IpPrefix("add4:f00:80:f7:1111::6adb/8")); - // There is a default route, still covers everything - assertEquals(BigInteger.ONE.shiftLeft(128), NetworkUtils.routedIPv6AddressCount(set)); - - set.clear(); - set.add(new IpPrefix("add4:f00:80:f7:1111::6adb/96")); - set.add(new IpPrefix("add4:f00:80:f7:1111::6adb/8")); - // The 8-length includes the 96-length prefix - assertEquals(BigInteger.ONE.shiftLeft(120), NetworkUtils.routedIPv6AddressCount(set)); - - set.add(new IpPrefix("10::26/64")); - // The 8-length does not include this 64-length prefix - assertEquals(BigInteger.ONE.shiftLeft(120).add(BigInteger.ONE.shiftLeft(64)), - NetworkUtils.routedIPv6AddressCount(set)); - - set.clear(); - set.add(new IpPrefix("add4:f00:80:f7:1111::6ad4/128")); - set.add(new IpPrefix("add4:f00:80:f7:1111::6ad4/128")); - set.add(new IpPrefix("add4:f00:80:f7:1111::6ad4/128")); - set.add(new IpPrefix("add4:f00:80:f7:1111::6ad4/128")); - assertEquals(BigInteger.ONE, NetworkUtils.routedIPv6AddressCount(set)); - - set.add(new IpPrefix("add4:f00:80:f7:1111::6ad5/128")); - set.add(new IpPrefix("add4:f00:80:f7:1111::6ad6/128")); - set.add(new IpPrefix("add4:f00:80:f7:1111::6ad7/128")); - set.add(new IpPrefix("add4:f00:80:f7:1111::6ad8/128")); - set.add(new IpPrefix("add4:f00:80:f7:1111::6ad9/128")); - set.add(new IpPrefix("add4:f00:80:f7:1111::6ad0/128")); - assertEquals(BigInteger.valueOf(7), NetworkUtils.routedIPv6AddressCount(set)); - - // add4:f00:80:f7:1111::6ad4/126 eats add4:f00:8[:f7:1111::6ad{4-7}/128 - set.add(new IpPrefix("add4:f00:80:f7:1111::6ad4/126")); - set.add(new IpPrefix("d00d:f00:80:f7:1111::6ade/124")); - set.add(new IpPrefix("f00b:a33::/112")); - assertEquals(BigInteger.valueOf(7l - 4 + 4 + 16 + 65536), - NetworkUtils.routedIPv6AddressCount(set)); - } -} diff --git a/packages/Connectivity/tests/unit/java/android/net/QosSocketFilterTest.java b/packages/Connectivity/tests/unit/java/android/net/QosSocketFilterTest.java deleted file mode 100644 index 40f8f1b8d09a9..0000000000000 --- a/packages/Connectivity/tests/unit/java/android/net/QosSocketFilterTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertTrue; - -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.net.InetAddress; -import java.net.InetSocketAddress; - -@RunWith(AndroidJUnit4.class) -@androidx.test.filters.SmallTest -public class QosSocketFilterTest { - - @Test - public void testPortExactMatch() { - final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4"); - final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.4"); - assertTrue(QosSocketFilter.matchesAddress( - new InetSocketAddress(addressA, 10), addressB, 10, 10)); - - } - - @Test - public void testPortLessThanStart() { - final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4"); - final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.4"); - assertFalse(QosSocketFilter.matchesAddress( - new InetSocketAddress(addressA, 8), addressB, 10, 10)); - } - - @Test - public void testPortGreaterThanEnd() { - final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4"); - final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.4"); - assertFalse(QosSocketFilter.matchesAddress( - new InetSocketAddress(addressA, 18), addressB, 10, 10)); - } - - @Test - public void testPortBetweenStartAndEnd() { - final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4"); - final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.4"); - assertTrue(QosSocketFilter.matchesAddress( - new InetSocketAddress(addressA, 10), addressB, 8, 18)); - } - - @Test - public void testAddressesDontMatch() { - final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4"); - final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.5"); - assertFalse(QosSocketFilter.matchesAddress( - new InetSocketAddress(addressA, 10), addressB, 10, 10)); - } -} - diff --git a/packages/Connectivity/tests/unit/java/android/net/TelephonyNetworkSpecifierTest.java b/packages/Connectivity/tests/unit/java/android/net/TelephonyNetworkSpecifierTest.java deleted file mode 100644 index 6714bb1abbe62..0000000000000 --- a/packages/Connectivity/tests/unit/java/android/net/TelephonyNetworkSpecifierTest.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static com.android.testutils.ParcelUtils.assertParcelSane; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import android.net.wifi.WifiNetworkSpecifier; -import android.telephony.SubscriptionManager; - -import androidx.test.filters.SmallTest; - -import org.junit.Test; - -/** - * Unit test for {@link android.net.TelephonyNetworkSpecifier}. - */ -@SmallTest -public class TelephonyNetworkSpecifierTest { - private static final int TEST_SUBID = 5; - private static final String TEST_SSID = "Test123"; - - /** - * Validate that IllegalArgumentException will be thrown if build TelephonyNetworkSpecifier - * without calling {@link TelephonyNetworkSpecifier.Builder#setSubscriptionId(int)}. - */ - @Test - public void testBuilderBuildWithDefault() { - try { - new TelephonyNetworkSpecifier.Builder().build(); - } catch (IllegalArgumentException iae) { - // expected, test pass - } - } - - /** - * Validate that no exception will be thrown even if pass invalid subscription id to - * {@link TelephonyNetworkSpecifier.Builder#setSubscriptionId(int)}. - */ - @Test - public void testBuilderBuildWithInvalidSubId() { - TelephonyNetworkSpecifier specifier = new TelephonyNetworkSpecifier.Builder() - .setSubscriptionId(SubscriptionManager.INVALID_SUBSCRIPTION_ID) - .build(); - assertEquals(specifier.getSubscriptionId(), SubscriptionManager.INVALID_SUBSCRIPTION_ID); - } - - /** - * Validate the correctness of TelephonyNetworkSpecifier when provide valid subId. - */ - @Test - public void testBuilderBuildWithValidSubId() { - final TelephonyNetworkSpecifier specifier = new TelephonyNetworkSpecifier.Builder() - .setSubscriptionId(TEST_SUBID) - .build(); - assertEquals(TEST_SUBID, specifier.getSubscriptionId()); - } - - /** - * Validate that parcel marshalling/unmarshalling works. - */ - @Test - public void testParcel() { - TelephonyNetworkSpecifier specifier = new TelephonyNetworkSpecifier.Builder() - .setSubscriptionId(TEST_SUBID) - .build(); - assertParcelSane(specifier, 1 /* fieldCount */); - } - - /** - * Validate the behavior of method canBeSatisfiedBy(). - */ - @Test - public void testCanBeSatisfiedBy() { - final TelephonyNetworkSpecifier tns1 = new TelephonyNetworkSpecifier.Builder() - .setSubscriptionId(TEST_SUBID) - .build(); - final TelephonyNetworkSpecifier tns2 = new TelephonyNetworkSpecifier.Builder() - .setSubscriptionId(TEST_SUBID) - .build(); - final WifiNetworkSpecifier wns = new WifiNetworkSpecifier.Builder() - .setSsid(TEST_SSID) - .build(); - final MatchAllNetworkSpecifier mans = new MatchAllNetworkSpecifier(); - - // Test equality - assertEquals(tns1, tns2); - assertTrue(tns1.canBeSatisfiedBy(tns1)); - assertTrue(tns1.canBeSatisfiedBy(tns2)); - - // Test other edge cases. - assertFalse(tns1.canBeSatisfiedBy(null)); - assertFalse(tns1.canBeSatisfiedBy(wns)); - assertTrue(tns1.canBeSatisfiedBy(mans)); - } -} diff --git a/packages/Connectivity/tests/unit/java/android/net/VpnManagerTest.java b/packages/Connectivity/tests/unit/java/android/net/VpnManagerTest.java deleted file mode 100644 index 3135062138ac5..0000000000000 --- a/packages/Connectivity/tests/unit/java/android/net/VpnManagerTest.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.content.ComponentName; -import android.content.Intent; -import android.test.mock.MockContext; -import android.util.SparseArray; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.internal.net.VpnProfile; -import com.android.internal.util.MessageUtils; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -/** Unit tests for {@link VpnManager}. */ -@SmallTest -@RunWith(AndroidJUnit4.class) -public class VpnManagerTest { - private static final String PKG_NAME = "fooPackage"; - - private static final String SESSION_NAME_STRING = "testSession"; - private static final String SERVER_ADDR_STRING = "1.2.3.4"; - private static final String IDENTITY_STRING = "Identity"; - private static final byte[] PSK_BYTES = "preSharedKey".getBytes(); - - private IVpnManager mMockService; - private VpnManager mVpnManager; - private final MockContext mMockContext = - new MockContext() { - @Override - public String getOpPackageName() { - return PKG_NAME; - } - }; - - @Before - public void setUp() throws Exception { - mMockService = mock(IVpnManager.class); - mVpnManager = new VpnManager(mMockContext, mMockService); - } - - @Test - public void testProvisionVpnProfilePreconsented() throws Exception { - final PlatformVpnProfile profile = getPlatformVpnProfile(); - when(mMockService.provisionVpnProfile(any(VpnProfile.class), eq(PKG_NAME))) - .thenReturn(true); - - // Expect there to be no intent returned, as consent has already been granted. - assertNull(mVpnManager.provisionVpnProfile(profile)); - verify(mMockService).provisionVpnProfile(eq(profile.toVpnProfile()), eq(PKG_NAME)); - } - - @Test - public void testProvisionVpnProfileNeedsConsent() throws Exception { - final PlatformVpnProfile profile = getPlatformVpnProfile(); - when(mMockService.provisionVpnProfile(any(VpnProfile.class), eq(PKG_NAME))) - .thenReturn(false); - - // Expect intent to be returned, as consent has not already been granted. - final Intent intent = mVpnManager.provisionVpnProfile(profile); - assertNotNull(intent); - - final ComponentName expectedComponentName = - ComponentName.unflattenFromString( - "com.android.vpndialogs/com.android.vpndialogs.PlatformVpnConfirmDialog"); - assertEquals(expectedComponentName, intent.getComponent()); - verify(mMockService).provisionVpnProfile(eq(profile.toVpnProfile()), eq(PKG_NAME)); - } - - @Test - public void testDeleteProvisionedVpnProfile() throws Exception { - mVpnManager.deleteProvisionedVpnProfile(); - verify(mMockService).deleteVpnProfile(eq(PKG_NAME)); - } - - @Test - public void testStartProvisionedVpnProfile() throws Exception { - mVpnManager.startProvisionedVpnProfile(); - verify(mMockService).startVpnProfile(eq(PKG_NAME)); - } - - @Test - public void testStopProvisionedVpnProfile() throws Exception { - mVpnManager.stopProvisionedVpnProfile(); - verify(mMockService).stopVpnProfile(eq(PKG_NAME)); - } - - private Ikev2VpnProfile getPlatformVpnProfile() throws Exception { - return new Ikev2VpnProfile.Builder(SERVER_ADDR_STRING, IDENTITY_STRING) - .setBypassable(true) - .setMaxMtu(1300) - .setMetered(true) - .setAuthPsk(PSK_BYTES) - .build(); - } - - @Test - public void testVpnTypesEqual() throws Exception { - SparseArray vmVpnTypes = MessageUtils.findMessageNames( - new Class[] { VpnManager.class }, new String[]{ "TYPE_VPN_" }); - SparseArray nativeVpnType = MessageUtils.findMessageNames( - new Class[] { NativeVpnType.class }, new String[]{ "" }); - - // TYPE_VPN_NONE = -1 is only defined in VpnManager. - assertEquals(vmVpnTypes.size() - 1, nativeVpnType.size()); - for (int i = VpnManager.TYPE_VPN_SERVICE; i < vmVpnTypes.size(); i++) { - assertEquals(vmVpnTypes.get(i), "TYPE_VPN_" + nativeVpnType.get(i)); - } - } -} diff --git a/packages/Connectivity/tests/unit/java/android/net/VpnTransportInfoTest.java b/packages/Connectivity/tests/unit/java/android/net/VpnTransportInfoTest.java deleted file mode 100644 index ccaa5cf7e9f7c..0000000000000 --- a/packages/Connectivity/tests/unit/java/android/net/VpnTransportInfoTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS; -import static android.net.NetworkCapabilities.REDACT_NONE; - -import static com.android.testutils.ParcelUtils.assertParcelSane; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class VpnTransportInfoTest { - - @Test - public void testParceling() { - VpnTransportInfo v = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, "12345"); - assertParcelSane(v, 2 /* fieldCount */); - } - - @Test - public void testEqualsAndHashCode() { - String session1 = "12345"; - String session2 = "6789"; - VpnTransportInfo v11 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, session1); - VpnTransportInfo v12 = new VpnTransportInfo(VpnManager.TYPE_VPN_SERVICE, session1); - VpnTransportInfo v13 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, session1); - VpnTransportInfo v14 = new VpnTransportInfo(VpnManager.TYPE_VPN_LEGACY, session1); - VpnTransportInfo v15 = new VpnTransportInfo(VpnManager.TYPE_VPN_OEM, session1); - VpnTransportInfo v21 = new VpnTransportInfo(VpnManager.TYPE_VPN_LEGACY, session2); - - VpnTransportInfo v31 = v11.makeCopy(REDACT_FOR_NETWORK_SETTINGS); - VpnTransportInfo v32 = v13.makeCopy(REDACT_FOR_NETWORK_SETTINGS); - - assertNotEquals(v11, v12); - assertNotEquals(v13, v14); - assertNotEquals(v14, v15); - assertNotEquals(v14, v21); - - assertEquals(v11, v13); - assertEquals(v31, v32); - assertEquals(v11.hashCode(), v13.hashCode()); - assertEquals(REDACT_FOR_NETWORK_SETTINGS, v32.getApplicableRedactions()); - assertEquals(session1, v15.makeCopy(REDACT_NONE).getSessionId()); - } -} diff --git a/packages/Connectivity/tests/unit/java/android/net/ipmemorystore/ParcelableTests.java b/packages/Connectivity/tests/unit/java/android/net/ipmemorystore/ParcelableTests.java deleted file mode 100644 index 603c875195323..0000000000000 --- a/packages/Connectivity/tests/unit/java/android/net/ipmemorystore/ParcelableTests.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.ipmemorystore; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import android.net.networkstack.aidl.quirks.IPv6ProvisioningLossQuirk; -import android.net.networkstack.aidl.quirks.IPv6ProvisioningLossQuirkParcelable; -import android.os.Parcel; -import android.os.Parcelable; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.lang.reflect.Modifier; -import java.net.Inet4Address; -import java.net.InetAddress; -import java.util.Arrays; -import java.util.Collections; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class ParcelableTests { - @Test - public void testNetworkAttributesParceling() throws Exception { - final NetworkAttributes.Builder builder = new NetworkAttributes.Builder(); - NetworkAttributes in = builder.build(); - assertEquals(in, new NetworkAttributes(parcelingRoundTrip(in.toParcelable()))); - - builder.setAssignedV4Address((Inet4Address) Inet4Address.getByName("1.2.3.4")); - // lease will expire in two hours - builder.setAssignedV4AddressExpiry(System.currentTimeMillis() + 7_200_000); - // cluster stays null this time around - builder.setDnsAddresses(Collections.emptyList()); - builder.setMtu(18); - in = builder.build(); - assertEquals(in, new NetworkAttributes(parcelingRoundTrip(in.toParcelable()))); - - builder.setAssignedV4Address((Inet4Address) Inet4Address.getByName("6.7.8.9")); - builder.setAssignedV4AddressExpiry(System.currentTimeMillis() + 3_600_000); - builder.setCluster("groupHint"); - builder.setDnsAddresses(Arrays.asList( - InetAddress.getByName("ACA1:652B:0911:DE8F:1200:115E:913B:AA2A"), - InetAddress.getByName("6.7.8.9"))); - builder.setMtu(1_000_000); - in = builder.build(); - assertEquals(in, new NetworkAttributes(parcelingRoundTrip(in.toParcelable()))); - - builder.setMtu(null); - in = builder.build(); - assertEquals(in, new NetworkAttributes(parcelingRoundTrip(in.toParcelable()))); - - // Verify that this test does not miss any new field added later. - // If any field is added to NetworkAttributes it must be tested here for parceling - // roundtrip. - assertEquals(6, Arrays.stream(NetworkAttributes.class.getDeclaredFields()) - .filter(f -> !Modifier.isStatic(f.getModifiers())).count()); - } - - @Test - public void testPrivateDataParceling() throws Exception { - final Blob in = new Blob(); - in.data = new byte[] {89, 111, 108, 111}; - final Blob out = parcelingRoundTrip(in); - // Object.equals on byte[] tests the references - assertEquals(in.data.length, out.data.length); - assertTrue(Arrays.equals(in.data, out.data)); - } - - @Test - public void testSameL3NetworkResponseParceling() throws Exception { - final SameL3NetworkResponseParcelable parcelable = new SameL3NetworkResponseParcelable(); - parcelable.l2Key1 = "key 1"; - parcelable.l2Key2 = "key 2"; - parcelable.confidence = 0.43f; - - final SameL3NetworkResponse in = new SameL3NetworkResponse(parcelable); - assertEquals("key 1", in.l2Key1); - assertEquals("key 2", in.l2Key2); - assertEquals(0.43f, in.confidence, 0.01f /* delta */); - - final SameL3NetworkResponse out = - new SameL3NetworkResponse(parcelingRoundTrip(in.toParcelable())); - - assertEquals(in, out); - assertEquals(in.l2Key1, out.l2Key1); - assertEquals(in.l2Key2, out.l2Key2); - assertEquals(in.confidence, out.confidence, 0.01f /* delta */); - } - - @Test - public void testIPv6ProvisioningLossQuirkParceling() throws Exception { - final NetworkAttributes.Builder builder = new NetworkAttributes.Builder(); - final IPv6ProvisioningLossQuirkParcelable parcelable = - new IPv6ProvisioningLossQuirkParcelable(); - final long expiry = System.currentTimeMillis() + 7_200_000; - - parcelable.detectionCount = 3; - parcelable.quirkExpiry = expiry; // quirk info will expire in two hours - builder.setIpv6ProvLossQuirk(IPv6ProvisioningLossQuirk.fromStableParcelable(parcelable)); - final NetworkAttributes in = builder.build(); - - final NetworkAttributes out = new NetworkAttributes(parcelingRoundTrip(in.toParcelable())); - assertEquals(out.ipv6ProvisioningLossQuirk, in.ipv6ProvisioningLossQuirk); - } - - private T parcelingRoundTrip(final T in) throws Exception { - final Parcel p = Parcel.obtain(); - in.writeToParcel(p, /* flags */ 0); - p.setDataPosition(0); - final byte[] marshalledData = p.marshall(); - p.recycle(); - - final Parcel q = Parcel.obtain(); - q.unmarshall(marshalledData, 0, marshalledData.length); - q.setDataPosition(0); - - final Parcelable.Creator creator = (Parcelable.Creator) - in.getClass().getField("CREATOR").get(null); // static object, so null receiver - final T unmarshalled = (T) creator.createFromParcel(q); - q.recycle(); - return unmarshalled; - } -} diff --git a/packages/Connectivity/tests/unit/java/android/net/nsd/NsdManagerTest.java b/packages/Connectivity/tests/unit/java/android/net/nsd/NsdManagerTest.java deleted file mode 100644 index b0a9b8a553223..0000000000000 --- a/packages/Connectivity/tests/unit/java/android/net/nsd/NsdManagerTest.java +++ /dev/null @@ -1,388 +0,0 @@ -/* - * Copyright (C) 2017 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.nsd; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.timeout; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Looper; -import android.os.Message; -import android.os.Messenger; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.internal.util.AsyncChannel; -import com.android.testutils.HandlerUtils; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class NsdManagerTest { - - static final int PROTOCOL = NsdManager.PROTOCOL_DNS_SD; - - @Mock Context mContext; - @Mock INsdManager mService; - MockServiceHandler mServiceHandler; - - NsdManager mManager; - - long mTimeoutMs = 200; // non-final so that tests can adjust the value. - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - mServiceHandler = spy(MockServiceHandler.create(mContext)); - when(mService.getMessenger()).thenReturn(new Messenger(mServiceHandler)); - - mManager = makeManager(); - } - - @After - public void tearDown() throws Exception { - HandlerUtils.waitForIdle(mServiceHandler, mTimeoutMs); - mServiceHandler.chan.disconnect(); - mServiceHandler.stop(); - if (mManager != null) { - mManager.disconnect(); - } - } - - @Test - public void testResolveService() { - NsdManager manager = mManager; - - NsdServiceInfo request = new NsdServiceInfo("a_name", "a_type"); - NsdServiceInfo reply = new NsdServiceInfo("resolved_name", "resolved_type"); - NsdManager.ResolveListener listener = mock(NsdManager.ResolveListener.class); - - manager.resolveService(request, listener); - int key1 = verifyRequest(NsdManager.RESOLVE_SERVICE); - int err = 33; - sendResponse(NsdManager.RESOLVE_SERVICE_FAILED, err, key1, null); - verify(listener, timeout(mTimeoutMs).times(1)).onResolveFailed(request, err); - - manager.resolveService(request, listener); - int key2 = verifyRequest(NsdManager.RESOLVE_SERVICE); - sendResponse(NsdManager.RESOLVE_SERVICE_SUCCEEDED, 0, key2, reply); - verify(listener, timeout(mTimeoutMs).times(1)).onServiceResolved(reply); - } - - @Test - public void testParallelResolveService() { - NsdManager manager = mManager; - - NsdServiceInfo request = new NsdServiceInfo("a_name", "a_type"); - NsdServiceInfo reply = new NsdServiceInfo("resolved_name", "resolved_type"); - - NsdManager.ResolveListener listener1 = mock(NsdManager.ResolveListener.class); - NsdManager.ResolveListener listener2 = mock(NsdManager.ResolveListener.class); - - manager.resolveService(request, listener1); - int key1 = verifyRequest(NsdManager.RESOLVE_SERVICE); - - manager.resolveService(request, listener2); - int key2 = verifyRequest(NsdManager.RESOLVE_SERVICE); - - sendResponse(NsdManager.RESOLVE_SERVICE_SUCCEEDED, 0, key2, reply); - sendResponse(NsdManager.RESOLVE_SERVICE_SUCCEEDED, 0, key1, reply); - - verify(listener1, timeout(mTimeoutMs).times(1)).onServiceResolved(reply); - verify(listener2, timeout(mTimeoutMs).times(1)).onServiceResolved(reply); - } - - @Test - public void testRegisterService() { - NsdManager manager = mManager; - - NsdServiceInfo request1 = new NsdServiceInfo("a_name", "a_type"); - NsdServiceInfo request2 = new NsdServiceInfo("another_name", "another_type"); - request1.setPort(2201); - request2.setPort(2202); - NsdManager.RegistrationListener listener1 = mock(NsdManager.RegistrationListener.class); - NsdManager.RegistrationListener listener2 = mock(NsdManager.RegistrationListener.class); - - // Register two services - manager.registerService(request1, PROTOCOL, listener1); - int key1 = verifyRequest(NsdManager.REGISTER_SERVICE); - - manager.registerService(request2, PROTOCOL, listener2); - int key2 = verifyRequest(NsdManager.REGISTER_SERVICE); - - // First reques fails, second request succeeds - sendResponse(NsdManager.REGISTER_SERVICE_SUCCEEDED, 0, key2, request2); - verify(listener2, timeout(mTimeoutMs).times(1)).onServiceRegistered(request2); - - int err = 1; - sendResponse(NsdManager.REGISTER_SERVICE_FAILED, err, key1, request1); - verify(listener1, timeout(mTimeoutMs).times(1)).onRegistrationFailed(request1, err); - - // Client retries first request, it succeeds - manager.registerService(request1, PROTOCOL, listener1); - int key3 = verifyRequest(NsdManager.REGISTER_SERVICE); - - sendResponse(NsdManager.REGISTER_SERVICE_SUCCEEDED, 0, key3, request1); - verify(listener1, timeout(mTimeoutMs).times(1)).onServiceRegistered(request1); - - // First request is unregistered, it succeeds - manager.unregisterService(listener1); - int key3again = verifyRequest(NsdManager.UNREGISTER_SERVICE); - assertEquals(key3, key3again); - - sendResponse(NsdManager.UNREGISTER_SERVICE_SUCCEEDED, 0, key3again, null); - verify(listener1, timeout(mTimeoutMs).times(1)).onServiceUnregistered(request1); - - // Second request is unregistered, it fails - manager.unregisterService(listener2); - int key2again = verifyRequest(NsdManager.UNREGISTER_SERVICE); - assertEquals(key2, key2again); - - sendResponse(NsdManager.UNREGISTER_SERVICE_FAILED, err, key2again, null); - verify(listener2, timeout(mTimeoutMs).times(1)).onUnregistrationFailed(request2, err); - - // TODO: do not unregister listener until service is unregistered - // Client retries unregistration of second request, it succeeds - //manager.unregisterService(listener2); - //int key2yetAgain = verifyRequest(NsdManager.UNREGISTER_SERVICE); - //assertEquals(key2, key2yetAgain); - - //sendResponse(NsdManager.UNREGISTER_SERVICE_SUCCEEDED, 0, key2yetAgain, null); - //verify(listener2, timeout(mTimeoutMs).times(1)).onServiceUnregistered(request2); - } - - @Test - public void testDiscoverService() { - NsdManager manager = mManager; - - NsdServiceInfo reply1 = new NsdServiceInfo("a_name", "a_type"); - NsdServiceInfo reply2 = new NsdServiceInfo("another_name", "a_type"); - NsdServiceInfo reply3 = new NsdServiceInfo("a_third_name", "a_type"); - - NsdManager.DiscoveryListener listener = mock(NsdManager.DiscoveryListener.class); - - // Client registers for discovery, request fails - manager.discoverServices("a_type", PROTOCOL, listener); - int key1 = verifyRequest(NsdManager.DISCOVER_SERVICES); - - int err = 1; - sendResponse(NsdManager.DISCOVER_SERVICES_FAILED, err, key1, null); - verify(listener, timeout(mTimeoutMs).times(1)).onStartDiscoveryFailed("a_type", err); - - // Client retries, request succeeds - manager.discoverServices("a_type", PROTOCOL, listener); - int key2 = verifyRequest(NsdManager.DISCOVER_SERVICES); - - sendResponse(NsdManager.DISCOVER_SERVICES_STARTED, 0, key2, reply1); - verify(listener, timeout(mTimeoutMs).times(1)).onDiscoveryStarted("a_type"); - - - // mdns notifies about services - sendResponse(NsdManager.SERVICE_FOUND, 0, key2, reply1); - verify(listener, timeout(mTimeoutMs).times(1)).onServiceFound(reply1); - - sendResponse(NsdManager.SERVICE_FOUND, 0, key2, reply2); - verify(listener, timeout(mTimeoutMs).times(1)).onServiceFound(reply2); - - sendResponse(NsdManager.SERVICE_LOST, 0, key2, reply2); - verify(listener, timeout(mTimeoutMs).times(1)).onServiceLost(reply2); - - - // Client unregisters its listener - manager.stopServiceDiscovery(listener); - int key2again = verifyRequest(NsdManager.STOP_DISCOVERY); - assertEquals(key2, key2again); - - // TODO: unregister listener immediately and stop notifying it about services - // Notifications are still passed to the client's listener - sendResponse(NsdManager.SERVICE_LOST, 0, key2, reply1); - verify(listener, timeout(mTimeoutMs).times(1)).onServiceLost(reply1); - - // Client is notified of complete unregistration - sendResponse(NsdManager.STOP_DISCOVERY_SUCCEEDED, 0, key2again, "a_type"); - verify(listener, timeout(mTimeoutMs).times(1)).onDiscoveryStopped("a_type"); - - // Notifications are not passed to the client anymore - sendResponse(NsdManager.SERVICE_FOUND, 0, key2, reply3); - verify(listener, timeout(mTimeoutMs).times(0)).onServiceLost(reply3); - - - // Client registers for service discovery - reset(listener); - manager.discoverServices("a_type", PROTOCOL, listener); - int key3 = verifyRequest(NsdManager.DISCOVER_SERVICES); - - sendResponse(NsdManager.DISCOVER_SERVICES_STARTED, 0, key3, reply1); - verify(listener, timeout(mTimeoutMs).times(1)).onDiscoveryStarted("a_type"); - - // Client unregisters immediately, it fails - manager.stopServiceDiscovery(listener); - int key3again = verifyRequest(NsdManager.STOP_DISCOVERY); - assertEquals(key3, key3again); - - err = 2; - sendResponse(NsdManager.STOP_DISCOVERY_FAILED, err, key3again, "a_type"); - verify(listener, timeout(mTimeoutMs).times(1)).onStopDiscoveryFailed("a_type", err); - - // New notifications are not passed to the client anymore - sendResponse(NsdManager.SERVICE_FOUND, 0, key3, reply1); - verify(listener, timeout(mTimeoutMs).times(0)).onServiceFound(reply1); - } - - @Test - public void testInvalidCalls() { - NsdManager manager = mManager; - - NsdManager.RegistrationListener listener1 = mock(NsdManager.RegistrationListener.class); - NsdManager.DiscoveryListener listener2 = mock(NsdManager.DiscoveryListener.class); - NsdManager.ResolveListener listener3 = mock(NsdManager.ResolveListener.class); - - NsdServiceInfo invalidService = new NsdServiceInfo(null, null); - NsdServiceInfo validService = new NsdServiceInfo("a_name", "a_type"); - validService.setPort(2222); - - // Service registration - // - invalid arguments - mustFail(() -> { manager.unregisterService(null); }); - mustFail(() -> { manager.registerService(null, -1, null); }); - mustFail(() -> { manager.registerService(null, PROTOCOL, listener1); }); - mustFail(() -> { manager.registerService(invalidService, PROTOCOL, listener1); }); - mustFail(() -> { manager.registerService(validService, -1, listener1); }); - mustFail(() -> { manager.registerService(validService, PROTOCOL, null); }); - manager.registerService(validService, PROTOCOL, listener1); - // - listener already registered - mustFail(() -> { manager.registerService(validService, PROTOCOL, listener1); }); - manager.unregisterService(listener1); - // TODO: make listener immediately reusable - //mustFail(() -> { manager.unregisterService(listener1); }); - //manager.registerService(validService, PROTOCOL, listener1); - - // Discover service - // - invalid arguments - mustFail(() -> { manager.stopServiceDiscovery(null); }); - mustFail(() -> { manager.discoverServices(null, -1, null); }); - mustFail(() -> { manager.discoverServices(null, PROTOCOL, listener2); }); - mustFail(() -> { manager.discoverServices("a_service", -1, listener2); }); - mustFail(() -> { manager.discoverServices("a_service", PROTOCOL, null); }); - manager.discoverServices("a_service", PROTOCOL, listener2); - // - listener already registered - mustFail(() -> { manager.discoverServices("another_service", PROTOCOL, listener2); }); - manager.stopServiceDiscovery(listener2); - // TODO: make listener immediately reusable - //mustFail(() -> { manager.stopServiceDiscovery(listener2); }); - //manager.discoverServices("another_service", PROTOCOL, listener2); - - // Resolver service - // - invalid arguments - mustFail(() -> { manager.resolveService(null, null); }); - mustFail(() -> { manager.resolveService(null, listener3); }); - mustFail(() -> { manager.resolveService(invalidService, listener3); }); - mustFail(() -> { manager.resolveService(validService, null); }); - manager.resolveService(validService, listener3); - // - listener already registered:w - mustFail(() -> { manager.resolveService(validService, listener3); }); - } - - public void mustFail(Runnable fn) { - try { - fn.run(); - fail(); - } catch (Exception expected) { - } - } - - NsdManager makeManager() { - NsdManager manager = new NsdManager(mContext, mService); - // Acknowledge first two messages connecting the AsyncChannel. - verify(mServiceHandler, timeout(mTimeoutMs).times(2)).handleMessage(any()); - reset(mServiceHandler); - assertNotNull(mServiceHandler.chan); - return manager; - } - - int verifyRequest(int expectedMessageType) { - HandlerUtils.waitForIdle(mServiceHandler, mTimeoutMs); - verify(mServiceHandler, timeout(mTimeoutMs)).handleMessage(any()); - reset(mServiceHandler); - Message received = mServiceHandler.getLastMessage(); - assertEquals(NsdManager.nameOf(expectedMessageType), NsdManager.nameOf(received.what)); - return received.arg2; - } - - void sendResponse(int replyType, int arg, int key, Object obj) { - mServiceHandler.chan.sendMessage(replyType, arg, key, obj); - } - - // Implements the server side of AsyncChannel connection protocol - public static class MockServiceHandler extends Handler { - public final Context context; - public AsyncChannel chan; - public Message lastMessage; - - MockServiceHandler(Looper l, Context c) { - super(l); - context = c; - } - - synchronized Message getLastMessage() { - return lastMessage; - } - - synchronized void setLastMessage(Message msg) { - lastMessage = obtainMessage(); - lastMessage.copyFrom(msg); - } - - @Override - public void handleMessage(Message msg) { - setLastMessage(msg); - if (msg.what == AsyncChannel.CMD_CHANNEL_FULL_CONNECTION) { - chan = new AsyncChannel(); - chan.connect(context, this, msg.replyTo); - chan.sendMessage(AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED); - } - } - - void stop() { - getLooper().quitSafely(); - } - - static MockServiceHandler create(Context context) { - HandlerThread t = new HandlerThread("mock-service-handler"); - t.start(); - return new MockServiceHandler(t.getLooper(), context); - } - } -} diff --git a/packages/Connectivity/tests/unit/java/android/net/nsd/NsdServiceInfoTest.java b/packages/Connectivity/tests/unit/java/android/net/nsd/NsdServiceInfoTest.java deleted file mode 100644 index 94dfc7515c67f..0000000000000 --- a/packages/Connectivity/tests/unit/java/android/net/nsd/NsdServiceInfoTest.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (C) 2014 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.nsd; - -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 android.os.Bundle; -import android.os.Parcel; -import android.os.StrictMode; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.Arrays; -import java.util.Map; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class NsdServiceInfoTest { - - public final static InetAddress LOCALHOST; - static { - // Because test. - StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); - StrictMode.setThreadPolicy(policy); - - InetAddress _host = null; - try { - _host = InetAddress.getLocalHost(); - } catch (UnknownHostException e) { } - LOCALHOST = _host; - } - - @Test - public void testLimits() throws Exception { - NsdServiceInfo info = new NsdServiceInfo(); - - // Non-ASCII keys. - boolean exceptionThrown = false; - try { - info.setAttribute("猫", "meow"); - } catch (IllegalArgumentException e) { - exceptionThrown = true; - } - assertTrue(exceptionThrown); - assertEmptyServiceInfo(info); - - // ASCII keys with '=' character. - exceptionThrown = false; - try { - info.setAttribute("kitten=", "meow"); - } catch (IllegalArgumentException e) { - exceptionThrown = true; - } - assertTrue(exceptionThrown); - assertEmptyServiceInfo(info); - - // Single key + value length too long. - exceptionThrown = false; - try { - String longValue = "loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" + - "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" + - "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" + - "ooooooooooooooooooooooooooooong"; // 248 characters. - info.setAttribute("longcat", longValue); // Key + value == 255 characters. - } catch (IllegalArgumentException e) { - exceptionThrown = true; - } - assertTrue(exceptionThrown); - assertEmptyServiceInfo(info); - - // Total TXT record length too long. - exceptionThrown = false; - int recordsAdded = 0; - try { - for (int i = 100; i < 300; ++i) { - // 6 char key + 5 char value + 2 bytes overhead = 13 byte record length. - String key = String.format("key%d", i); - info.setAttribute(key, "12345"); - recordsAdded++; - } - } catch (IllegalArgumentException e) { - exceptionThrown = true; - } - assertTrue(exceptionThrown); - assertTrue(100 == recordsAdded); - assertTrue(info.getTxtRecord().length == 1300); - } - - @Test - public void testParcel() throws Exception { - NsdServiceInfo emptyInfo = new NsdServiceInfo(); - checkParcelable(emptyInfo); - - NsdServiceInfo fullInfo = new NsdServiceInfo(); - fullInfo.setServiceName("kitten"); - fullInfo.setServiceType("_kitten._tcp"); - fullInfo.setPort(4242); - fullInfo.setHost(LOCALHOST); - checkParcelable(fullInfo); - - NsdServiceInfo noHostInfo = new NsdServiceInfo(); - noHostInfo.setServiceName("kitten"); - noHostInfo.setServiceType("_kitten._tcp"); - noHostInfo.setPort(4242); - checkParcelable(noHostInfo); - - NsdServiceInfo attributedInfo = new NsdServiceInfo(); - attributedInfo.setServiceName("kitten"); - attributedInfo.setServiceType("_kitten._tcp"); - attributedInfo.setPort(4242); - attributedInfo.setHost(LOCALHOST); - attributedInfo.setAttribute("color", "pink"); - attributedInfo.setAttribute("sound", (new String("にゃあ")).getBytes("UTF-8")); - attributedInfo.setAttribute("adorable", (String) null); - attributedInfo.setAttribute("sticky", "yes"); - attributedInfo.setAttribute("siblings", new byte[] {}); - attributedInfo.setAttribute("edge cases", new byte[] {0, -1, 127, -128}); - attributedInfo.removeAttribute("sticky"); - checkParcelable(attributedInfo); - - // Sanity check that we actually wrote attributes to attributedInfo. - assertTrue(attributedInfo.getAttributes().keySet().contains("adorable")); - String sound = new String(attributedInfo.getAttributes().get("sound"), "UTF-8"); - assertTrue(sound.equals("にゃあ")); - byte[] edgeCases = attributedInfo.getAttributes().get("edge cases"); - assertTrue(Arrays.equals(edgeCases, new byte[] {0, -1, 127, -128})); - assertFalse(attributedInfo.getAttributes().keySet().contains("sticky")); - } - - public void checkParcelable(NsdServiceInfo original) { - // Write to parcel. - Parcel p = Parcel.obtain(); - Bundle writer = new Bundle(); - writer.putParcelable("test_info", original); - writer.writeToParcel(p, 0); - - // Extract from parcel. - p.setDataPosition(0); - Bundle reader = p.readBundle(); - reader.setClassLoader(NsdServiceInfo.class.getClassLoader()); - NsdServiceInfo result = reader.getParcelable("test_info"); - - // Assert equality of base fields. - assertEquals(original.getServiceName(), result.getServiceName()); - assertEquals(original.getServiceType(), result.getServiceType()); - assertEquals(original.getHost(), result.getHost()); - assertTrue(original.getPort() == result.getPort()); - - // Assert equality of attribute map. - Map originalMap = original.getAttributes(); - Map resultMap = result.getAttributes(); - assertEquals(originalMap.keySet(), resultMap.keySet()); - for (String key : originalMap.keySet()) { - assertTrue(Arrays.equals(originalMap.get(key), resultMap.get(key))); - } - } - - public void assertEmptyServiceInfo(NsdServiceInfo shouldBeEmpty) { - byte[] txtRecord = shouldBeEmpty.getTxtRecord(); - if (txtRecord == null || txtRecord.length == 0) { - return; - } - fail("NsdServiceInfo.getTxtRecord did not return null but " + Arrays.toString(txtRecord)); - } -} diff --git a/packages/Connectivity/tests/unit/java/android/net/util/DnsUtilsTest.java b/packages/Connectivity/tests/unit/java/android/net/util/DnsUtilsTest.java deleted file mode 100644 index b626db8d89e42..0000000000000 --- a/packages/Connectivity/tests/unit/java/android/net/util/DnsUtilsTest.java +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.util; - -import static android.net.util.DnsUtils.IPV6_ADDR_SCOPE_GLOBAL; -import static android.net.util.DnsUtils.IPV6_ADDR_SCOPE_LINKLOCAL; -import static android.net.util.DnsUtils.IPV6_ADDR_SCOPE_SITELOCAL; - -import static org.junit.Assert.assertEquals; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.net.InetAddresses; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.net.InetAddress; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class DnsUtilsTest { - private InetAddress stringToAddress(@NonNull String addr) { - return InetAddresses.parseNumericAddress(addr); - } - - private DnsUtils.SortableAddress makeSortableAddress(@NonNull String addr) { - return makeSortableAddress(addr, null); - } - - private DnsUtils.SortableAddress makeSortableAddress(@NonNull String addr, - @Nullable String srcAddr) { - return new DnsUtils.SortableAddress(stringToAddress(addr), - srcAddr != null ? stringToAddress(srcAddr) : null); - } - - @Test - public void testRfc6724Comparator() { - final List test = Arrays.asList( - // Ipv4 - makeSortableAddress("216.58.200.36", "192.168.1.1"), - // global with different scope src - makeSortableAddress("2404:6800:4008:801::2004", "fe80::1111:2222"), - // global without src addr - makeSortableAddress("2404:6800:cafe:801::1"), - // loop back - makeSortableAddress("::1", "::1"), - // link local - makeSortableAddress("fe80::c46f:1cff:fe04:39b4", "fe80::1"), - // teredo tunneling - makeSortableAddress("2001::47c1", "2001::2"), - // 6bone without src addr - makeSortableAddress("3ffe::1234:5678"), - // IPv4-compatible - makeSortableAddress("::216.58.200.36", "::216.58.200.9"), - // 6bone - makeSortableAddress("3ffe::1234:5678", "3ffe::1234:1"), - // IPv4-mapped IPv6 - makeSortableAddress("::ffff:192.168.95.7", "::ffff:192.168.95.1")); - - final List expected = Arrays.asList( - stringToAddress("::1"), // loop back - stringToAddress("fe80::c46f:1cff:fe04:39b4"), // link local - stringToAddress("216.58.200.36"), // Ipv4 - stringToAddress("::ffff:192.168.95.7"), // IPv4-mapped IPv6 - stringToAddress("2001::47c1"), // teredo tunneling - stringToAddress("::216.58.200.36"), // IPv4-compatible - stringToAddress("3ffe::1234:5678"), // 6bone - stringToAddress("2404:6800:4008:801::2004"), // global with different scope src - stringToAddress("2404:6800:cafe:801::1"), // global without src addr - stringToAddress("3ffe::1234:5678")); // 6bone without src addr - - Collections.sort(test, new DnsUtils.Rfc6724Comparator()); - - for (int i = 0; i < test.size(); ++i) { - assertEquals(test.get(i).address, expected.get(i)); - } - - // TODO: add more combinations - } - - @Test - public void testV4SortableAddress() { - // Test V4 address - DnsUtils.SortableAddress test = makeSortableAddress("216.58.200.36"); - assertEquals(test.hasSrcAddr, 0); - assertEquals(test.prefixMatchLen, 0); - assertEquals(test.address, stringToAddress("216.58.200.36")); - assertEquals(test.labelMatch, 0); - assertEquals(test.scopeMatch, 0); - assertEquals(test.scope, IPV6_ADDR_SCOPE_GLOBAL); - assertEquals(test.label, 4); - assertEquals(test.precedence, 35); - - // Test V4 loopback address with the same source address - test = makeSortableAddress("127.1.2.3", "127.1.2.3"); - assertEquals(test.hasSrcAddr, 1); - assertEquals(test.prefixMatchLen, 0); - assertEquals(test.address, stringToAddress("127.1.2.3")); - assertEquals(test.labelMatch, 1); - assertEquals(test.scopeMatch, 1); - assertEquals(test.scope, IPV6_ADDR_SCOPE_LINKLOCAL); - assertEquals(test.label, 4); - assertEquals(test.precedence, 35); - } - - @Test - public void testV6SortableAddress() { - // Test global address - DnsUtils.SortableAddress test = makeSortableAddress("2404:6800:4008:801::2004"); - assertEquals(test.address, stringToAddress("2404:6800:4008:801::2004")); - assertEquals(test.scope, IPV6_ADDR_SCOPE_GLOBAL); - assertEquals(test.label, 1); - assertEquals(test.precedence, 40); - - // Test global address with global source address - test = makeSortableAddress("2404:6800:4008:801::2004", - "2401:fa00:fc:fd00:6d6c:7199:b8e7:41d6"); - assertEquals(test.address, stringToAddress("2404:6800:4008:801::2004")); - assertEquals(test.hasSrcAddr, 1); - assertEquals(test.scope, IPV6_ADDR_SCOPE_GLOBAL); - assertEquals(test.labelMatch, 1); - assertEquals(test.scopeMatch, 1); - assertEquals(test.label, 1); - assertEquals(test.precedence, 40); - assertEquals(test.prefixMatchLen, 13); - - // Test global address with linklocal source address - test = makeSortableAddress("2404:6800:4008:801::2004", "fe80::c46f:1cff:fe04:39b4"); - assertEquals(test.hasSrcAddr, 1); - assertEquals(test.scope, IPV6_ADDR_SCOPE_GLOBAL); - assertEquals(test.labelMatch, 1); - assertEquals(test.scopeMatch, 0); - assertEquals(test.label, 1); - assertEquals(test.precedence, 40); - assertEquals(test.prefixMatchLen, 0); - - // Test loopback address with the same source address - test = makeSortableAddress("::1", "::1"); - assertEquals(test.hasSrcAddr, 1); - assertEquals(test.prefixMatchLen, 16 * 8); - assertEquals(test.labelMatch, 1); - assertEquals(test.scopeMatch, 1); - assertEquals(test.scope, IPV6_ADDR_SCOPE_LINKLOCAL); - assertEquals(test.label, 0); - assertEquals(test.precedence, 50); - - // Test linklocal address - test = makeSortableAddress("fe80::c46f:1cff:fe04:39b4"); - assertEquals(test.scope, IPV6_ADDR_SCOPE_LINKLOCAL); - assertEquals(test.label, 1); - assertEquals(test.precedence, 40); - - // Test linklocal address - test = makeSortableAddress("fe80::"); - assertEquals(test.scope, IPV6_ADDR_SCOPE_LINKLOCAL); - assertEquals(test.label, 1); - assertEquals(test.precedence, 40); - - // Test 6to4 address - test = makeSortableAddress("2002:c000:0204::"); - assertEquals(test.scope, IPV6_ADDR_SCOPE_GLOBAL); - assertEquals(test.label, 2); - assertEquals(test.precedence, 30); - - // Test unique local address - test = makeSortableAddress("fc00::c000:13ab"); - assertEquals(test.scope, IPV6_ADDR_SCOPE_GLOBAL); - assertEquals(test.label, 13); - assertEquals(test.precedence, 3); - - // Test teredo tunneling address - test = makeSortableAddress("2001::47c1"); - assertEquals(test.scope, IPV6_ADDR_SCOPE_GLOBAL); - assertEquals(test.label, 5); - assertEquals(test.precedence, 5); - - // Test IPv4-compatible addresses - test = makeSortableAddress("::216.58.200.36"); - assertEquals(test.scope, IPV6_ADDR_SCOPE_GLOBAL); - assertEquals(test.label, 3); - assertEquals(test.precedence, 1); - - // Test site-local address - test = makeSortableAddress("fec0::cafe:3ab2"); - assertEquals(test.scope, IPV6_ADDR_SCOPE_SITELOCAL); - assertEquals(test.label, 11); - assertEquals(test.precedence, 1); - - // Test 6bone address - test = makeSortableAddress("3ffe::1234:5678"); - assertEquals(test.scope, IPV6_ADDR_SCOPE_GLOBAL); - assertEquals(test.label, 12); - assertEquals(test.precedence, 1); - } -} diff --git a/packages/Connectivity/tests/unit/java/android/net/util/KeepaliveUtilsTest.kt b/packages/Connectivity/tests/unit/java/android/net/util/KeepaliveUtilsTest.kt deleted file mode 100644 index 5006d5345f5fc..0000000000000 --- a/packages/Connectivity/tests/unit/java/android/net/util/KeepaliveUtilsTest.kt +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.util - -import android.content.Context -import android.content.res.Resources -import android.net.ConnectivityResources -import android.net.NetworkCapabilities -import android.net.NetworkCapabilities.MAX_TRANSPORT -import android.net.NetworkCapabilities.TRANSPORT_CELLULAR -import android.net.NetworkCapabilities.TRANSPORT_ETHERNET -import android.net.NetworkCapabilities.TRANSPORT_VPN -import android.net.NetworkCapabilities.TRANSPORT_WIFI -import androidx.test.filters.SmallTest -import com.android.internal.R -import org.junit.After -import org.junit.Assert.assertArrayEquals -import org.junit.Assert.assertEquals -import org.junit.Assert.fail -import org.junit.Test -import org.junit.runner.RunWith -import org.junit.runners.JUnit4 -import org.mockito.ArgumentMatchers.eq -import org.mockito.Mockito.any -import org.mockito.Mockito.doReturn -import org.mockito.Mockito.mock - -/** - * Tests for [KeepaliveUtils]. - * - * Build, install and run with: - * atest android.net.util.KeepaliveUtilsTest - */ -@RunWith(JUnit4::class) -@SmallTest -class KeepaliveUtilsTest { - - // Prepare mocked context with given resource strings. - private fun getMockedContextWithStringArrayRes( - id: Int, - name: String, - res: Array? - ): Context { - val mockRes = mock(Resources::class.java) - doReturn(res).`when`(mockRes).getStringArray(eq(id)) - doReturn(id).`when`(mockRes).getIdentifier(eq(name), any(), any()) - - return mock(Context::class.java).apply { - doReturn(mockRes).`when`(this).getResources() - ConnectivityResources.setResourcesContextForTest(this) - } - } - - @After - fun tearDown() { - ConnectivityResources.setResourcesContextForTest(null) - } - - @Test - fun testGetSupportedKeepalives() { - fun assertRunWithException(res: Array?) { - try { - val mockContext = getMockedContextWithStringArrayRes( - R.array.config_networkSupportedKeepaliveCount, - "config_networkSupportedKeepaliveCount", res) - KeepaliveUtils.getSupportedKeepalives(mockContext) - fail("Expected KeepaliveDeviceConfigurationException") - } catch (expected: KeepaliveUtils.KeepaliveDeviceConfigurationException) { - } - } - - // Check resource with various invalid format. - assertRunWithException(null) - assertRunWithException(arrayOf(null)) - assertRunWithException(arrayOfNulls(10)) - assertRunWithException(arrayOf("")) - assertRunWithException(arrayOf("3,ABC")) - assertRunWithException(arrayOf("6,3,3")) - assertRunWithException(arrayOf("5")) - - // Check resource with invalid slots value. - assertRunWithException(arrayOf("3,-1")) - - // Check resource with invalid transport type. - assertRunWithException(arrayOf("-1,3")) - assertRunWithException(arrayOf("10,3")) - - // Check valid customization generates expected array. - val validRes = arrayOf("0,3", "1,0", "4,4") - val expectedValidRes = intArrayOf(3, 0, 0, 0, 4, 0, 0, 0, 0) - - val mockContext = getMockedContextWithStringArrayRes( - R.array.config_networkSupportedKeepaliveCount, - "config_networkSupportedKeepaliveCount", validRes) - val actual = KeepaliveUtils.getSupportedKeepalives(mockContext) - assertArrayEquals(expectedValidRes, actual) - } - - @Test - fun testGetSupportedKeepalivesForNetworkCapabilities() { - // Mock customized supported keepalives for each transport type, and assuming: - // 3 for cellular, - // 6 for wifi, - // 0 for others. - val cust = IntArray(MAX_TRANSPORT + 1).apply { - this[TRANSPORT_CELLULAR] = 3 - this[TRANSPORT_WIFI] = 6 - } - - val nc = NetworkCapabilities() - // Check supported keepalives with single transport type. - nc.transportTypes = intArrayOf(TRANSPORT_CELLULAR) - assertEquals(3, KeepaliveUtils.getSupportedKeepalivesForNetworkCapabilities(cust, nc)) - - // Check supported keepalives with multiple transport types. - nc.transportTypes = intArrayOf(TRANSPORT_WIFI, TRANSPORT_VPN) - assertEquals(0, KeepaliveUtils.getSupportedKeepalivesForNetworkCapabilities(cust, nc)) - - // Check supported keepalives with non-customized transport type. - nc.transportTypes = intArrayOf(TRANSPORT_ETHERNET) - assertEquals(0, KeepaliveUtils.getSupportedKeepalivesForNetworkCapabilities(cust, nc)) - - // Check supported keepalives with undefined transport type. - nc.transportTypes = intArrayOf(MAX_TRANSPORT + 1) - try { - KeepaliveUtils.getSupportedKeepalivesForNetworkCapabilities(cust, nc) - fail("Expected ArrayIndexOutOfBoundsException") - } catch (expected: ArrayIndexOutOfBoundsException) { - } - } -} diff --git a/packages/Connectivity/tests/unit/java/android/net/util/MultinetworkPolicyTrackerTest.kt b/packages/Connectivity/tests/unit/java/android/net/util/MultinetworkPolicyTrackerTest.kt deleted file mode 100644 index 25aa6266577e8..0000000000000 --- a/packages/Connectivity/tests/unit/java/android/net/util/MultinetworkPolicyTrackerTest.kt +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.util - -import android.content.Context -import android.content.res.Resources -import android.net.ConnectivityManager.MULTIPATH_PREFERENCE_HANDOVER -import android.net.ConnectivityManager.MULTIPATH_PREFERENCE_PERFORMANCE -import android.net.ConnectivityManager.MULTIPATH_PREFERENCE_RELIABILITY -import android.net.ConnectivityResources -import android.net.ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI -import android.net.ConnectivitySettingsManager.NETWORK_METERED_MULTIPATH_PREFERENCE -import android.net.util.MultinetworkPolicyTracker.ActiveDataSubscriptionIdListener -import android.provider.Settings -import android.telephony.SubscriptionInfo -import android.telephony.SubscriptionManager -import android.telephony.TelephonyManager -import android.test.mock.MockContentResolver -import androidx.test.filters.SmallTest -import androidx.test.runner.AndroidJUnit4 -import com.android.connectivity.resources.R -import com.android.internal.util.test.FakeSettingsProvider -import org.junit.After -import org.junit.Assert.assertEquals -import org.junit.Assert.assertFalse -import org.junit.Assert.assertTrue -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.ArgumentCaptor -import org.mockito.ArgumentMatchers.anyInt -import org.mockito.ArgumentMatchers.argThat -import org.mockito.ArgumentMatchers.eq -import org.mockito.Mockito.any -import org.mockito.Mockito.doReturn -import org.mockito.Mockito.mock -import org.mockito.Mockito.times -import org.mockito.Mockito.verify - -/** - * Tests for [MultinetworkPolicyTracker]. - * - * Build, install and run with: - * atest android.net.util.MultinetworkPolicyTrackerTest - */ -@RunWith(AndroidJUnit4::class) -@SmallTest -class MultinetworkPolicyTrackerTest { - private val resources = mock(Resources::class.java).also { - doReturn(R.integer.config_networkAvoidBadWifi).`when`(it).getIdentifier( - eq("config_networkAvoidBadWifi"), eq("integer"), any()) - doReturn(0).`when`(it).getInteger(R.integer.config_networkAvoidBadWifi) - } - private val telephonyManager = mock(TelephonyManager::class.java) - private val subscriptionManager = mock(SubscriptionManager::class.java).also { - doReturn(null).`when`(it).getActiveSubscriptionInfo(anyInt()) - } - private val resolver = MockContentResolver().apply { - addProvider(Settings.AUTHORITY, FakeSettingsProvider()) } - private val context = mock(Context::class.java).also { - doReturn(Context.TELEPHONY_SERVICE).`when`(it) - .getSystemServiceName(TelephonyManager::class.java) - doReturn(telephonyManager).`when`(it).getSystemService(Context.TELEPHONY_SERVICE) - doReturn(subscriptionManager).`when`(it) - .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE) - doReturn(resolver).`when`(it).contentResolver - doReturn(resources).`when`(it).resources - doReturn(it).`when`(it).createConfigurationContext(any()) - Settings.Global.putString(resolver, NETWORK_AVOID_BAD_WIFI, "1") - ConnectivityResources.setResourcesContextForTest(it) - } - private val tracker = MultinetworkPolicyTracker(context, null /* handler */) - - private fun assertMultipathPreference(preference: Int) { - Settings.Global.putString(resolver, NETWORK_METERED_MULTIPATH_PREFERENCE, - preference.toString()) - tracker.updateMeteredMultipathPreference() - assertEquals(preference, tracker.meteredMultipathPreference) - } - - @After - fun tearDown() { - ConnectivityResources.setResourcesContextForTest(null) - } - - @Test - fun testUpdateMeteredMultipathPreference() { - assertMultipathPreference(MULTIPATH_PREFERENCE_HANDOVER) - assertMultipathPreference(MULTIPATH_PREFERENCE_RELIABILITY) - assertMultipathPreference(MULTIPATH_PREFERENCE_PERFORMANCE) - } - - @Test - fun testUpdateAvoidBadWifi() { - Settings.Global.putString(resolver, NETWORK_AVOID_BAD_WIFI, "0") - assertTrue(tracker.updateAvoidBadWifi()) - assertFalse(tracker.avoidBadWifi) - - doReturn(1).`when`(resources).getInteger(R.integer.config_networkAvoidBadWifi) - assertTrue(tracker.updateAvoidBadWifi()) - assertTrue(tracker.avoidBadWifi) - } - - @Test - fun testOnActiveDataSubscriptionIdChanged() { - val testSubId = 1000 - val subscriptionInfo = SubscriptionInfo(testSubId, ""/* iccId */, 1/* iccId */, - "TMO"/* displayName */, "TMO"/* carrierName */, 1/* nameSource */, 1/* iconTint */, - "123"/* number */, 1/* roaming */, null/* icon */, "310"/* mcc */, "210"/* mnc */, - ""/* countryIso */, false/* isEmbedded */, null/* nativeAccessRules */, - "1"/* cardString */) - doReturn(subscriptionInfo).`when`(subscriptionManager).getActiveSubscriptionInfo(testSubId) - - // Modify avoidBadWifi and meteredMultipathPreference settings value and local variables in - // MultinetworkPolicyTracker should be also updated after subId changed. - Settings.Global.putString(resolver, NETWORK_AVOID_BAD_WIFI, "0") - Settings.Global.putString(resolver, NETWORK_METERED_MULTIPATH_PREFERENCE, - MULTIPATH_PREFERENCE_PERFORMANCE.toString()) - - val listenerCaptor = ArgumentCaptor.forClass( - ActiveDataSubscriptionIdListener::class.java) - verify(telephonyManager, times(1)) - .registerTelephonyCallback(any(), listenerCaptor.capture()) - val listener = listenerCaptor.value - listener.onActiveDataSubscriptionIdChanged(testSubId) - - // Check it get resource value with test sub id. - verify(subscriptionManager, times(1)).getActiveSubscriptionInfo(testSubId) - verify(context).createConfigurationContext(argThat { it.mcc == 310 && it.mnc == 210 }) - - // Check if avoidBadWifi and meteredMultipathPreference values have been updated. - assertFalse(tracker.avoidBadWifi) - assertEquals(MULTIPATH_PREFERENCE_PERFORMANCE, tracker.meteredMultipathPreference) - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/internal/net/NetworkUtilsInternalTest.java b/packages/Connectivity/tests/unit/java/com/android/internal/net/NetworkUtilsInternalTest.java deleted file mode 100644 index 3cfecd5529672..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/internal/net/NetworkUtilsInternalTest.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.net; - -import static android.system.OsConstants.AF_INET; -import static android.system.OsConstants.AF_INET6; -import static android.system.OsConstants.AF_UNIX; -import static android.system.OsConstants.EPERM; -import static android.system.OsConstants.SOCK_DGRAM; -import static android.system.OsConstants.SOCK_STREAM; - -import static junit.framework.Assert.assertEquals; - -import static org.junit.Assert.fail; - -import android.system.ErrnoException; -import android.system.Os; - -import androidx.test.runner.AndroidJUnit4; - -import libcore.io.IoUtils; - -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(AndroidJUnit4.class) -@androidx.test.filters.SmallTest -public class NetworkUtilsInternalTest { - - private static void expectSocketSuccess(String msg, int domain, int type) { - try { - IoUtils.closeQuietly(Os.socket(domain, type, 0)); - } catch (ErrnoException e) { - fail(msg + e.getMessage()); - } - } - - private static void expectSocketPemissionError(String msg, int domain, int type) { - try { - IoUtils.closeQuietly(Os.socket(domain, type, 0)); - fail(msg); - } catch (ErrnoException e) { - assertEquals(msg, e.errno, EPERM); - } - } - - private static void expectHasNetworking() { - expectSocketSuccess("Creating a UNIX socket should not have thrown ErrnoException", - AF_UNIX, SOCK_STREAM); - expectSocketSuccess("Creating a AF_INET socket shouldn't have thrown ErrnoException", - AF_INET, SOCK_DGRAM); - expectSocketSuccess("Creating a AF_INET6 socket shouldn't have thrown ErrnoException", - AF_INET6, SOCK_DGRAM); - } - - private static void expectNoNetworking() { - expectSocketSuccess("Creating a UNIX socket should not have thrown ErrnoException", - AF_UNIX, SOCK_STREAM); - expectSocketPemissionError( - "Creating a AF_INET socket should have thrown ErrnoException(EPERM)", - AF_INET, SOCK_DGRAM); - expectSocketPemissionError( - "Creating a AF_INET6 socket should have thrown ErrnoException(EPERM)", - AF_INET6, SOCK_DGRAM); - } - - @Test - public void testSetAllowNetworkingForProcess() { - expectHasNetworking(); - NetworkUtilsInternal.setAllowNetworkingForProcess(false); - expectNoNetworking(); - NetworkUtilsInternal.setAllowNetworkingForProcess(true); - expectHasNetworking(); - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/internal/net/VpnProfileTest.java b/packages/Connectivity/tests/unit/java/com/android/internal/net/VpnProfileTest.java deleted file mode 100644 index cb0f0710d6e7f..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/internal/net/VpnProfileTest.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.net; - -import static com.android.testutils.ParcelUtils.assertParcelSane; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import android.net.IpSecAlgorithm; - -import androidx.test.filters.SmallTest; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** Unit tests for {@link VpnProfile}. */ -@SmallTest -@RunWith(JUnit4.class) -public class VpnProfileTest { - private static final String DUMMY_PROFILE_KEY = "Test"; - - private static final int ENCODED_INDEX_AUTH_PARAMS_INLINE = 23; - private static final int ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS = 24; - - @Test - public void testDefaults() throws Exception { - final VpnProfile p = new VpnProfile(DUMMY_PROFILE_KEY); - - assertEquals(DUMMY_PROFILE_KEY, p.key); - assertEquals("", p.name); - assertEquals(VpnProfile.TYPE_PPTP, p.type); - assertEquals("", p.server); - assertEquals("", p.username); - assertEquals("", p.password); - assertEquals("", p.dnsServers); - assertEquals("", p.searchDomains); - assertEquals("", p.routes); - assertTrue(p.mppe); - assertEquals("", p.l2tpSecret); - assertEquals("", p.ipsecIdentifier); - assertEquals("", p.ipsecSecret); - assertEquals("", p.ipsecUserCert); - assertEquals("", p.ipsecCaCert); - assertEquals("", p.ipsecServerCert); - assertEquals(null, p.proxy); - assertTrue(p.getAllowedAlgorithms() != null && p.getAllowedAlgorithms().isEmpty()); - assertFalse(p.isBypassable); - assertFalse(p.isMetered); - assertEquals(1360, p.maxMtu); - assertFalse(p.areAuthParamsInline); - assertFalse(p.isRestrictedToTestNetworks); - } - - private VpnProfile getSampleIkev2Profile(String key) { - final VpnProfile p = new VpnProfile(key, true /* isRestrictedToTestNetworks */); - - p.name = "foo"; - p.type = VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS; - p.server = "bar"; - p.username = "baz"; - p.password = "qux"; - p.dnsServers = "8.8.8.8"; - p.searchDomains = ""; - p.routes = "0.0.0.0/0"; - p.mppe = false; - p.l2tpSecret = ""; - p.ipsecIdentifier = "quux"; - p.ipsecSecret = "quuz"; - p.ipsecUserCert = "corge"; - p.ipsecCaCert = "grault"; - p.ipsecServerCert = "garply"; - p.proxy = null; - p.setAllowedAlgorithms( - Arrays.asList( - IpSecAlgorithm.AUTH_CRYPT_AES_GCM, - IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305, - IpSecAlgorithm.AUTH_HMAC_SHA512, - IpSecAlgorithm.CRYPT_AES_CBC)); - p.isBypassable = true; - p.isMetered = true; - p.maxMtu = 1350; - p.areAuthParamsInline = true; - - // Not saved, but also not compared. - p.saveLogin = true; - - return p; - } - - @Test - public void testEquals() { - assertEquals( - getSampleIkev2Profile(DUMMY_PROFILE_KEY), getSampleIkev2Profile(DUMMY_PROFILE_KEY)); - - final VpnProfile modified = getSampleIkev2Profile(DUMMY_PROFILE_KEY); - modified.maxMtu--; - assertNotEquals(getSampleIkev2Profile(DUMMY_PROFILE_KEY), modified); - } - - @Test - public void testParcelUnparcel() { - assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 23); - } - - @Test - public void testEncodeDecode() { - final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY); - final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, profile.encode()); - assertEquals(profile, decoded); - } - - @Test - public void testEncodeDecodeTooManyValues() { - final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY); - final byte[] tooManyValues = - (new String(profile.encode()) + VpnProfile.VALUE_DELIMITER + "invalid").getBytes(); - - assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooManyValues)); - } - - private String getEncodedDecodedIkev2ProfileMissingValues(int... missingIndices) { - // Sort to ensure when we remove, we can do it from greatest first. - Arrays.sort(missingIndices); - - final String encoded = new String(getSampleIkev2Profile(DUMMY_PROFILE_KEY).encode()); - final List parts = - new ArrayList<>(Arrays.asList(encoded.split(VpnProfile.VALUE_DELIMITER))); - - // Remove from back first to ensure indexing is consistent. - for (int i = missingIndices.length - 1; i >= 0; i--) { - parts.remove(missingIndices[i]); - } - - return String.join(VpnProfile.VALUE_DELIMITER, parts.toArray(new String[0])); - } - - @Test - public void testEncodeDecodeInvalidNumberOfValues() { - final String tooFewValues = - getEncodedDecodedIkev2ProfileMissingValues( - ENCODED_INDEX_AUTH_PARAMS_INLINE, - ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS /* missingIndices */); - - assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes())); - } - - @Test - public void testEncodeDecodeMissingIsRestrictedToTestNetworks() { - final String tooFewValues = - getEncodedDecodedIkev2ProfileMissingValues( - ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS /* missingIndices */); - - // Verify decoding without isRestrictedToTestNetworks defaults to false - final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes()); - assertFalse(decoded.isRestrictedToTestNetworks); - } - - @Test - public void testEncodeDecodeLoginsNotSaved() { - final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY); - profile.saveLogin = false; - - final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, profile.encode()); - assertNotEquals(profile, decoded); - - // Add the username/password back, everything else must be equal. - decoded.username = profile.username; - decoded.password = profile.password; - assertEquals(profile, decoded); - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/internal/util/BitUtilsTest.java b/packages/Connectivity/tests/unit/java/com/android/internal/util/BitUtilsTest.java deleted file mode 100644 index d2fbdce9771af..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/internal/util/BitUtilsTest.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.util; - -import static com.android.internal.util.BitUtils.bytesToBEInt; -import static com.android.internal.util.BitUtils.bytesToLEInt; -import static com.android.internal.util.BitUtils.getUint16; -import static com.android.internal.util.BitUtils.getUint32; -import static com.android.internal.util.BitUtils.getUint8; -import static com.android.internal.util.BitUtils.packBits; -import static com.android.internal.util.BitUtils.uint16; -import static com.android.internal.util.BitUtils.uint32; -import static com.android.internal.util.BitUtils.uint8; -import static com.android.internal.util.BitUtils.unpackBits; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.Random; - -@SmallTest -@RunWith(AndroidJUnit4.class) -public class BitUtilsTest { - - @Test - public void testUnsignedByteWideningConversions() { - byte b0 = 0; - byte b1 = 1; - byte bm1 = -1; - assertEquals(0, uint8(b0)); - assertEquals(1, uint8(b1)); - assertEquals(127, uint8(Byte.MAX_VALUE)); - assertEquals(128, uint8(Byte.MIN_VALUE)); - assertEquals(255, uint8(bm1)); - assertEquals(255, uint8((byte)255)); - } - - @Test - public void testUnsignedShortWideningConversions() { - short s0 = 0; - short s1 = 1; - short sm1 = -1; - assertEquals(0, uint16(s0)); - assertEquals(1, uint16(s1)); - assertEquals(32767, uint16(Short.MAX_VALUE)); - assertEquals(32768, uint16(Short.MIN_VALUE)); - assertEquals(65535, uint16(sm1)); - assertEquals(65535, uint16((short)65535)); - } - - @Test - public void testUnsignedShortComposition() { - byte b0 = 0; - byte b1 = 1; - byte b2 = 2; - byte b10 = 10; - byte b16 = 16; - byte b128 = -128; - byte b224 = -32; - byte b255 = -1; - assertEquals(0x0000, uint16(b0, b0)); - assertEquals(0xffff, uint16(b255, b255)); - assertEquals(0x0a01, uint16(b10, b1)); - assertEquals(0x8002, uint16(b128, b2)); - assertEquals(0x01ff, uint16(b1, b255)); - assertEquals(0x80ff, uint16(b128, b255)); - assertEquals(0xe010, uint16(b224, b16)); - } - - @Test - public void testUnsignedIntWideningConversions() { - assertEquals(0, uint32(0)); - assertEquals(1, uint32(1)); - assertEquals(2147483647L, uint32(Integer.MAX_VALUE)); - assertEquals(2147483648L, uint32(Integer.MIN_VALUE)); - assertEquals(4294967295L, uint32(-1)); - assertEquals(4294967295L, uint32((int)4294967295L)); - } - - @Test - public void testBytesToInt() { - assertEquals(0x00000000, bytesToBEInt(bytes(0, 0, 0, 0))); - assertEquals(0xffffffff, bytesToBEInt(bytes(255, 255, 255, 255))); - assertEquals(0x0a000001, bytesToBEInt(bytes(10, 0, 0, 1))); - assertEquals(0x0a000002, bytesToBEInt(bytes(10, 0, 0, 2))); - assertEquals(0x0a001fff, bytesToBEInt(bytes(10, 0, 31, 255))); - assertEquals(0xe0000001, bytesToBEInt(bytes(224, 0, 0, 1))); - - assertEquals(0x00000000, bytesToLEInt(bytes(0, 0, 0, 0))); - assertEquals(0x01020304, bytesToLEInt(bytes(4, 3, 2, 1))); - assertEquals(0xffff0000, bytesToLEInt(bytes(0, 0, 255, 255))); - } - - @Test - public void testUnsignedGetters() { - ByteBuffer b = ByteBuffer.allocate(4); - b.putInt(0xffff); - - assertEquals(0x0, getUint8(b, 0)); - assertEquals(0x0, getUint8(b, 1)); - assertEquals(0xff, getUint8(b, 2)); - assertEquals(0xff, getUint8(b, 3)); - - assertEquals(0x0, getUint16(b, 0)); - assertEquals(0xffff, getUint16(b, 2)); - - b.rewind(); - b.putInt(0xffffffff); - assertEquals(0xffffffffL, getUint32(b, 0)); - } - - @Test - public void testBitsPacking() { - BitPackingTestCase[] testCases = { - new BitPackingTestCase(0, ints()), - new BitPackingTestCase(1, ints(0)), - new BitPackingTestCase(2, ints(1)), - new BitPackingTestCase(3, ints(0, 1)), - new BitPackingTestCase(4, ints(2)), - new BitPackingTestCase(6, ints(1, 2)), - new BitPackingTestCase(9, ints(0, 3)), - new BitPackingTestCase(~Long.MAX_VALUE, ints(63)), - new BitPackingTestCase(~Long.MAX_VALUE + 1, ints(0, 63)), - new BitPackingTestCase(~Long.MAX_VALUE + 2, ints(1, 63)), - }; - for (BitPackingTestCase tc : testCases) { - int[] got = unpackBits(tc.packedBits); - assertTrue( - "unpackBits(" - + tc.packedBits - + "): expected " - + Arrays.toString(tc.bits) - + " but got " - + Arrays.toString(got), - Arrays.equals(tc.bits, got)); - } - for (BitPackingTestCase tc : testCases) { - long got = packBits(tc.bits); - assertEquals( - "packBits(" - + Arrays.toString(tc.bits) - + "): expected " - + tc.packedBits - + " but got " - + got, - tc.packedBits, - got); - } - - long[] moreTestCases = { - 0, 1, -1, 23895, -908235, Long.MAX_VALUE, Long.MIN_VALUE, new Random().nextLong(), - }; - for (long l : moreTestCases) { - assertEquals(l, packBits(unpackBits(l))); - } - } - - static byte[] bytes(int b1, int b2, int b3, int b4) { - return new byte[] {b(b1), b(b2), b(b3), b(b4)}; - } - - static byte b(int i) { - return (byte) i; - } - - static int[] ints(int... array) { - return array; - } - - static class BitPackingTestCase { - final int[] bits; - final long packedBits; - - BitPackingTestCase(long packedBits, int[] bits) { - this.bits = bits; - this.packedBits = packedBits; - } - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/internal/util/RingBufferTest.java b/packages/Connectivity/tests/unit/java/com/android/internal/util/RingBufferTest.java deleted file mode 100644 index d06095a690cf2..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/internal/util/RingBufferTest.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.util; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.fail; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -@SmallTest -@RunWith(AndroidJUnit4.class) -public class RingBufferTest { - - @Test - public void testEmptyRingBuffer() { - RingBuffer buffer = new RingBuffer<>(String.class, 100); - - assertArrayEquals(new String[0], buffer.toArray()); - } - - @Test - public void testIncorrectConstructorArguments() { - try { - RingBuffer buffer = new RingBuffer<>(String.class, -10); - fail("Should not be able to create a negative capacity RingBuffer"); - } catch (IllegalArgumentException expected) { - } - - try { - RingBuffer buffer = new RingBuffer<>(String.class, 0); - fail("Should not be able to create a 0 capacity RingBuffer"); - } catch (IllegalArgumentException expected) { - } - } - - @Test - public void testRingBufferWithNoWrapping() { - RingBuffer buffer = new RingBuffer<>(String.class, 100); - - buffer.append("a"); - buffer.append("b"); - buffer.append("c"); - buffer.append("d"); - buffer.append("e"); - - String[] expected = {"a", "b", "c", "d", "e"}; - assertArrayEquals(expected, buffer.toArray()); - } - - @Test - public void testRingBufferWithCapacity1() { - RingBuffer buffer = new RingBuffer<>(String.class, 1); - - buffer.append("a"); - assertArrayEquals(new String[]{"a"}, buffer.toArray()); - - buffer.append("b"); - assertArrayEquals(new String[]{"b"}, buffer.toArray()); - - buffer.append("c"); - assertArrayEquals(new String[]{"c"}, buffer.toArray()); - - buffer.append("d"); - assertArrayEquals(new String[]{"d"}, buffer.toArray()); - - buffer.append("e"); - assertArrayEquals(new String[]{"e"}, buffer.toArray()); - } - - @Test - public void testRingBufferWithWrapping() { - int capacity = 100; - RingBuffer buffer = new RingBuffer<>(String.class, capacity); - - buffer.append("a"); - buffer.append("b"); - buffer.append("c"); - buffer.append("d"); - buffer.append("e"); - - String[] expected1 = {"a", "b", "c", "d", "e"}; - assertArrayEquals(expected1, buffer.toArray()); - - String[] expected2 = new String[capacity]; - int firstIndex = 0; - int lastIndex = capacity - 1; - - expected2[firstIndex] = "e"; - for (int i = 1; i < capacity; i++) { - buffer.append("x"); - expected2[i] = "x"; - } - assertArrayEquals(expected2, buffer.toArray()); - - buffer.append("x"); - expected2[firstIndex] = "x"; - assertArrayEquals(expected2, buffer.toArray()); - - for (int i = 0; i < 10; i++) { - for (String s : expected2) { - buffer.append(s); - } - } - assertArrayEquals(expected2, buffer.toArray()); - - buffer.append("a"); - expected2[lastIndex] = "a"; - assertArrayEquals(expected2, buffer.toArray()); - } - - @Test - public void testGetNextSlot() { - int capacity = 100; - RingBuffer buffer = new RingBuffer<>(DummyClass1.class, capacity); - - final DummyClass1[] actual = new DummyClass1[capacity]; - final DummyClass1[] expected = new DummyClass1[capacity]; - for (int i = 0; i < capacity; ++i) { - final DummyClass1 obj = buffer.getNextSlot(); - obj.x = capacity * i; - actual[i] = obj; - expected[i] = new DummyClass1(); - expected[i].x = capacity * i; - } - assertArrayEquals(expected, buffer.toArray()); - - for (int i = 0; i < capacity; ++i) { - if (actual[i] != buffer.getNextSlot()) { - fail("getNextSlot() should re-use objects if available"); - } - } - - RingBuffer buffer2 = new RingBuffer<>(DummyClass2.class, capacity); - assertNull("getNextSlot() should return null if the object can't be initiated " - + "(No nullary constructor)", buffer2.getNextSlot()); - - RingBuffer buffer3 = new RingBuffer<>(DummyClass3.class, capacity); - assertNull("getNextSlot() should return null if the object can't be initiated " - + "(Inaccessible class)", buffer3.getNextSlot()); - } - - public static final class DummyClass1 { - int x; - - public boolean equals(Object o) { - if (o instanceof DummyClass1) { - final DummyClass1 other = (DummyClass1) o; - return other.x == this.x; - } - return false; - } - } - - public static final class DummyClass2 { - public DummyClass2(int x) {} - } - - private static final class DummyClass3 {} -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/packages/Connectivity/tests/unit/java/com/android/server/ConnectivityServiceTest.java deleted file mode 100644 index 466138550aae7..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/ConnectivityServiceTest.java +++ /dev/null @@ -1,12901 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server; - -import static android.Manifest.permission.CHANGE_NETWORK_STATE; -import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS; -import static android.Manifest.permission.DUMP; -import static android.Manifest.permission.LOCAL_MAC_ADDRESS; -import static android.Manifest.permission.NETWORK_FACTORY; -import static android.Manifest.permission.NETWORK_SETTINGS; -import static android.app.PendingIntent.FLAG_IMMUTABLE; -import static android.content.Intent.ACTION_PACKAGE_ADDED; -import static android.content.Intent.ACTION_PACKAGE_REMOVED; -import static android.content.Intent.ACTION_PACKAGE_REPLACED; -import static android.content.Intent.ACTION_USER_ADDED; -import static android.content.Intent.ACTION_USER_REMOVED; -import static android.content.Intent.ACTION_USER_UNLOCKED; -import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; -import static android.content.pm.PackageManager.FEATURE_WIFI; -import static android.content.pm.PackageManager.FEATURE_WIFI_DIRECT; -import static android.content.pm.PackageManager.GET_PERMISSIONS; -import static android.content.pm.PackageManager.MATCH_ANY_USER; -import static android.content.pm.PackageManager.PERMISSION_DENIED; -import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN; -import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_DATA_SAVER; -import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_MASK; -import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_USER_RESTRICTED; -import static android.net.ConnectivityManager.BLOCKED_REASON_BATTERY_SAVER; -import static android.net.ConnectivityManager.BLOCKED_REASON_NONE; -import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; -import static android.net.ConnectivityManager.EXTRA_NETWORK_INFO; -import static android.net.ConnectivityManager.EXTRA_NETWORK_TYPE; -import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT; -import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE; -import static android.net.ConnectivityManager.TYPE_ETHERNET; -import static android.net.ConnectivityManager.TYPE_MOBILE; -import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA; -import static android.net.ConnectivityManager.TYPE_MOBILE_MMS; -import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL; -import static android.net.ConnectivityManager.TYPE_PROXY; -import static android.net.ConnectivityManager.TYPE_VPN; -import static android.net.ConnectivityManager.TYPE_WIFI; -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.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS; -import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK; -import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTP; -import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTPS; -import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS; -import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL; -import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID; -import static android.net.NetworkCapabilities.NET_CAPABILITY_BIP; -import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL; -import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS; -import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN; -import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS; -import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE; -import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND; -import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA; -import static android.net.NetworkCapabilities.NET_CAPABILITY_IA; -import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS; -import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; -import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED; -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_ROAMING; -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_NOT_VPN; -import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID; -import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE; -import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY; -import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS; -import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL; -import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_VSIM; -import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P; -import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP; -import static android.net.NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION; -import static android.net.NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS; -import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS; -import static android.net.NetworkCapabilities.REDACT_NONE; -import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; -import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET; -import static android.net.NetworkCapabilities.TRANSPORT_VPN; -import static android.net.NetworkCapabilities.TRANSPORT_WIFI; -import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE; -import static android.net.NetworkScore.KEEP_CONNECTED_FOR_HANDOVER; -import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID; -import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK; -import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; -import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY; -import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_UNINITIALIZED; -import static android.net.RouteInfo.RTN_UNREACHABLE; -import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.PREFIX_OPERATION_ADDED; -import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.PREFIX_OPERATION_REMOVED; -import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_FAILURE; -import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_SUCCESS; -import static android.os.Process.INVALID_UID; -import static android.system.OsConstants.IPPROTO_TCP; - -import static com.android.server.ConnectivityServiceTestUtils.transportToLegacyType; -import static com.android.testutils.ConcurrentUtils.await; -import static com.android.testutils.ConcurrentUtils.durationOf; -import static com.android.testutils.ExceptionUtils.ignoreExceptions; -import static com.android.testutils.HandlerUtils.waitForIdleSerialExecutor; -import static com.android.testutils.MiscAsserts.assertContainsAll; -import static com.android.testutils.MiscAsserts.assertContainsExactly; -import static com.android.testutils.MiscAsserts.assertEmpty; -import static com.android.testutils.MiscAsserts.assertLength; -import static com.android.testutils.MiscAsserts.assertRunsInAtMost; -import static com.android.testutils.MiscAsserts.assertSameElements; -import static com.android.testutils.MiscAsserts.assertThrows; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.AdditionalMatchers.aryEq; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.isNull; -import static org.mockito.ArgumentMatchers.startsWith; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.timeout; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.Manifest; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.app.AlarmManager; -import android.app.AppOpsManager; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.app.usage.NetworkStatsManager; -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.ContentProvider; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.pm.ServiceInfo; -import android.content.pm.UserInfo; -import android.content.res.Resources; -import android.location.LocationManager; -import android.net.CaptivePortalData; -import android.net.ConnectionInfo; -import android.net.ConnectivityManager; -import android.net.ConnectivityManager.NetworkCallback; -import android.net.ConnectivityManager.PacketKeepalive; -import android.net.ConnectivityManager.PacketKeepaliveCallback; -import android.net.ConnectivityManager.TooManyRequestsException; -import android.net.ConnectivityResources; -import android.net.ConnectivitySettingsManager; -import android.net.ConnectivityThread; -import android.net.DataStallReportParcelable; -import android.net.EthernetManager; -import android.net.IConnectivityDiagnosticsCallback; -import android.net.IDnsResolver; -import android.net.INetd; -import android.net.INetworkMonitor; -import android.net.INetworkMonitorCallbacks; -import android.net.IOnCompleteListener; -import android.net.IQosCallback; -import android.net.InetAddresses; -import android.net.InterfaceConfigurationParcel; -import android.net.IpPrefix; -import android.net.IpSecManager; -import android.net.IpSecManager.UdpEncapsulationSocket; -import android.net.LinkAddress; -import android.net.LinkProperties; -import android.net.MatchAllNetworkSpecifier; -import android.net.NativeNetworkConfig; -import android.net.NativeNetworkType; -import android.net.Network; -import android.net.NetworkAgent; -import android.net.NetworkAgentConfig; -import android.net.NetworkCapabilities; -import android.net.NetworkFactory; -import android.net.NetworkInfo; -import android.net.NetworkInfo.DetailedState; -import android.net.NetworkPolicyManager; -import android.net.NetworkPolicyManager.NetworkPolicyCallback; -import android.net.NetworkRequest; -import android.net.NetworkScore; -import android.net.NetworkSpecifier; -import android.net.NetworkStack; -import android.net.NetworkStateSnapshot; -import android.net.NetworkTestResultParcelable; -import android.net.OemNetworkPreferences; -import android.net.ProxyInfo; -import android.net.QosCallbackException; -import android.net.QosFilter; -import android.net.QosSession; -import android.net.ResolverParamsParcel; -import android.net.RouteInfo; -import android.net.RouteInfoParcel; -import android.net.SocketKeepalive; -import android.net.TransportInfo; -import android.net.UidRange; -import android.net.UidRangeParcel; -import android.net.UnderlyingNetworkInfo; -import android.net.Uri; -import android.net.VpnManager; -import android.net.VpnTransportInfo; -import android.net.metrics.IpConnectivityLog; -import android.net.networkstack.NetworkStackClientBase; -import android.net.resolv.aidl.Nat64PrefixEventParcel; -import android.net.resolv.aidl.PrivateDnsValidationEventParcel; -import android.net.shared.NetworkMonitorUtils; -import android.net.shared.PrivateDnsConfig; -import android.net.util.MultinetworkPolicyTracker; -import android.os.BadParcelableException; -import android.os.Binder; -import android.os.Build; -import android.os.Bundle; -import android.os.ConditionVariable; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.INetworkManagementService; -import android.os.Looper; -import android.os.Parcel; -import android.os.ParcelFileDescriptor; -import android.os.Parcelable; -import android.os.Process; -import android.os.RemoteException; -import android.os.ServiceSpecificException; -import android.os.SystemClock; -import android.os.SystemConfigManager; -import android.os.UserHandle; -import android.os.UserManager; -import android.provider.Settings; -import android.security.Credentials; -import android.system.Os; -import android.telephony.TelephonyManager; -import android.telephony.data.EpsBearerQosSessionAttributes; -import android.telephony.data.NrQosSessionAttributes; -import android.test.mock.MockContentResolver; -import android.text.TextUtils; -import android.util.ArraySet; -import android.util.Log; -import android.util.Pair; -import android.util.Range; -import android.util.SparseArray; - -import androidx.test.InstrumentationRegistry; -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.connectivity.resources.R; -import com.android.internal.net.VpnConfig; -import com.android.internal.net.VpnProfile; -import com.android.internal.util.ArrayUtils; -import com.android.internal.util.WakeupMessage; -import com.android.internal.util.test.BroadcastInterceptingContext; -import com.android.internal.util.test.FakeSettingsProvider; -import com.android.net.module.util.ArrayTrackRecord; -import com.android.server.ConnectivityService.ConnectivityDiagnosticsCallbackInfo; -import com.android.server.connectivity.MockableSystemProperties; -import com.android.server.connectivity.Nat464Xlat; -import com.android.server.connectivity.NetworkAgentInfo; -import com.android.server.connectivity.NetworkNotificationManager.NotificationType; -import com.android.server.connectivity.ProxyTracker; -import com.android.server.connectivity.QosCallbackTracker; -import com.android.server.connectivity.Vpn; -import com.android.server.connectivity.VpnProfileStore; -import com.android.server.net.NetworkPinner; -import com.android.testutils.ExceptionUtils; -import com.android.testutils.HandlerUtils; -import com.android.testutils.RecorderCallback.CallbackEntry; -import com.android.testutils.TestableNetworkCallback; - -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.AdditionalAnswers; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; -import org.mockito.stubbing.Answer; - -import java.io.FileDescriptor; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.net.DatagramSocket; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Predicate; -import java.util.function.Supplier; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -import kotlin.reflect.KClass; - -/** - * Tests for {@link ConnectivityService}. - * - * Build, install and run with: - * runtest frameworks-net -c com.android.server.ConnectivityServiceTest - */ -@RunWith(AndroidJUnit4.class) -@SmallTest -public class ConnectivityServiceTest { - private static final String TAG = "ConnectivityServiceTest"; - - private static final int TIMEOUT_MS = 500; - // Broadcasts can take a long time to be delivered. The test will not wait for that long unless - // there is a failure, so use a long timeout. - private static final int BROADCAST_TIMEOUT_MS = 30_000; - private static final int TEST_LINGER_DELAY_MS = 400; - private static final int TEST_NASCENT_DELAY_MS = 300; - // Chosen to be less than the linger and nascent timeout. This ensures that we can distinguish - // between a LOST callback that arrives immediately and a LOST callback that arrives after - // the linger/nascent timeout. For this, our assertions should run fast enough to leave - // less than (mService.mLingerDelayMs - TEST_CALLBACK_TIMEOUT_MS) between the time callbacks are - // supposedly fired, and the time we call expectCallback. - private static final int TEST_CALLBACK_TIMEOUT_MS = 250; - // Chosen to be less than TEST_CALLBACK_TIMEOUT_MS. This ensures that requests have time to - // complete before callbacks are verified. - private static final int TEST_REQUEST_TIMEOUT_MS = 150; - - private static final int UNREASONABLY_LONG_ALARM_WAIT_MS = 1000; - - private static final long TIMESTAMP = 1234L; - - private static final int NET_ID = 110; - private static final int OEM_PREF_ANY_NET_ID = -1; - // Set a non-zero value to verify the flow to set tcp init rwnd value. - private static final int TEST_TCP_INIT_RWND = 60; - - // Used for testing the per-work-profile default network. - private static final int TEST_APP_ID = 103; - private static final int TEST_WORK_PROFILE_USER_ID = 2; - private static final int TEST_WORK_PROFILE_APP_UID = - UserHandle.getUid(TEST_WORK_PROFILE_USER_ID, TEST_APP_ID); - private static final String CLAT_PREFIX = "v4-"; - private static final String MOBILE_IFNAME = "test_rmnet_data0"; - private static final String WIFI_IFNAME = "test_wlan0"; - private static final String WIFI_WOL_IFNAME = "test_wlan_wol"; - private static final String VPN_IFNAME = "tun10042"; - private static final String TEST_PACKAGE_NAME = "com.android.test.package"; - private static final int TEST_PACKAGE_UID = 123; - private static final String ALWAYS_ON_PACKAGE = "com.android.test.alwaysonvpn"; - - private static final String INTERFACE_NAME = "interface"; - - private static final String TEST_VENUE_URL_NA_PASSPOINT = "https://android.com/"; - private static final String TEST_VENUE_URL_NA_OTHER = "https://example.com/"; - private static final String TEST_TERMS_AND_CONDITIONS_URL_NA_PASSPOINT = - "https://android.com/terms/"; - private static final String TEST_TERMS_AND_CONDITIONS_URL_NA_OTHER = - "https://example.com/terms/"; - private static final String TEST_VENUE_URL_CAPPORT = "https://android.com/capport/"; - private static final String TEST_USER_PORTAL_API_URL_CAPPORT = - "https://android.com/user/api/capport/"; - private static final String TEST_FRIENDLY_NAME = "Network friendly name"; - private static final String TEST_REDIRECT_URL = "http://example.com/firstPath"; - - private MockContext mServiceContext; - private HandlerThread mCsHandlerThread; - private HandlerThread mVMSHandlerThread; - private ConnectivityService.Dependencies mDeps; - private ConnectivityService mService; - private WrappedConnectivityManager mCm; - private TestNetworkAgentWrapper mWiFiNetworkAgent; - private TestNetworkAgentWrapper mCellNetworkAgent; - private TestNetworkAgentWrapper mEthernetNetworkAgent; - private MockVpn mMockVpn; - private Context mContext; - private NetworkPolicyCallback mPolicyCallback; - private WrappedMultinetworkPolicyTracker mPolicyTracker; - private HandlerThread mAlarmManagerThread; - private TestNetIdManager mNetIdManager; - private QosCallbackMockHelper mQosCallbackMockHelper; - private QosCallbackTracker mQosCallbackTracker; - private VpnManagerService mVpnManagerService; - private TestNetworkCallback mDefaultNetworkCallback; - private TestNetworkCallback mSystemDefaultNetworkCallback; - private TestNetworkCallback mProfileDefaultNetworkCallback; - - // State variables required to emulate NetworkPolicyManagerService behaviour. - private int mBlockedReasons = BLOCKED_REASON_NONE; - - @Mock DeviceIdleInternal mDeviceIdleInternal; - @Mock INetworkManagementService mNetworkManagementService; - @Mock NetworkStatsManager mStatsManager; - @Mock IDnsResolver mMockDnsResolver; - @Mock INetd mMockNetd; - @Mock NetworkStackClientBase mNetworkStack; - @Mock PackageManager mPackageManager; - @Mock UserManager mUserManager; - @Mock NotificationManager mNotificationManager; - @Mock AlarmManager mAlarmManager; - @Mock IConnectivityDiagnosticsCallback mConnectivityDiagnosticsCallback; - @Mock IBinder mIBinder; - @Mock LocationManager mLocationManager; - @Mock AppOpsManager mAppOpsManager; - @Mock TelephonyManager mTelephonyManager; - @Mock MockableSystemProperties mSystemProperties; - @Mock EthernetManager mEthernetManager; - @Mock NetworkPolicyManager mNetworkPolicyManager; - @Mock VpnProfileStore mVpnProfileStore; - @Mock SystemConfigManager mSystemConfigManager; - @Mock Resources mResources; - - private ArgumentCaptor mResolverParamsParcelCaptor = - ArgumentCaptor.forClass(ResolverParamsParcel.class); - - // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods - // do not go through ConnectivityService but talk to netd directly, so they don't automatically - // reflect the state of our test ConnectivityService. - private class WrappedConnectivityManager extends ConnectivityManager { - private Network mFakeBoundNetwork; - - public synchronized boolean bindProcessToNetwork(Network network) { - mFakeBoundNetwork = network; - return true; - } - - public synchronized Network getBoundNetworkForProcess() { - return mFakeBoundNetwork; - } - - public WrappedConnectivityManager(Context context, ConnectivityService service) { - super(context, service); - } - } - - private class MockContext extends BroadcastInterceptingContext { - private final MockContentResolver mContentResolver; - - @Spy private Resources mInternalResources; - private final LinkedBlockingQueue mStartedActivities = new LinkedBlockingQueue<>(); - - // Map of permission name -> PermissionManager.Permission_{GRANTED|DENIED} constant - private final HashMap mMockedPermissions = new HashMap<>(); - - MockContext(Context base, ContentProvider settingsProvider) { - super(base); - - mInternalResources = spy(base.getResources()); - when(mInternalResources.getStringArray(com.android.internal.R.array.networkAttributes)) - .thenReturn(new String[] { - "wifi,1,1,1,-1,true", - "mobile,0,0,0,-1,true", - "mobile_mms,2,0,2,60000,true", - "mobile_supl,3,0,2,60000,true", - }); - - mContentResolver = new MockContentResolver(); - mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider); - } - - @Override - public void startActivityAsUser(Intent intent, UserHandle handle) { - mStartedActivities.offer(intent); - } - - public Intent expectStartActivityIntent(int timeoutMs) { - Intent intent = null; - try { - intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) {} - assertNotNull("Did not receive sign-in intent after " + timeoutMs + "ms", intent); - return intent; - } - - public void expectNoStartActivityIntent(int timeoutMs) { - try { - assertNull("Received unexpected Intent to start activity", - mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS)); - } catch (InterruptedException e) {} - } - - @Override - public ComponentName startService(Intent service) { - final String action = service.getAction(); - if (!VpnConfig.SERVICE_INTERFACE.equals(action)) { - fail("Attempt to start unknown service, action=" + action); - } - return new ComponentName(service.getPackage(), "com.android.test.Service"); - } - - @Override - public Object getSystemService(String name) { - if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm; - if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager; - if (Context.USER_SERVICE.equals(name)) return mUserManager; - if (Context.ALARM_SERVICE.equals(name)) return mAlarmManager; - if (Context.LOCATION_SERVICE.equals(name)) return mLocationManager; - if (Context.APP_OPS_SERVICE.equals(name)) return mAppOpsManager; - if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager; - if (Context.ETHERNET_SERVICE.equals(name)) return mEthernetManager; - if (Context.NETWORK_POLICY_SERVICE.equals(name)) return mNetworkPolicyManager; - if (Context.SYSTEM_CONFIG_SERVICE.equals(name)) return mSystemConfigManager; - if (Context.NETWORK_STATS_SERVICE.equals(name)) return mStatsManager; - return super.getSystemService(name); - } - - final HashMap mUserManagers = new HashMap<>(); - @Override - public Context createContextAsUser(UserHandle user, int flags) { - final Context asUser = mock(Context.class, AdditionalAnswers.delegatesTo(this)); - doReturn(user).when(asUser).getUser(); - doAnswer((inv) -> { - final UserManager um = mUserManagers.computeIfAbsent(user, - u -> mock(UserManager.class, AdditionalAnswers.delegatesTo(mUserManager))); - return um; - }).when(asUser).getSystemService(Context.USER_SERVICE); - return asUser; - } - - public void setWorkProfile(@NonNull final UserHandle userHandle, boolean value) { - // This relies on all contexts for a given user returning the same UM mock - final UserManager umMock = createContextAsUser(userHandle, 0 /* flags */) - .getSystemService(UserManager.class); - doReturn(value).when(umMock).isManagedProfile(); - doReturn(value).when(mUserManager).isManagedProfile(eq(userHandle.getIdentifier())); - } - - @Override - public ContentResolver getContentResolver() { - return mContentResolver; - } - - @Override - public Resources getResources() { - return mInternalResources; - } - - @Override - public PackageManager getPackageManager() { - return mPackageManager; - } - - private int checkMockedPermission(String permission, Supplier ifAbsent) { - final Integer granted = mMockedPermissions.get(permission); - return granted != null ? granted : ifAbsent.get(); - } - - @Override - public int checkPermission(String permission, int pid, int uid) { - return checkMockedPermission( - permission, () -> super.checkPermission(permission, pid, uid)); - } - - @Override - public int checkCallingOrSelfPermission(String permission) { - return checkMockedPermission( - permission, () -> super.checkCallingOrSelfPermission(permission)); - } - - @Override - public void enforceCallingOrSelfPermission(String permission, String message) { - final Integer granted = mMockedPermissions.get(permission); - if (granted == null) { - super.enforceCallingOrSelfPermission(permission, message); - return; - } - - if (!granted.equals(PERMISSION_GRANTED)) { - throw new SecurityException("[Test] permission denied: " + permission); - } - } - - /** - * Mock checks for the specified permission, and have them behave as per {@code granted}. - * - *

      Passing null reverts to default behavior, which does a real permission check on the - * test package. - * @param granted One of {@link PackageManager#PERMISSION_GRANTED} or - * {@link PackageManager#PERMISSION_DENIED}. - */ - public void setPermission(String permission, Integer granted) { - mMockedPermissions.put(permission, granted); - } - } - - private void waitForIdle() { - HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS); - waitForIdle(mCellNetworkAgent, TIMEOUT_MS); - waitForIdle(mWiFiNetworkAgent, TIMEOUT_MS); - waitForIdle(mEthernetNetworkAgent, TIMEOUT_MS); - HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS); - HandlerUtils.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS); - } - - private void waitForIdle(TestNetworkAgentWrapper agent, long timeoutMs) { - if (agent == null) { - return; - } - agent.waitForIdle(timeoutMs); - } - - @Test - public void testWaitForIdle() throws Exception { - final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng. - - // Tests that waitForIdle returns immediately if the service is already idle. - for (int i = 0; i < attempts; i++) { - waitForIdle(); - } - - // Bring up a network that we can use to send messages to ConnectivityService. - ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED); - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); - b.expectBroadcast(); - Network n = mWiFiNetworkAgent.getNetwork(); - assertNotNull(n); - - // Tests that calling waitForIdle waits for messages to be processed. - for (int i = 0; i < attempts; i++) { - mWiFiNetworkAgent.setSignalStrength(i); - waitForIdle(); - assertEquals(i, mCm.getNetworkCapabilities(n).getSignalStrength()); - } - } - - // This test has an inherent race condition in it, and cannot be enabled for continuous testing - // or presubmit tests. It is kept for manual runs and documentation purposes. - @Ignore - public void verifyThatNotWaitingForIdleCausesRaceConditions() throws Exception { - // Bring up a network that we can use to send messages to ConnectivityService. - ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED); - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); - b.expectBroadcast(); - Network n = mWiFiNetworkAgent.getNetwork(); - assertNotNull(n); - - // Ensure that not calling waitForIdle causes a race condition. - final int attempts = 50; // Causes the test to take about 200ms on bullhead-eng. - for (int i = 0; i < attempts; i++) { - mWiFiNetworkAgent.setSignalStrength(i); - if (i != mCm.getNetworkCapabilities(n).getSignalStrength()) { - // We hit a race condition, as expected. Pass the test. - return; - } - } - - // No race? There is a bug in this test. - fail("expected race condition at least once in " + attempts + " attempts"); - } - - private class TestNetworkAgentWrapper extends NetworkAgentWrapper { - private static final int VALIDATION_RESULT_INVALID = 0; - - private static final long DATA_STALL_TIMESTAMP = 10L; - private static final int DATA_STALL_DETECTION_METHOD = 1; - - private INetworkMonitor mNetworkMonitor; - private INetworkMonitorCallbacks mNmCallbacks; - private int mNmValidationResult = VALIDATION_RESULT_INVALID; - private int mProbesCompleted; - private int mProbesSucceeded; - private String mNmValidationRedirectUrl = null; - private boolean mNmProvNotificationRequested = false; - private Runnable mCreatedCallback; - private Runnable mUnwantedCallback; - private Runnable mDisconnectedCallback; - - private final ConditionVariable mNetworkStatusReceived = new ConditionVariable(); - // Contains the redirectUrl from networkStatus(). Before reading, wait for - // mNetworkStatusReceived. - private String mRedirectUrl; - - TestNetworkAgentWrapper(int transport) throws Exception { - this(transport, new LinkProperties(), null); - } - - TestNetworkAgentWrapper(int transport, LinkProperties linkProperties) - throws Exception { - this(transport, linkProperties, null); - } - - private TestNetworkAgentWrapper(int transport, LinkProperties linkProperties, - NetworkCapabilities ncTemplate) throws Exception { - super(transport, linkProperties, ncTemplate, mServiceContext); - - // Waits for the NetworkAgent to be registered, which includes the creation of the - // NetworkMonitor. - waitForIdle(TIMEOUT_MS); - HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS); - HandlerUtils.waitForIdle(ConnectivityThread.get(), TIMEOUT_MS); - } - - @Override - protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties, - NetworkAgentConfig nac) throws Exception { - mNetworkMonitor = mock(INetworkMonitor.class); - - final Answer validateAnswer = inv -> { - new Thread(ignoreExceptions(this::onValidationRequested)).start(); - return null; - }; - - doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any()); - doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt()); - - final ArgumentCaptor nmNetworkCaptor = ArgumentCaptor.forClass(Network.class); - final ArgumentCaptor nmCbCaptor = - ArgumentCaptor.forClass(INetworkMonitorCallbacks.class); - doNothing().when(mNetworkStack).makeNetworkMonitor( - nmNetworkCaptor.capture(), - any() /* name */, - nmCbCaptor.capture()); - - final InstrumentedNetworkAgent na = - new InstrumentedNetworkAgent(this, linkProperties, nac) { - @Override - public void networkStatus(int status, String redirectUrl) { - mRedirectUrl = redirectUrl; - mNetworkStatusReceived.open(); - } - - @Override - public void onNetworkCreated() { - super.onNetworkCreated(); - if (mCreatedCallback != null) mCreatedCallback.run(); - } - - @Override - public void onNetworkUnwanted() { - super.onNetworkUnwanted(); - if (mUnwantedCallback != null) mUnwantedCallback.run(); - } - - @Override - public void onNetworkDestroyed() { - super.onNetworkDestroyed(); - if (mDisconnectedCallback != null) mDisconnectedCallback.run(); - } - }; - - assertEquals(na.getNetwork().netId, nmNetworkCaptor.getValue().netId); - mNmCallbacks = nmCbCaptor.getValue(); - - mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor); - - return na; - } - - private void onValidationRequested() throws Exception { - if (mNmProvNotificationRequested - && ((mNmValidationResult & NETWORK_VALIDATION_RESULT_VALID) != 0)) { - mNmCallbacks.hideProvisioningNotification(); - mNmProvNotificationRequested = false; - } - - mNmCallbacks.notifyProbeStatusChanged(mProbesCompleted, mProbesSucceeded); - final NetworkTestResultParcelable p = new NetworkTestResultParcelable(); - p.result = mNmValidationResult; - p.probesAttempted = mProbesCompleted; - p.probesSucceeded = mProbesSucceeded; - p.redirectUrl = mNmValidationRedirectUrl; - p.timestampMillis = TIMESTAMP; - mNmCallbacks.notifyNetworkTestedWithExtras(p); - - if (mNmValidationRedirectUrl != null) { - mNmCallbacks.showProvisioningNotification( - "test_provisioning_notif_action", TEST_PACKAGE_NAME); - mNmProvNotificationRequested = true; - } - } - - /** - * Connect without adding any internet capability. - */ - public void connectWithoutInternet() { - super.connect(); - } - - /** - * Transition this NetworkAgent to CONNECTED state with NET_CAPABILITY_INTERNET. - * @param validated Indicate if network should pretend to be validated. - */ - public void connect(boolean validated) { - connect(validated, true, false /* isStrictMode */); - } - - /** - * Transition this NetworkAgent to CONNECTED state. - * @param validated Indicate if network should pretend to be validated. - * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET. - */ - public void connect(boolean validated, boolean hasInternet, boolean isStrictMode) { - assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_INTERNET)); - - ConnectivityManager.NetworkCallback callback = null; - final ConditionVariable validatedCv = new ConditionVariable(); - if (validated) { - setNetworkValid(isStrictMode); - NetworkRequest request = new NetworkRequest.Builder() - .addTransportType(getNetworkCapabilities().getTransportTypes()[0]) - .clearCapabilities() - .build(); - callback = new ConnectivityManager.NetworkCallback() { - public void onCapabilitiesChanged(Network network, - NetworkCapabilities networkCapabilities) { - if (network.equals(getNetwork()) && - networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) { - validatedCv.open(); - } - } - }; - mCm.registerNetworkCallback(request, callback); - } - if (hasInternet) { - addCapability(NET_CAPABILITY_INTERNET); - } - - connectWithoutInternet(); - - if (validated) { - // Wait for network to validate. - waitFor(validatedCv); - setNetworkInvalid(isStrictMode); - } - - if (callback != null) mCm.unregisterNetworkCallback(callback); - } - - public void connectWithCaptivePortal(String redirectUrl, boolean isStrictMode) { - setNetworkPortal(redirectUrl, isStrictMode); - connect(false, true /* hasInternet */, isStrictMode); - } - - public void connectWithPartialConnectivity() { - setNetworkPartial(); - connect(false); - } - - public void connectWithPartialValidConnectivity(boolean isStrictMode) { - setNetworkPartialValid(isStrictMode); - connect(false, true /* hasInternet */, isStrictMode); - } - - void setNetworkValid(boolean isStrictMode) { - mNmValidationResult = NETWORK_VALIDATION_RESULT_VALID; - mNmValidationRedirectUrl = null; - int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS; - if (isStrictMode) { - probesSucceeded |= NETWORK_VALIDATION_PROBE_PRIVDNS; - } - // The probesCompleted equals to probesSucceeded for the case of valid network, so put - // the same value into two different parameter of the method. - setProbesStatus(probesSucceeded, probesSucceeded); - } - - void setNetworkInvalid(boolean isStrictMode) { - mNmValidationResult = VALIDATION_RESULT_INVALID; - mNmValidationRedirectUrl = null; - int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS - | NETWORK_VALIDATION_PROBE_HTTP; - int probesSucceeded = 0; - // If the isStrictMode is true, it means the network is invalid when NetworkMonitor - // tried to validate the private DNS but failed. - if (isStrictMode) { - probesCompleted &= ~NETWORK_VALIDATION_PROBE_HTTP; - probesSucceeded = probesCompleted; - probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS; - } - setProbesStatus(probesCompleted, probesSucceeded); - } - - void setNetworkPortal(String redirectUrl, boolean isStrictMode) { - setNetworkInvalid(isStrictMode); - mNmValidationRedirectUrl = redirectUrl; - // Suppose the portal is found when NetworkMonitor probes NETWORK_VALIDATION_PROBE_HTTP - // in the beginning, so the NETWORK_VALIDATION_PROBE_HTTPS hasn't probed yet. - int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP; - int probesSucceeded = VALIDATION_RESULT_INVALID; - if (isStrictMode) { - probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS; - } - setProbesStatus(probesCompleted, probesSucceeded); - } - - void setNetworkPartial() { - mNmValidationResult = NETWORK_VALIDATION_RESULT_PARTIAL; - mNmValidationRedirectUrl = null; - int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS - | NETWORK_VALIDATION_PROBE_FALLBACK; - int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_FALLBACK; - setProbesStatus(probesCompleted, probesSucceeded); - } - - void setNetworkPartialValid(boolean isStrictMode) { - setNetworkPartial(); - mNmValidationResult |= NETWORK_VALIDATION_RESULT_VALID; - int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS - | NETWORK_VALIDATION_PROBE_HTTP; - int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP; - // Suppose the partial network cannot pass the private DNS validation as well, so only - // add NETWORK_VALIDATION_PROBE_DNS in probesCompleted but not probesSucceeded. - if (isStrictMode) { - probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS; - } - setProbesStatus(probesCompleted, probesSucceeded); - } - - void setProbesStatus(int probesCompleted, int probesSucceeded) { - mProbesCompleted = probesCompleted; - mProbesSucceeded = probesSucceeded; - } - - void notifyCapportApiDataChanged(CaptivePortalData data) { - try { - mNmCallbacks.notifyCaptivePortalDataChanged(data); - } catch (RemoteException e) { - throw new AssertionError("This cannot happen", e); - } - } - - public String waitForRedirectUrl() { - assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS)); - return mRedirectUrl; - } - - public void expectDisconnected() { - expectDisconnected(TIMEOUT_MS); - } - - public void expectPreventReconnectReceived() { - expectPreventReconnectReceived(TIMEOUT_MS); - } - - void notifyDataStallSuspected() throws Exception { - final DataStallReportParcelable p = new DataStallReportParcelable(); - p.detectionMethod = DATA_STALL_DETECTION_METHOD; - p.timestampMillis = DATA_STALL_TIMESTAMP; - mNmCallbacks.notifyDataStallSuspected(p); - } - - public void setCreatedCallback(Runnable r) { - mCreatedCallback = r; - } - - public void setUnwantedCallback(Runnable r) { - mUnwantedCallback = r; - } - - public void setDisconnectedCallback(Runnable r) { - mDisconnectedCallback = r; - } - } - - /** - * A NetworkFactory that allows to wait until any in-flight NetworkRequest add or remove - * operations have been processed and test for them. - */ - private static class MockNetworkFactory extends NetworkFactory { - private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false); - - static class RequestEntry { - @NonNull - public final NetworkRequest request; - - RequestEntry(@NonNull final NetworkRequest request) { - this.request = request; - } - - static final class Add extends RequestEntry { - Add(@NonNull final NetworkRequest request) { - super(request); - } - } - - static final class Remove extends RequestEntry { - Remove(@NonNull final NetworkRequest request) { - super(request); - } - } - - @Override - public String toString() { - return "RequestEntry [ " + getClass().getName() + " : " + request + " ]"; - } - } - - // History of received requests adds and removes. - private final ArrayTrackRecord.ReadHead mRequestHistory = - new ArrayTrackRecord().newReadHead(); - - private static T failIfNull(@Nullable final T obj, @Nullable final String message) { - if (null == obj) fail(null != message ? message : "Must not be null"); - return obj; - } - - public RequestEntry.Add expectRequestAdd() { - return failIfNull((RequestEntry.Add) mRequestHistory.poll(TIMEOUT_MS, - it -> it instanceof RequestEntry.Add), "Expected request add"); - } - - public void expectRequestAdds(final int count) { - for (int i = count; i > 0; --i) { - expectRequestAdd(); - } - } - - public RequestEntry.Remove expectRequestRemove() { - return failIfNull((RequestEntry.Remove) mRequestHistory.poll(TIMEOUT_MS, - it -> it instanceof RequestEntry.Remove), "Expected request remove"); - } - - public void expectRequestRemoves(final int count) { - for (int i = count; i > 0; --i) { - expectRequestRemove(); - } - } - - // Used to collect the networks requests managed by this factory. This is a duplicate of - // the internal information stored in the NetworkFactory (which is private). - private SparseArray mNetworkRequests = new SparseArray<>(); - private final HandlerThread mHandlerSendingRequests; - - public MockNetworkFactory(Looper looper, Context context, String logTag, - NetworkCapabilities filter, HandlerThread threadSendingRequests) { - super(looper, context, logTag, filter); - mHandlerSendingRequests = threadSendingRequests; - } - - public int getMyRequestCount() { - return getRequestCount(); - } - - protected void startNetwork() { - mNetworkStarted.set(true); - } - - protected void stopNetwork() { - mNetworkStarted.set(false); - } - - public boolean getMyStartRequested() { - return mNetworkStarted.get(); - } - - - @Override - protected void needNetworkFor(NetworkRequest request) { - mNetworkRequests.put(request.requestId, request); - super.needNetworkFor(request); - mRequestHistory.add(new RequestEntry.Add(request)); - } - - @Override - protected void releaseNetworkFor(NetworkRequest request) { - mNetworkRequests.remove(request.requestId); - super.releaseNetworkFor(request); - mRequestHistory.add(new RequestEntry.Remove(request)); - } - - public void assertRequestCountEquals(final int count) { - assertEquals(count, getMyRequestCount()); - } - - @Override - public void terminate() { - super.terminate(); - // Make sure there are no remaining requests unaccounted for. - HandlerUtils.waitForIdle(mHandlerSendingRequests, TIMEOUT_MS); - assertNull(mRequestHistory.poll(0, r -> true)); - } - - // Trigger releasing the request as unfulfillable - public void triggerUnfulfillable(NetworkRequest r) { - super.releaseRequestAsUnfulfillableByAnyFactory(r); - } - - public void assertNoRequestChanged() { - assertNull(mRequestHistory.poll(0, r -> true)); - } - } - - private Set uidRangesForUids(int... uids) { - final ArraySet ranges = new ArraySet<>(); - for (final int uid : uids) { - ranges.add(new UidRange(uid, uid)); - } - return ranges; - } - - private static Looper startHandlerThreadAndReturnLooper() { - final HandlerThread handlerThread = new HandlerThread("MockVpnThread"); - handlerThread.start(); - return handlerThread.getLooper(); - } - - private class MockVpn extends Vpn implements TestableNetworkCallback.HasNetwork { - // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does - // not inherit from NetworkAgent. - private TestNetworkAgentWrapper mMockNetworkAgent; - private boolean mAgentRegistered = false; - - private int mVpnType = VpnManager.TYPE_VPN_SERVICE; - private UnderlyingNetworkInfo mUnderlyingNetworkInfo; - - // These ConditionVariables allow tests to wait for LegacyVpnRunner to be stopped/started. - // TODO: this scheme is ad-hoc and error-prone because it does not fail if, for example, the - // test expects two starts in a row, or even if the production code calls start twice in a - // row. find a better solution. Simply putting a method to create a LegacyVpnRunner into - // Vpn.Dependencies doesn't work because LegacyVpnRunner is not a static class and has - // extensive access into the internals of Vpn. - private ConditionVariable mStartLegacyVpnCv = new ConditionVariable(); - private ConditionVariable mStopVpnRunnerCv = new ConditionVariable(); - - public MockVpn(int userId) { - super(startHandlerThreadAndReturnLooper(), mServiceContext, - new Dependencies() { - @Override - public boolean isCallerSystem() { - return true; - } - - @Override - public DeviceIdleInternal getDeviceIdleInternal() { - return mDeviceIdleInternal; - } - }, - mNetworkManagementService, mMockNetd, userId, mVpnProfileStore); - } - - public void setUids(Set uids) { - mNetworkCapabilities.setUids(UidRange.toIntRanges(uids)); - if (mAgentRegistered) { - mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities, true); - } - } - - public void setVpnType(int vpnType) { - mVpnType = vpnType; - } - - @Override - public Network getNetwork() { - return (mMockNetworkAgent == null) ? null : mMockNetworkAgent.getNetwork(); - } - - @Override - public int getActiveVpnType() { - return mVpnType; - } - - private LinkProperties makeLinkProperties() { - final LinkProperties lp = new LinkProperties(); - lp.setInterfaceName(VPN_IFNAME); - return lp; - } - - private void registerAgent(boolean isAlwaysMetered, Set uids, LinkProperties lp) - throws Exception { - if (mAgentRegistered) throw new IllegalStateException("already registered"); - updateState(NetworkInfo.DetailedState.CONNECTING, "registerAgent"); - mConfig = new VpnConfig(); - mConfig.session = "MySession12345"; - setUids(uids); - if (!isAlwaysMetered) mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED); - mInterface = VPN_IFNAME; - mNetworkCapabilities.setTransportInfo(new VpnTransportInfo(getActiveVpnType(), - mConfig.session)); - mMockNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp, - mNetworkCapabilities); - mMockNetworkAgent.waitForIdle(TIMEOUT_MS); - - verify(mMockNetd, times(1)).networkAddUidRanges(eq(mMockVpn.getNetwork().getNetId()), - eq(toUidRangeStableParcels(uids))); - verify(mMockNetd, never()) - .networkRemoveUidRanges(eq(mMockVpn.getNetwork().getNetId()), any()); - mAgentRegistered = true; - verify(mMockNetd).networkCreate(nativeNetworkConfigVpn(getNetwork().netId, - !mMockNetworkAgent.isBypassableVpn(), mVpnType)); - updateState(NetworkInfo.DetailedState.CONNECTED, "registerAgent"); - mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities()); - mNetworkAgent = mMockNetworkAgent.getNetworkAgent(); - } - - private void registerAgent(Set uids) throws Exception { - registerAgent(false /* isAlwaysMetered */, uids, makeLinkProperties()); - } - - private void connect(boolean validated, boolean hasInternet, boolean isStrictMode) { - mMockNetworkAgent.connect(validated, hasInternet, isStrictMode); - } - - private void connect(boolean validated) { - mMockNetworkAgent.connect(validated); - } - - private TestNetworkAgentWrapper getAgent() { - return mMockNetworkAgent; - } - - public void establish(LinkProperties lp, int uid, Set ranges, boolean validated, - boolean hasInternet, boolean isStrictMode) throws Exception { - mNetworkCapabilities.setOwnerUid(uid); - mNetworkCapabilities.setAdministratorUids(new int[]{uid}); - registerAgent(false, ranges, lp); - connect(validated, hasInternet, isStrictMode); - waitForIdle(); - } - - public void establish(LinkProperties lp, int uid, Set ranges) throws Exception { - establish(lp, uid, ranges, true, true, false); - } - - public void establishForMyUid(LinkProperties lp) throws Exception { - final int uid = Process.myUid(); - establish(lp, uid, uidRangesForUids(uid), true, true, false); - } - - public void establishForMyUid(boolean validated, boolean hasInternet, boolean isStrictMode) - throws Exception { - final int uid = Process.myUid(); - establish(makeLinkProperties(), uid, uidRangesForUids(uid), validated, hasInternet, - isStrictMode); - } - - public void establishForMyUid() throws Exception { - establishForMyUid(makeLinkProperties()); - } - - public void sendLinkProperties(LinkProperties lp) { - mMockNetworkAgent.sendLinkProperties(lp); - } - - public void disconnect() { - if (mMockNetworkAgent != null) { - mMockNetworkAgent.disconnect(); - updateState(NetworkInfo.DetailedState.DISCONNECTED, "disconnect"); - } - mAgentRegistered = false; - setUids(null); - // Remove NET_CAPABILITY_INTERNET or MockNetworkAgent will refuse to connect later on. - mNetworkCapabilities.removeCapability(NET_CAPABILITY_INTERNET); - mInterface = null; - } - - @Override - public void startLegacyVpnRunner() { - mStartLegacyVpnCv.open(); - } - - public void expectStartLegacyVpnRunner() { - assertTrue("startLegacyVpnRunner not called after " + TIMEOUT_MS + " ms", - mStartLegacyVpnCv.block(TIMEOUT_MS)); - - // startLegacyVpn calls stopVpnRunnerPrivileged, which will open mStopVpnRunnerCv, just - // before calling startLegacyVpnRunner. Restore mStopVpnRunnerCv, so the test can expect - // that the VpnRunner is stopped and immediately restarted by calling - // expectStartLegacyVpnRunner() and expectStopVpnRunnerPrivileged() back-to-back. - mStopVpnRunnerCv = new ConditionVariable(); - } - - @Override - public void stopVpnRunnerPrivileged() { - if (mVpnRunner != null) { - super.stopVpnRunnerPrivileged(); - disconnect(); - mStartLegacyVpnCv = new ConditionVariable(); - } - mVpnRunner = null; - mStopVpnRunnerCv.open(); - } - - public void expectStopVpnRunnerPrivileged() { - assertTrue("stopVpnRunnerPrivileged not called after " + TIMEOUT_MS + " ms", - mStopVpnRunnerCv.block(TIMEOUT_MS)); - } - - @Override - public synchronized UnderlyingNetworkInfo getUnderlyingNetworkInfo() { - if (mUnderlyingNetworkInfo != null) return mUnderlyingNetworkInfo; - - return super.getUnderlyingNetworkInfo(); - } - - private synchronized void setUnderlyingNetworkInfo( - UnderlyingNetworkInfo underlyingNetworkInfo) { - mUnderlyingNetworkInfo = underlyingNetworkInfo; - } - } - - private UidRangeParcel[] toUidRangeStableParcels(final @NonNull Set ranges) { - return ranges.stream().map( - r -> new UidRangeParcel(r.start, r.stop)).toArray(UidRangeParcel[]::new); - } - - private VpnManagerService makeVpnManagerService() { - final VpnManagerService.Dependencies deps = new VpnManagerService.Dependencies() { - public int getCallingUid() { - return mDeps.getCallingUid(); - } - - public HandlerThread makeHandlerThread() { - return mVMSHandlerThread; - } - - @Override - public VpnProfileStore getVpnProfileStore() { - return mVpnProfileStore; - } - - public INetd getNetd() { - return mMockNetd; - } - - public INetworkManagementService getINetworkManagementService() { - return mNetworkManagementService; - } - }; - return new VpnManagerService(mServiceContext, deps); - } - - private void assertVpnTransportInfo(NetworkCapabilities nc, int type) { - assertNotNull(nc); - final TransportInfo ti = nc.getTransportInfo(); - assertTrue("VPN TransportInfo is not a VpnTransportInfo: " + ti, - ti instanceof VpnTransportInfo); - assertEquals(type, ((VpnTransportInfo) ti).getType()); - - } - - private void processBroadcast(Intent intent) { - mServiceContext.sendBroadcast(intent); - HandlerUtils.waitForIdle(mVMSHandlerThread, TIMEOUT_MS); - waitForIdle(); - } - - private void mockVpn(int uid) { - synchronized (mVpnManagerService.mVpns) { - int userId = UserHandle.getUserId(uid); - mMockVpn = new MockVpn(userId); - // Every running user always has a Vpn in the mVpns array, even if no VPN is running. - mVpnManagerService.mVpns.put(userId, mMockVpn); - } - } - - private void mockUidNetworkingBlocked() { - doAnswer(i -> isUidBlocked(mBlockedReasons, i.getArgument(1)) - ).when(mNetworkPolicyManager).isUidNetworkingBlocked(anyInt(), anyBoolean()); - } - - private boolean isUidBlocked(int blockedReasons, boolean meteredNetwork) { - final int blockedOnAllNetworksReason = (blockedReasons & ~BLOCKED_METERED_REASON_MASK); - if (blockedOnAllNetworksReason != BLOCKED_REASON_NONE) { - return true; - } - if (meteredNetwork) { - return blockedReasons != BLOCKED_REASON_NONE; - } - return false; - } - - private void setBlockedReasonChanged(int blockedReasons) { - mBlockedReasons = blockedReasons; - mPolicyCallback.onUidBlockedReasonChanged(Process.myUid(), blockedReasons); - } - - private Nat464Xlat getNat464Xlat(NetworkAgentWrapper mna) { - return mService.getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd; - } - - private static class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker { - volatile boolean mConfigRestrictsAvoidBadWifi; - volatile int mConfigMeteredMultipathPreference; - - WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) { - super(c, h, r); - } - - @Override - public boolean configRestrictsAvoidBadWifi() { - return mConfigRestrictsAvoidBadWifi; - } - - @Override - public int configMeteredMultipathPreference() { - return mConfigMeteredMultipathPreference; - } - } - - /** - * Wait up to TIMEOUT_MS for {@code conditionVariable} to open. - * Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens. - */ - static private void waitFor(ConditionVariable conditionVariable) { - if (conditionVariable.block(TIMEOUT_MS)) { - return; - } - fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms"); - } - - private T doAsUid(final int uid, @NonNull final Supplier what) { - when(mDeps.getCallingUid()).thenReturn(uid); - try { - return what.get(); - } finally { - returnRealCallingUid(); - } - } - - private void doAsUid(final int uid, @NonNull final Runnable what) { - doAsUid(uid, () -> { - what.run(); return Void.TYPE; - }); - } - - private void registerNetworkCallbackAsUid(NetworkRequest request, NetworkCallback callback, - int uid) { - doAsUid(uid, () -> { - mCm.registerNetworkCallback(request, callback); - }); - } - - private void registerDefaultNetworkCallbackAsUid(@NonNull final NetworkCallback callback, - final int uid) { - doAsUid(uid, () -> { - mCm.registerDefaultNetworkCallback(callback); - waitForIdle(); - }); - } - - private interface ExceptionalRunnable { - void run() throws Exception; - } - - private void withPermission(String permission, ExceptionalRunnable r) throws Exception { - if (mServiceContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) { - r.run(); - return; - } - try { - mServiceContext.setPermission(permission, PERMISSION_GRANTED); - r.run(); - } finally { - mServiceContext.setPermission(permission, PERMISSION_DENIED); - } - } - - private static final int PRIMARY_USER = 0; - private static final UidRange PRIMARY_UIDRANGE = - UidRange.createForUser(UserHandle.of(PRIMARY_USER)); - private static final int APP1_UID = UserHandle.getUid(PRIMARY_USER, 10100); - private static final int APP2_UID = UserHandle.getUid(PRIMARY_USER, 10101); - private static final int VPN_UID = UserHandle.getUid(PRIMARY_USER, 10043); - private static final UserInfo PRIMARY_USER_INFO = new UserInfo(PRIMARY_USER, "", - UserInfo.FLAG_PRIMARY); - private static final UserHandle PRIMARY_USER_HANDLE = new UserHandle(PRIMARY_USER); - - private static final int RESTRICTED_USER = 1; - private static final UserInfo RESTRICTED_USER_INFO = new UserInfo(RESTRICTED_USER, "", - UserInfo.FLAG_RESTRICTED); - static { - RESTRICTED_USER_INFO.restrictedProfileParentId = PRIMARY_USER; - } - - @Before - public void setUp() throws Exception { - mNetIdManager = new TestNetIdManager(); - - mContext = InstrumentationRegistry.getContext(); - - MockitoAnnotations.initMocks(this); - - when(mUserManager.getAliveUsers()).thenReturn(Arrays.asList(PRIMARY_USER_INFO)); - when(mUserManager.getUserHandles(anyBoolean())).thenReturn( - Arrays.asList(PRIMARY_USER_HANDLE)); - when(mUserManager.getUserInfo(PRIMARY_USER)).thenReturn(PRIMARY_USER_INFO); - // canHaveRestrictedProfile does not take a userId. It applies to the userId of the context - // it was started from, i.e., PRIMARY_USER. - when(mUserManager.canHaveRestrictedProfile()).thenReturn(true); - when(mUserManager.getUserInfo(RESTRICTED_USER)).thenReturn(RESTRICTED_USER_INFO); - - final ApplicationInfo applicationInfo = new ApplicationInfo(); - applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q; - when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any())) - .thenReturn(applicationInfo); - when(mPackageManager.getTargetSdkVersion(anyString())) - .thenReturn(applicationInfo.targetSdkVersion); - when(mSystemConfigManager.getSystemPermissionUids(anyString())).thenReturn(new int[0]); - - // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not. - // http://b/25897652 . - if (Looper.myLooper() == null) { - Looper.prepare(); - } - mockDefaultPackages(); - mockHasSystemFeature(FEATURE_WIFI, true); - mockHasSystemFeature(FEATURE_WIFI_DIRECT, true); - doReturn(true).when(mTelephonyManager).isDataCapable(); - - FakeSettingsProvider.clearSettingsProvider(); - mServiceContext = new MockContext(InstrumentationRegistry.getContext(), - new FakeSettingsProvider()); - mServiceContext.setUseRegisteredHandlers(true); - - mAlarmManagerThread = new HandlerThread("TestAlarmManager"); - mAlarmManagerThread.start(); - initAlarmManager(mAlarmManager, mAlarmManagerThread.getThreadHandler()); - - mCsHandlerThread = new HandlerThread("TestConnectivityService"); - mVMSHandlerThread = new HandlerThread("TestVpnManagerService"); - mDeps = makeDependencies(); - returnRealCallingUid(); - mService = new ConnectivityService(mServiceContext, - mMockDnsResolver, - mock(IpConnectivityLog.class), - mMockNetd, - mDeps); - mService.mLingerDelayMs = TEST_LINGER_DELAY_MS; - mService.mNascentDelayMs = TEST_NASCENT_DELAY_MS; - verify(mDeps).makeMultinetworkPolicyTracker(any(), any(), any()); - - final ArgumentCaptor policyCallbackCaptor = - ArgumentCaptor.forClass(NetworkPolicyCallback.class); - verify(mNetworkPolicyManager).registerNetworkPolicyCallback(any(), - policyCallbackCaptor.capture()); - mPolicyCallback = policyCallbackCaptor.getValue(); - - // Create local CM before sending system ready so that we can answer - // getSystemService() correctly. - mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService); - mService.systemReadyInternal(); - mVpnManagerService = makeVpnManagerService(); - mVpnManagerService.systemReady(); - mockVpn(Process.myUid()); - mCm.bindProcessToNetwork(null); - mQosCallbackTracker = mock(QosCallbackTracker.class); - - // Ensure that the default setting for Captive Portals is used for most tests - setCaptivePortalMode(ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_PROMPT); - setAlwaysOnNetworks(false); - setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com"); - } - - private void returnRealCallingUid() { - doAnswer((invocationOnMock) -> Binder.getCallingUid()).when(mDeps).getCallingUid(); - } - - private ConnectivityService.Dependencies makeDependencies() { - doReturn(false).when(mSystemProperties).getBoolean("ro.radio.noril", false); - final ConnectivityService.Dependencies deps = mock(ConnectivityService.Dependencies.class); - doReturn(mCsHandlerThread).when(deps).makeHandlerThread(); - doReturn(mNetIdManager).when(deps).makeNetIdManager(); - doReturn(mNetworkStack).when(deps).getNetworkStack(); - doReturn(mSystemProperties).when(deps).getSystemProperties(); - doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any()); - doReturn(true).when(deps).queryUserAccess(anyInt(), any(), any()); - doAnswer(inv -> { - mPolicyTracker = new WrappedMultinetworkPolicyTracker( - inv.getArgument(0), inv.getArgument(1), inv.getArgument(2)); - return mPolicyTracker; - }).when(deps).makeMultinetworkPolicyTracker(any(), any(), any()); - doReturn(true).when(deps).getCellular464XlatEnabled(); - - doReturn(60000).when(mResources).getInteger(R.integer.config_networkTransitionTimeout); - doReturn("").when(mResources).getString(R.string.config_networkCaptivePortalServerUrl); - doReturn(new String[]{ WIFI_WOL_IFNAME }).when(mResources).getStringArray( - R.array.config_wakeonlan_supported_interfaces); - doReturn(new String[] { "0,1", "1,3" }).when(mResources).getStringArray( - R.array.config_networkSupportedKeepaliveCount); - doReturn(new String[0]).when(mResources).getStringArray( - R.array.config_networkNotifySwitches); - doReturn(new int[]{10, 11, 12, 14, 15}).when(mResources).getIntArray( - R.array.config_protectedNetworks); - // We don't test the actual notification value strings, so just return an empty array. - // It doesn't matter what the values are as long as it's not null. - doReturn(new String[0]).when(mResources).getStringArray(R.array.network_switch_type_name); - - doReturn(R.array.config_networkSupportedKeepaliveCount).when(mResources) - .getIdentifier(eq("config_networkSupportedKeepaliveCount"), eq("array"), any()); - doReturn(R.array.network_switch_type_name).when(mResources) - .getIdentifier(eq("network_switch_type_name"), eq("array"), any()); - - - final ConnectivityResources connRes = mock(ConnectivityResources.class); - doReturn(mResources).when(connRes).get(); - doReturn(connRes).when(deps).getResources(any()); - - final Context mockResContext = mock(Context.class); - doReturn(mResources).when(mockResContext).getResources(); - ConnectivityResources.setResourcesContextForTest(mockResContext); - - return deps; - } - - private static void initAlarmManager(final AlarmManager am, final Handler alarmHandler) { - doAnswer(inv -> { - final long when = inv.getArgument(1); - final WakeupMessage wakeupMsg = inv.getArgument(3); - final Handler handler = inv.getArgument(4); - - long delayMs = when - SystemClock.elapsedRealtime(); - if (delayMs < 0) delayMs = 0; - if (delayMs > UNREASONABLY_LONG_ALARM_WAIT_MS) { - fail("Attempting to send msg more than " + UNREASONABLY_LONG_ALARM_WAIT_MS - + "ms into the future: " + delayMs); - } - alarmHandler.postDelayed(() -> handler.post(wakeupMsg::onAlarm), wakeupMsg /* token */, - delayMs); - - return null; - }).when(am).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), anyLong(), anyString(), - any(WakeupMessage.class), any()); - - doAnswer(inv -> { - final WakeupMessage wakeupMsg = inv.getArgument(0); - alarmHandler.removeCallbacksAndMessages(wakeupMsg /* token */); - return null; - }).when(am).cancel(any(WakeupMessage.class)); - } - - @After - public void tearDown() throws Exception { - unregisterDefaultNetworkCallbacks(); - maybeTearDownEnterpriseNetwork(); - setAlwaysOnNetworks(false); - if (mCellNetworkAgent != null) { - mCellNetworkAgent.disconnect(); - mCellNetworkAgent = null; - } - if (mWiFiNetworkAgent != null) { - mWiFiNetworkAgent.disconnect(); - mWiFiNetworkAgent = null; - } - if (mEthernetNetworkAgent != null) { - mEthernetNetworkAgent.disconnect(); - mEthernetNetworkAgent = null; - } - - if (mQosCallbackMockHelper != null) { - mQosCallbackMockHelper.tearDown(); - mQosCallbackMockHelper = null; - } - mMockVpn.disconnect(); - waitForIdle(); - - FakeSettingsProvider.clearSettingsProvider(); - ConnectivityResources.setResourcesContextForTest(null); - - mCsHandlerThread.quitSafely(); - mAlarmManagerThread.quitSafely(); - } - - private void mockDefaultPackages() throws Exception { - final String myPackageName = mContext.getPackageName(); - final PackageInfo myPackageInfo = mContext.getPackageManager().getPackageInfo( - myPackageName, PackageManager.GET_PERMISSIONS); - when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn( - new String[] {myPackageName}); - when(mPackageManager.getPackageInfoAsUser(eq(myPackageName), anyInt(), - eq(UserHandle.getCallingUserId()))).thenReturn(myPackageInfo); - - when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn( - Arrays.asList(new PackageInfo[] { - buildPackageInfo(/* SYSTEM */ false, APP1_UID), - buildPackageInfo(/* SYSTEM */ false, APP2_UID), - buildPackageInfo(/* SYSTEM */ false, VPN_UID) - })); - - // Create a fake always-on VPN package. - final int userId = UserHandle.getCallingUserId(); - final ApplicationInfo applicationInfo = new ApplicationInfo(); - applicationInfo.targetSdkVersion = Build.VERSION_CODES.R; // Always-on supported in N+. - when(mPackageManager.getApplicationInfoAsUser(eq(ALWAYS_ON_PACKAGE), anyInt(), - eq(userId))).thenReturn(applicationInfo); - - // Minimal mocking to keep Vpn#isAlwaysOnPackageSupported happy. - ResolveInfo rInfo = new ResolveInfo(); - rInfo.serviceInfo = new ServiceInfo(); - rInfo.serviceInfo.metaData = new Bundle(); - final List services = Arrays.asList(new ResolveInfo[]{rInfo}); - when(mPackageManager.queryIntentServicesAsUser(any(), eq(PackageManager.GET_META_DATA), - eq(userId))).thenReturn(services); - when(mPackageManager.getPackageUidAsUser(TEST_PACKAGE_NAME, userId)) - .thenReturn(Process.myUid()); - when(mPackageManager.getPackageUidAsUser(ALWAYS_ON_PACKAGE, userId)) - .thenReturn(VPN_UID); - } - - private void verifyActiveNetwork(int transport) { - // Test getActiveNetworkInfo() - assertNotNull(mCm.getActiveNetworkInfo()); - assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType()); - // Test getActiveNetwork() - assertNotNull(mCm.getActiveNetwork()); - assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid())); - if (!NetworkCapabilities.isValidTransport(transport)) { - throw new IllegalStateException("Unknown transport " + transport); - } - switch (transport) { - case TRANSPORT_WIFI: - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - break; - case TRANSPORT_CELLULAR: - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - break; - case TRANSPORT_ETHERNET: - assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - break; - default: - break; - } - // Test getNetworkInfo(Network) - assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork())); - assertEquals(transportToLegacyType(transport), - mCm.getNetworkInfo(mCm.getActiveNetwork()).getType()); - assertNotNull(mCm.getActiveNetworkInfoForUid(Process.myUid())); - // Test getNetworkCapabilities(Network) - assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork())); - assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport)); - } - - private void verifyNoNetwork() { - waitForIdle(); - // Test getActiveNetworkInfo() - assertNull(mCm.getActiveNetworkInfo()); - // Test getActiveNetwork() - assertNull(mCm.getActiveNetwork()); - assertNull(mCm.getActiveNetworkForUid(Process.myUid())); - // Test getAllNetworks() - assertEmpty(mCm.getAllNetworks()); - assertEmpty(mCm.getAllNetworkStateSnapshots()); - } - - /** - * Class to simplify expecting broadcasts using BroadcastInterceptingContext. - * Ensures that the receiver is unregistered after the expected broadcast is received. This - * cannot be done in the BroadcastReceiver itself because BroadcastInterceptingContext runs - * the receivers' receive method while iterating over the list of receivers, and unregistering - * the receiver during iteration throws ConcurrentModificationException. - */ - private class ExpectedBroadcast extends CompletableFuture { - private final BroadcastReceiver mReceiver; - - ExpectedBroadcast(BroadcastReceiver receiver) { - mReceiver = receiver; - } - - public Intent expectBroadcast(int timeoutMs) throws Exception { - try { - return get(timeoutMs, TimeUnit.MILLISECONDS); - } catch (TimeoutException e) { - fail("Expected broadcast not received after " + timeoutMs + " ms"); - return null; - } finally { - mServiceContext.unregisterReceiver(mReceiver); - } - } - - public Intent expectBroadcast() throws Exception { - return expectBroadcast(BROADCAST_TIMEOUT_MS); - } - - public void expectNoBroadcast(int timeoutMs) throws Exception { - waitForIdle(); - try { - final Intent intent = get(timeoutMs, TimeUnit.MILLISECONDS); - fail("Unexpected broadcast: " + intent.getAction() + " " + intent.getExtras()); - } catch (TimeoutException expected) { - } finally { - mServiceContext.unregisterReceiver(mReceiver); - } - } - } - - /** Expects that {@code count} CONNECTIVITY_ACTION broadcasts are received. */ - private ExpectedBroadcast registerConnectivityBroadcast(final int count) { - return registerConnectivityBroadcastThat(count, intent -> true); - } - - private ExpectedBroadcast registerConnectivityBroadcastThat(final int count, - @NonNull final Predicate filter) { - final IntentFilter intentFilter = new IntentFilter(CONNECTIVITY_ACTION); - // AtomicReference allows receiver to access expected even though it is constructed later. - final AtomicReference expectedRef = new AtomicReference<>(); - final BroadcastReceiver receiver = new BroadcastReceiver() { - private int mRemaining = count; - public void onReceive(Context context, Intent intent) { - final int type = intent.getIntExtra(EXTRA_NETWORK_TYPE, -1); - final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO); - Log.d(TAG, "Received CONNECTIVITY_ACTION type=" + type + " ni=" + ni); - if (!filter.test(intent)) return; - if (--mRemaining == 0) { - expectedRef.get().complete(intent); - } - } - }; - final ExpectedBroadcast expected = new ExpectedBroadcast(receiver); - expectedRef.set(expected); - mServiceContext.registerReceiver(receiver, intentFilter); - return expected; - } - - private boolean extraInfoInBroadcastHasExpectedNullness(NetworkInfo ni) { - final DetailedState state = ni.getDetailedState(); - if (state == DetailedState.CONNECTED && ni.getExtraInfo() == null) return false; - // Expect a null extraInfo if the network is CONNECTING, because a CONNECTIVITY_ACTION - // broadcast with a state of CONNECTING only happens due to legacy VPN lockdown, which also - // nulls out extraInfo. - if (state == DetailedState.CONNECTING && ni.getExtraInfo() != null) return false; - // Can't make any assertions about DISCONNECTED broadcasts. When a network actually - // disconnects, disconnectAndDestroyNetwork sets its state to DISCONNECTED and its extraInfo - // to null. But if the DISCONNECTED broadcast is just simulated by LegacyTypeTracker due to - // a network switch, extraInfo will likely be populated. - // This is likely a bug in CS, but likely not one we can fix without impacting apps. - return true; - } - - private ExpectedBroadcast expectConnectivityAction(int type, NetworkInfo.DetailedState state) { - return registerConnectivityBroadcastThat(1, intent -> { - final int actualType = intent.getIntExtra(EXTRA_NETWORK_TYPE, -1); - final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO); - return type == actualType - && state == ni.getDetailedState() - && extraInfoInBroadcastHasExpectedNullness(ni); - }); - } - - @Test - public void testNetworkTypes() { - // Ensure that our mocks for the networkAttributes config variable work as expected. If they - // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types - // will fail. Failing here is much easier to debug. - assertTrue(mCm.isNetworkSupported(TYPE_WIFI)); - assertTrue(mCm.isNetworkSupported(TYPE_MOBILE)); - assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS)); - assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_FOTA)); - assertFalse(mCm.isNetworkSupported(TYPE_PROXY)); - - // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our - // mocks, this assert exercises the ConnectivityService code path that ensures that - // TYPE_ETHERNET is supported if the ethernet service is running. - assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET)); - } - - @Test - public void testNetworkFeature() throws Exception { - // Connect the cell agent and wait for the connected broadcast. - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.addCapability(NET_CAPABILITY_SUPL); - ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED); - mCellNetworkAgent.connect(true); - b.expectBroadcast(); - - // Build legacy request for SUPL. - final NetworkCapabilities legacyCaps = new NetworkCapabilities(); - legacyCaps.addTransportType(TRANSPORT_CELLULAR); - legacyCaps.addCapability(NET_CAPABILITY_SUPL); - final NetworkRequest legacyRequest = new NetworkRequest(legacyCaps, TYPE_MOBILE_SUPL, - ConnectivityManager.REQUEST_ID_UNSET, NetworkRequest.Type.REQUEST); - - // File request, withdraw it and make sure no broadcast is sent - b = registerConnectivityBroadcast(1); - final TestNetworkCallback callback = new TestNetworkCallback(); - mCm.requestNetwork(legacyRequest, callback); - callback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent); - mCm.unregisterNetworkCallback(callback); - b.expectNoBroadcast(800); // 800ms long enough to at least flake if this is sent - - // Disconnect the network and expect mobile disconnected broadcast. - b = expectConnectivityAction(TYPE_MOBILE, DetailedState.DISCONNECTED); - mCellNetworkAgent.disconnect(); - b.expectBroadcast(); - } - - @Test - public void testLingering() throws Exception { - verifyNoNetwork(); - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - assertNull(mCm.getActiveNetworkInfo()); - assertNull(mCm.getActiveNetwork()); - // Test bringing up validated cellular. - ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED); - mCellNetworkAgent.connect(true); - b.expectBroadcast(); - verifyActiveNetwork(TRANSPORT_CELLULAR); - assertLength(2, mCm.getAllNetworks()); - assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) || - mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork())); - assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) || - mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork())); - // Test bringing up validated WiFi. - b = registerConnectivityBroadcast(2); - mWiFiNetworkAgent.connect(true); - b.expectBroadcast(); - verifyActiveNetwork(TRANSPORT_WIFI); - assertLength(2, mCm.getAllNetworks()); - assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) || - mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork())); - assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) || - mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork())); - // Test cellular linger timeout. - mCellNetworkAgent.expectDisconnected(); - waitForIdle(); - assertLength(1, mCm.getAllNetworks()); - verifyActiveNetwork(TRANSPORT_WIFI); - assertLength(1, mCm.getAllNetworks()); - assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork()); - // Test WiFi disconnect. - b = registerConnectivityBroadcast(1); - mWiFiNetworkAgent.disconnect(); - b.expectBroadcast(); - verifyNoNetwork(); - } - - /** - * Verify a newly created network will be inactive instead of torn down even if no one is - * requesting. - */ - @Test - public void testNewNetworkInactive() throws Exception { - // Create a callback that monitoring the testing network. - final TestNetworkCallback listenCallback = new TestNetworkCallback(); - mCm.registerNetworkCallback(new NetworkRequest.Builder().build(), listenCallback); - - // 1. Create a network that is not requested by anyone, and does not satisfy any of the - // default requests. Verify that the network will be inactive instead of torn down. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connectWithoutInternet(); - listenCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - listenCallback.assertNoCallback(); - - // Verify that the network will be torn down after nascent expiry. A small period of time - // is added in case of flakiness. - final int nascentTimeoutMs = - mService.mNascentDelayMs + mService.mNascentDelayMs / 4; - listenCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent, nascentTimeoutMs); - - // 2. Create a network that is satisfied by a request comes later. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connectWithoutInternet(); - listenCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - final NetworkRequest wifiRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_WIFI).build(); - final TestNetworkCallback wifiCallback = new TestNetworkCallback(); - mCm.requestNetwork(wifiRequest, wifiCallback); - wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - - // Verify that the network will be kept since the request is still satisfied. And is able - // to get disconnected as usual if the request is released after the nascent timer expires. - listenCallback.assertNoCallback(nascentTimeoutMs); - mCm.unregisterNetworkCallback(wifiCallback); - listenCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - - // 3. Create a network that is satisfied by a request comes later. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connectWithoutInternet(); - listenCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - mCm.requestNetwork(wifiRequest, wifiCallback); - wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - - // Verify that the network will still be torn down after the request gets removed. - mCm.unregisterNetworkCallback(wifiCallback); - listenCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - - // There is no need to ensure that LOSING is never sent in the common case that the - // network immediately satisfies a request that was already present, because it is already - // verified anywhere whenever {@code TestNetworkCallback#expectAvailable*} is called. - - mCm.unregisterNetworkCallback(listenCallback); - } - - /** - * Verify a newly created network will be inactive and switch to background if only background - * request is satisfied. - */ - @Test - public void testNewNetworkInactive_bgNetwork() throws Exception { - // Create a callback that monitoring the wifi network. - final TestNetworkCallback wifiListenCallback = new TestNetworkCallback(); - mCm.registerNetworkCallback(new NetworkRequest.Builder() - .addTransportType(TRANSPORT_WIFI).build(), wifiListenCallback); - - // Create callbacks that can monitor background and foreground mobile networks. - // This is done by granting using background networks permission before registration. Thus, - // the service will not add {@code NET_CAPABILITY_FOREGROUND} by default. - grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid()); - final TestNetworkCallback bgMobileListenCallback = new TestNetworkCallback(); - final TestNetworkCallback fgMobileListenCallback = new TestNetworkCallback(); - mCm.registerNetworkCallback(new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR).build(), bgMobileListenCallback); - mCm.registerNetworkCallback(new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR) - .addCapability(NET_CAPABILITY_FOREGROUND).build(), fgMobileListenCallback); - - // Connect wifi, which satisfies default request. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true); - wifiListenCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent); - - // Connect a cellular network, verify that satisfies only the background callback. - setAlwaysOnNetworks(true); - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - bgMobileListenCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - fgMobileListenCallback.assertNoCallback(); - assertFalse(isForegroundNetwork(mCellNetworkAgent)); - - mCellNetworkAgent.disconnect(); - bgMobileListenCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - fgMobileListenCallback.assertNoCallback(); - - mCm.unregisterNetworkCallback(wifiListenCallback); - mCm.unregisterNetworkCallback(bgMobileListenCallback); - mCm.unregisterNetworkCallback(fgMobileListenCallback); - } - - @Test - public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception { - // Test bringing up unvalidated WiFi - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - ExpectedBroadcast b = registerConnectivityBroadcast(1); - mWiFiNetworkAgent.connect(false); - b.expectBroadcast(); - verifyActiveNetwork(TRANSPORT_WIFI); - // Test bringing up unvalidated cellular - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(false); - waitForIdle(); - verifyActiveNetwork(TRANSPORT_WIFI); - // Test cellular disconnect. - mCellNetworkAgent.disconnect(); - waitForIdle(); - verifyActiveNetwork(TRANSPORT_WIFI); - // Test bringing up validated cellular - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - b = registerConnectivityBroadcast(2); - mCellNetworkAgent.connect(true); - b.expectBroadcast(); - verifyActiveNetwork(TRANSPORT_CELLULAR); - // Test cellular disconnect. - b = registerConnectivityBroadcast(2); - mCellNetworkAgent.disconnect(); - b.expectBroadcast(); - verifyActiveNetwork(TRANSPORT_WIFI); - // Test WiFi disconnect. - b = registerConnectivityBroadcast(1); - mWiFiNetworkAgent.disconnect(); - b.expectBroadcast(); - verifyNoNetwork(); - } - - @Test - public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception { - // Test bringing up unvalidated cellular. - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - ExpectedBroadcast b = registerConnectivityBroadcast(1); - mCellNetworkAgent.connect(false); - b.expectBroadcast(); - verifyActiveNetwork(TRANSPORT_CELLULAR); - // Test bringing up unvalidated WiFi. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - b = registerConnectivityBroadcast(2); - mWiFiNetworkAgent.connect(false); - b.expectBroadcast(); - verifyActiveNetwork(TRANSPORT_WIFI); - // Test WiFi disconnect. - b = registerConnectivityBroadcast(2); - mWiFiNetworkAgent.disconnect(); - b.expectBroadcast(); - verifyActiveNetwork(TRANSPORT_CELLULAR); - // Test cellular disconnect. - b = registerConnectivityBroadcast(1); - mCellNetworkAgent.disconnect(); - b.expectBroadcast(); - verifyNoNetwork(); - } - - @Test - public void testUnlingeringDoesNotValidate() throws Exception { - // Test bringing up unvalidated WiFi. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - ExpectedBroadcast b = registerConnectivityBroadcast(1); - mWiFiNetworkAgent.connect(false); - b.expectBroadcast(); - verifyActiveNetwork(TRANSPORT_WIFI); - assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( - NET_CAPABILITY_VALIDATED)); - // Test bringing up validated cellular. - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - b = registerConnectivityBroadcast(2); - mCellNetworkAgent.connect(true); - b.expectBroadcast(); - verifyActiveNetwork(TRANSPORT_CELLULAR); - assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( - NET_CAPABILITY_VALIDATED)); - // Test cellular disconnect. - b = registerConnectivityBroadcast(2); - mCellNetworkAgent.disconnect(); - b.expectBroadcast(); - verifyActiveNetwork(TRANSPORT_WIFI); - // Unlingering a network should not cause it to be marked as validated. - assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( - NET_CAPABILITY_VALIDATED)); - } - - @Test - public void testCellularOutscoresWeakWifi() throws Exception { - // Test bringing up validated cellular. - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - ExpectedBroadcast b = registerConnectivityBroadcast(1); - mCellNetworkAgent.connect(true); - b.expectBroadcast(); - verifyActiveNetwork(TRANSPORT_CELLULAR); - // Test bringing up validated WiFi. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - b = registerConnectivityBroadcast(2); - mWiFiNetworkAgent.connect(true); - b.expectBroadcast(); - verifyActiveNetwork(TRANSPORT_WIFI); - // Test WiFi getting really weak. - b = registerConnectivityBroadcast(2); - mWiFiNetworkAgent.adjustScore(-11); - b.expectBroadcast(); - verifyActiveNetwork(TRANSPORT_CELLULAR); - // Test WiFi restoring signal strength. - b = registerConnectivityBroadcast(2); - mWiFiNetworkAgent.adjustScore(11); - b.expectBroadcast(); - verifyActiveNetwork(TRANSPORT_WIFI); - } - - @Test - public void testReapingNetwork() throws Exception { - // Test bringing up WiFi without NET_CAPABILITY_INTERNET. - // Expect it to be torn down immediately because it satisfies no requests. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connectWithoutInternet(); - mWiFiNetworkAgent.expectDisconnected(); - // Test bringing up cellular without NET_CAPABILITY_INTERNET. - // Expect it to be torn down immediately because it satisfies no requests. - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mCellNetworkAgent.connectWithoutInternet(); - mCellNetworkAgent.expectDisconnected(); - // Test bringing up validated WiFi. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - final ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED); - mWiFiNetworkAgent.connect(true); - b.expectBroadcast(); - verifyActiveNetwork(TRANSPORT_WIFI); - // Test bringing up unvalidated cellular. - // Expect it to be torn down because it could never be the highest scoring network - // satisfying the default request even if it validated. - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(false); - mCellNetworkAgent.expectDisconnected(); - verifyActiveNetwork(TRANSPORT_WIFI); - mWiFiNetworkAgent.disconnect(); - mWiFiNetworkAgent.expectDisconnected(); - } - - @Test - public void testCellularFallback() throws Exception { - // Test bringing up validated cellular. - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - ExpectedBroadcast b = registerConnectivityBroadcast(1); - mCellNetworkAgent.connect(true); - b.expectBroadcast(); - verifyActiveNetwork(TRANSPORT_CELLULAR); - // Test bringing up validated WiFi. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - b = registerConnectivityBroadcast(2); - mWiFiNetworkAgent.connect(true); - b.expectBroadcast(); - verifyActiveNetwork(TRANSPORT_WIFI); - // Reevaluate WiFi (it'll instantly fail DNS). - b = registerConnectivityBroadcast(2); - assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( - NET_CAPABILITY_VALIDATED)); - mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork()); - // Should quickly fall back to Cellular. - b.expectBroadcast(); - assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( - NET_CAPABILITY_VALIDATED)); - verifyActiveNetwork(TRANSPORT_CELLULAR); - // Reevaluate cellular (it'll instantly fail DNS). - b = registerConnectivityBroadcast(2); - assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( - NET_CAPABILITY_VALIDATED)); - mCm.reportBadNetwork(mCellNetworkAgent.getNetwork()); - // Should quickly fall back to WiFi. - b.expectBroadcast(); - assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( - NET_CAPABILITY_VALIDATED)); - assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( - NET_CAPABILITY_VALIDATED)); - verifyActiveNetwork(TRANSPORT_WIFI); - } - - @Test - public void testWiFiFallback() throws Exception { - // Test bringing up unvalidated WiFi. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - ExpectedBroadcast b = registerConnectivityBroadcast(1); - mWiFiNetworkAgent.connect(false); - b.expectBroadcast(); - verifyActiveNetwork(TRANSPORT_WIFI); - // Test bringing up validated cellular. - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - b = registerConnectivityBroadcast(2); - mCellNetworkAgent.connect(true); - b.expectBroadcast(); - verifyActiveNetwork(TRANSPORT_CELLULAR); - // Reevaluate cellular (it'll instantly fail DNS). - b = registerConnectivityBroadcast(2); - assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( - NET_CAPABILITY_VALIDATED)); - mCm.reportBadNetwork(mCellNetworkAgent.getNetwork()); - // Should quickly fall back to WiFi. - b.expectBroadcast(); - assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( - NET_CAPABILITY_VALIDATED)); - verifyActiveNetwork(TRANSPORT_WIFI); - } - - @Test - public void testRequiresValidation() { - assertTrue(NetworkMonitorUtils.isValidationRequired( - mCm.getDefaultRequest().networkCapabilities)); - } - - /** - * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks - * this class receives, by calling expectCallback() exactly once each time a callback is - * received. assertNoCallback may be called at any time. - */ - private class TestNetworkCallback extends TestableNetworkCallback { - TestNetworkCallback() { - super(TEST_CALLBACK_TIMEOUT_MS); - } - - @Override - public void assertNoCallback() { - // TODO: better support this use case in TestableNetworkCallback - waitForIdle(); - assertNoCallback(0 /* timeout */); - } - - @Override - public T expectCallback(final KClass type, final HasNetwork n, - final long timeoutMs) { - final T callback = super.expectCallback(type, n, timeoutMs); - if (callback instanceof CallbackEntry.Losing) { - // TODO : move this to the specific test(s) needing this rather than here. - final CallbackEntry.Losing losing = (CallbackEntry.Losing) callback; - final int maxMsToLive = losing.getMaxMsToLive(); - String msg = String.format( - "Invalid linger time value %d, must be between %d and %d", - maxMsToLive, 0, mService.mLingerDelayMs); - assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= mService.mLingerDelayMs); - } - return callback; - } - } - - // Can't be part of TestNetworkCallback because "cannot be declared static; static methods can - // only be declared in a static or top level type". - static void assertNoCallbacks(TestNetworkCallback ... callbacks) { - for (TestNetworkCallback c : callbacks) { - c.assertNoCallback(); - } - } - - static void expectOnLost(TestNetworkAgentWrapper network, TestNetworkCallback ... callbacks) { - for (TestNetworkCallback c : callbacks) { - c.expectCallback(CallbackEntry.LOST, network); - } - } - - static void expectAvailableCallbacksUnvalidatedWithSpecifier(TestNetworkAgentWrapper network, - NetworkSpecifier specifier, TestNetworkCallback ... callbacks) { - for (TestNetworkCallback c : callbacks) { - c.expectCallback(CallbackEntry.AVAILABLE, network); - c.expectCapabilitiesThat(network, (nc) -> - !nc.hasCapability(NET_CAPABILITY_VALIDATED) - && Objects.equals(specifier, nc.getNetworkSpecifier())); - c.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, network); - c.expectCallback(CallbackEntry.BLOCKED_STATUS, network); - } - } - - @Test - public void testStateChangeNetworkCallbacks() throws Exception { - final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback(); - final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback(); - final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); - final NetworkRequest genericRequest = new NetworkRequest.Builder() - .clearCapabilities().build(); - final NetworkRequest wifiRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_WIFI).build(); - final NetworkRequest cellRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR).build(); - mCm.registerNetworkCallback(genericRequest, genericNetworkCallback); - mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback); - mCm.registerNetworkCallback(cellRequest, cellNetworkCallback); - - // Test unvalidated networks - ExpectedBroadcast b = registerConnectivityBroadcast(1); - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(false); - genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); - cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - b.expectBroadcast(); - assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); - - // This should not trigger spurious onAvailable() callbacks, b/21762680. - mCellNetworkAgent.adjustScore(-1); - waitForIdle(); - assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - - b = registerConnectivityBroadcast(2); - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); - genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - b.expectBroadcast(); - assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); - - b = registerConnectivityBroadcast(2); - mWiFiNetworkAgent.disconnect(); - genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - cellNetworkCallback.assertNoCallback(); - b.expectBroadcast(); - assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); - - b = registerConnectivityBroadcast(1); - mCellNetworkAgent.disconnect(); - genericNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - b.expectBroadcast(); - assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); - - // Test validated networks - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); - - // This should not trigger spurious onAvailable() callbacks, b/21762680. - mCellNetworkAgent.adjustScore(-1); - waitForIdle(); - assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true); - genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - genericNetworkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); - genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); - wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent); - cellNetworkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); - - mWiFiNetworkAgent.disconnect(); - genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); - - mCellNetworkAgent.disconnect(); - genericNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback); - } - - private void doNetworkCallbacksSanitizationTest(boolean sanitized) throws Exception { - final TestNetworkCallback callback = new TestNetworkCallback(); - final TestNetworkCallback defaultCallback = new TestNetworkCallback(); - final NetworkRequest wifiRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_WIFI).build(); - mCm.registerNetworkCallback(wifiRequest, callback); - mCm.registerDefaultNetworkCallback(defaultCallback); - - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); - callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - - final LinkProperties newLp = new LinkProperties(); - final Uri capportUrl = Uri.parse("https://capport.example.com/api"); - final CaptivePortalData capportData = new CaptivePortalData.Builder() - .setCaptive(true).build(); - - final Uri expectedCapportUrl = sanitized ? null : capportUrl; - newLp.setCaptivePortalApiUrl(capportUrl); - mWiFiNetworkAgent.sendLinkProperties(newLp); - callback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp -> - Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl())); - defaultCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp -> - Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl())); - - final CaptivePortalData expectedCapportData = sanitized ? null : capportData; - mWiFiNetworkAgent.notifyCapportApiDataChanged(capportData); - callback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp -> - Objects.equals(expectedCapportData, lp.getCaptivePortalData())); - defaultCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp -> - Objects.equals(expectedCapportData, lp.getCaptivePortalData())); - - final LinkProperties lp = mCm.getLinkProperties(mWiFiNetworkAgent.getNetwork()); - assertEquals(expectedCapportUrl, lp.getCaptivePortalApiUrl()); - assertEquals(expectedCapportData, lp.getCaptivePortalData()); - } - - @Test - public void networkCallbacksSanitizationTest_Sanitize() throws Exception { - mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, - PERMISSION_DENIED); - mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED); - doNetworkCallbacksSanitizationTest(true /* sanitized */); - } - - @Test - public void networkCallbacksSanitizationTest_NoSanitize_NetworkStack() throws Exception { - mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, - PERMISSION_GRANTED); - mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED); - doNetworkCallbacksSanitizationTest(false /* sanitized */); - } - - @Test - public void networkCallbacksSanitizationTest_NoSanitize_Settings() throws Exception { - mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, - PERMISSION_DENIED); - mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED); - doNetworkCallbacksSanitizationTest(false /* sanitized */); - } - - @Test - public void testOwnerUidCannotChange() throws Exception { - final NetworkCapabilities ncTemplate = new NetworkCapabilities(); - final int originalOwnerUid = Process.myUid(); - ncTemplate.setOwnerUid(originalOwnerUid); - - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(), - ncTemplate); - mWiFiNetworkAgent.connect(false); - waitForIdle(); - - // Send ConnectivityService an update to the mWiFiNetworkAgent's capabilities that changes - // the owner UID and an unrelated capability. - NetworkCapabilities agentCapabilities = mWiFiNetworkAgent.getNetworkCapabilities(); - assertEquals(originalOwnerUid, agentCapabilities.getOwnerUid()); - agentCapabilities.setOwnerUid(42); - assertFalse(agentCapabilities.hasCapability(NET_CAPABILITY_NOT_CONGESTED)); - agentCapabilities.addCapability(NET_CAPABILITY_NOT_CONGESTED); - mWiFiNetworkAgent.setNetworkCapabilities(agentCapabilities, true); - waitForIdle(); - - // Owner UIDs are not visible without location permission. - setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, - Manifest.permission.ACCESS_FINE_LOCATION); - - // Check that the capability change has been applied but the owner UID is not modified. - NetworkCapabilities nc = mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()); - assertEquals(originalOwnerUid, nc.getOwnerUid()); - assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_CONGESTED)); - } - - @Test - public void testMultipleLingering() throws Exception { - // This test would be flaky with the default 120ms timer: that is short enough that - // lingered networks are torn down before assertions can be run. We don't want to mock the - // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful - // in detecting races. - mService.mLingerDelayMs = 300; - - NetworkRequest request = new NetworkRequest.Builder() - .clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED) - .build(); - TestNetworkCallback callback = new TestNetworkCallback(); - mCm.registerNetworkCallback(request, callback); - - TestNetworkCallback defaultCallback = new TestNetworkCallback(); - mCm.registerDefaultNetworkCallback(defaultCallback); - - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET); - - mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); - mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); - mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); - - mCellNetworkAgent.connect(true); - callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - - mWiFiNetworkAgent.connect(true); - // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request. - // We then get LOSING when wifi validates and cell is outscored. - callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - // TODO: Investigate sending validated before losing. - callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); - callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); - defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - - mEthernetNetworkAgent.connect(true); - callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent); - // TODO: Investigate sending validated before losing. - callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent); - callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent); - defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent); - assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - - mEthernetNetworkAgent.disconnect(); - callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent); - defaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent); - defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent); - assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - - for (int i = 0; i < 4; i++) { - TestNetworkAgentWrapper oldNetwork, newNetwork; - if (i % 2 == 0) { - mWiFiNetworkAgent.adjustScore(-15); - oldNetwork = mWiFiNetworkAgent; - newNetwork = mCellNetworkAgent; - } else { - mWiFiNetworkAgent.adjustScore(15); - oldNetwork = mCellNetworkAgent; - newNetwork = mWiFiNetworkAgent; - - } - callback.expectCallback(CallbackEntry.LOSING, oldNetwork); - // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no - // longer lingering? - defaultCallback.expectAvailableCallbacksValidated(newNetwork); - assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork()); - } - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - - // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even - // if the network is still up. - mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED); - // We expect a notification about the capabilities change, and nothing else. - defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent); - defaultCallback.assertNoCallback(); - callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - - // Wifi no longer satisfies our listen, which is for an unmetered network. - // But because its score is 55, it's still up (and the default network). - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - - // Disconnect our test networks. - mWiFiNetworkAgent.disconnect(); - defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); - assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - mCellNetworkAgent.disconnect(); - defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - waitForIdle(); - assertEquals(null, mCm.getActiveNetwork()); - - mCm.unregisterNetworkCallback(callback); - waitForIdle(); - - // Check that a network is only lingered or torn down if it would not satisfy a request even - // if it validated. - request = new NetworkRequest.Builder().clearCapabilities().build(); - callback = new TestNetworkCallback(); - - mCm.registerNetworkCallback(request, callback); - - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(false); // Score: 10 - callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); - defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - - // Bring up wifi with a score of 20. - // Cell stays up because it would satisfy the default request if it validated. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); // Score: 20 - callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - - mWiFiNetworkAgent.disconnect(); - callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - - // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but - // it's arguably correct to linger it, since it was the default network before it validated. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true); - callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - // TODO: Investigate sending validated before losing. - callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); - callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); - defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - - mWiFiNetworkAgent.disconnect(); - callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); - mCellNetworkAgent.disconnect(); - callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - waitForIdle(); - assertEquals(null, mCm.getActiveNetwork()); - - // If a network is lingering, and we add and remove a request from it, resume lingering. - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true); - defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); - callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - // TODO: Investigate sending validated before losing. - callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); - callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); - assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - - NetworkRequest cellRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR).build(); - NetworkCallback noopCallback = new NetworkCallback(); - mCm.requestNetwork(cellRequest, noopCallback); - // TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer - // lingering? - mCm.unregisterNetworkCallback(noopCallback); - callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); - - // Similar to the above: lingering can start even after the lingered request is removed. - // Disconnect wifi and switch to cell. - mWiFiNetworkAgent.disconnect(); - callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); - assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - - // Cell is now the default network. Pin it with a cell-specific request. - noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525 - mCm.requestNetwork(cellRequest, noopCallback); - - // Now connect wifi, and expect it to become the default network. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true); - callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent); - defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); - assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - // The default request is lingering on cell, but nothing happens to cell, and we send no - // callbacks for it, because it's kept up by cellRequest. - callback.assertNoCallback(); - // Now unregister cellRequest and expect cell to start lingering. - mCm.unregisterNetworkCallback(noopCallback); - callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); - - // Let linger run its course. - callback.assertNoCallback(); - final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4; - callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, lingerTimeoutMs); - - // Register a TRACK_DEFAULT request and check that it does not affect lingering. - TestNetworkCallback trackDefaultCallback = new TestNetworkCallback(); - mCm.registerDefaultNetworkCallback(trackDefaultCallback); - trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent); - mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET); - mEthernetNetworkAgent.connect(true); - callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent); - callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent); - callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent); - trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent); - defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent); - assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - - // Let linger run its course. - callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent, lingerTimeoutMs); - - // Clean up. - mEthernetNetworkAgent.disconnect(); - callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent); - defaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent); - trackDefaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent); - - mCm.unregisterNetworkCallback(callback); - mCm.unregisterNetworkCallback(defaultCallback); - mCm.unregisterNetworkCallback(trackDefaultCallback); - } - - private void grantUsingBackgroundNetworksPermissionForUid(final int uid) throws Exception { - grantUsingBackgroundNetworksPermissionForUid(uid, mContext.getPackageName()); - } - - private void grantUsingBackgroundNetworksPermissionForUid( - final int uid, final String packageName) throws Exception { - when(mPackageManager.getPackageInfo( - eq(packageName), eq(GET_PERMISSIONS | MATCH_ANY_USER))) - .thenReturn(buildPackageInfo(true /* hasSystemPermission */, uid)); - mService.mPermissionMonitor.onPackageAdded(packageName, uid); - } - - @Test - public void testNetworkGoesIntoBackgroundAfterLinger() throws Exception { - setAlwaysOnNetworks(true); - grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid()); - NetworkRequest request = new NetworkRequest.Builder() - .clearCapabilities() - .build(); - TestNetworkCallback callback = new TestNetworkCallback(); - mCm.registerNetworkCallback(request, callback); - - TestNetworkCallback defaultCallback = new TestNetworkCallback(); - mCm.registerDefaultNetworkCallback(defaultCallback); - - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - - mCellNetworkAgent.connect(true); - callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - - // Wifi comes up and cell lingers. - mWiFiNetworkAgent.connect(true); - defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); - callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); - callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); - - // File a request for cellular, then release it. - NetworkRequest cellRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR).build(); - NetworkCallback noopCallback = new NetworkCallback(); - mCm.requestNetwork(cellRequest, noopCallback); - mCm.unregisterNetworkCallback(noopCallback); - callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); - - // Let linger run its course. - callback.assertNoCallback(); - final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4; - callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent, - lingerTimeoutMs); - - // Clean up. - mCm.unregisterNetworkCallback(defaultCallback); - mCm.unregisterNetworkCallback(callback); - } - - private NativeNetworkConfig nativeNetworkConfigPhysical(int netId, int permission) { - return new NativeNetworkConfig(netId, NativeNetworkType.PHYSICAL, permission, - /*secure=*/ false, VpnManager.TYPE_VPN_NONE); - } - - private NativeNetworkConfig nativeNetworkConfigVpn(int netId, boolean secure, int vpnType) { - return new NativeNetworkConfig(netId, NativeNetworkType.VIRTUAL, INetd.PERMISSION_NONE, - secure, vpnType); - } - - @Test - public void testNetworkAgentCallbacks() throws Exception { - // Keeps track of the order of events that happen in this test. - final LinkedBlockingQueue eventOrder = new LinkedBlockingQueue<>(); - - final NetworkRequest request = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_WIFI).build(); - final TestNetworkCallback callback = new TestNetworkCallback(); - final AtomicReference wifiNetwork = new AtomicReference<>(); - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - - // Expectations for state when various callbacks fire. These expectations run on the handler - // thread and not on the test thread because they need to prevent the handler thread from - // advancing while they examine state. - - // 1. When onCreated fires, netd has been told to create the network. - mWiFiNetworkAgent.setCreatedCallback(() -> { - eventOrder.offer("onNetworkCreated"); - wifiNetwork.set(mWiFiNetworkAgent.getNetwork()); - assertNotNull(wifiNetwork.get()); - try { - verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical( - wifiNetwork.get().getNetId(), INetd.PERMISSION_NONE)); - } catch (RemoteException impossible) { - fail(); - } - }); - - // 2. onNetworkUnwanted isn't precisely ordered with respect to any particular events. Just - // check that it is fired at some point after disconnect. - mWiFiNetworkAgent.setUnwantedCallback(() -> eventOrder.offer("onNetworkUnwanted")); - - // 3. While the teardown timer is running, connectivity APIs report the network is gone, but - // netd has not yet been told to destroy it. - final Runnable duringTeardown = () -> { - eventOrder.offer("timePasses"); - assertNull(mCm.getLinkProperties(wifiNetwork.get())); - try { - verify(mMockNetd, never()).networkDestroy(wifiNetwork.get().getNetId()); - } catch (RemoteException impossible) { - fail(); - } - }; - - // 4. After onNetworkDisconnected is called, connectivity APIs report the network is gone, - // and netd has been told to destroy it. - mWiFiNetworkAgent.setDisconnectedCallback(() -> { - eventOrder.offer("onNetworkDisconnected"); - assertNull(mCm.getLinkProperties(wifiNetwork.get())); - try { - verify(mMockNetd).networkDestroy(wifiNetwork.get().getNetId()); - } catch (RemoteException impossible) { - fail(); - } - }); - - // Connect a network, and file a request for it after it has come up, to ensure the nascent - // timer is cleared and the test does not have to wait for it. Filing the request after the - // network has come up is necessary because ConnectivityService does not appear to clear the - // nascent timer if the first request satisfied by the network was filed before the network - // connected. - // TODO: fix this bug, file the request before connecting, and remove the waitForIdle. - mWiFiNetworkAgent.connectWithoutInternet(); - waitForIdle(); - mCm.requestNetwork(request, callback); - callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - - // Set teardown delay and make sure CS has processed it. - mWiFiNetworkAgent.getNetworkAgent().setTeardownDelayMillis(300); - waitForIdle(); - - // Post the duringTeardown lambda to the handler so it fires while teardown is in progress. - // The delay must be long enough it will run after the unregisterNetworkCallback has torn - // down the network and started the teardown timer, and short enough that the lambda is - // scheduled to run before the teardown timer. - final Handler h = new Handler(mCsHandlerThread.getLooper()); - h.postDelayed(duringTeardown, 150); - - // Disconnect the network and check that events happened in the right order. - mCm.unregisterNetworkCallback(callback); - assertEquals("onNetworkCreated", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - assertEquals("onNetworkUnwanted", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - assertEquals("timePasses", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - assertEquals("onNetworkDisconnected", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - - mCm.unregisterNetworkCallback(callback); - } - - @Test - public void testExplicitlySelected() throws Exception { - NetworkRequest request = new NetworkRequest.Builder() - .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET) - .build(); - TestNetworkCallback callback = new TestNetworkCallback(); - mCm.registerNetworkCallback(request, callback); - - // Bring up validated cell. - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - - // Bring up unvalidated wifi with explicitlySelected=true. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.explicitlySelected(true, false); - mWiFiNetworkAgent.connect(false); - callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - - // Cell Remains the default. - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - - // Lower wifi's score to below than cell, and check that it doesn't disconnect because - // it's explicitly selected. - mWiFiNetworkAgent.adjustScore(-40); - mWiFiNetworkAgent.adjustScore(40); - callback.assertNoCallback(); - - // If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to - // wifi even though it's unvalidated. - mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false); - callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - - // Disconnect wifi, and then reconnect, again with explicitlySelected=true. - mWiFiNetworkAgent.disconnect(); - callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.explicitlySelected(true, false); - mWiFiNetworkAgent.connect(false); - callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - - // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the - // network to disconnect. - mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false); - callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - - // Reconnect, again with explicitlySelected=true, but this time validate. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.explicitlySelected(true, false); - mWiFiNetworkAgent.connect(true); - callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); - callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - - mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET); - mEthernetNetworkAgent.connect(true); - callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent); - callback.expectCallback(CallbackEntry.LOSING, mWiFiNetworkAgent); - callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent); - assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - callback.assertNoCallback(); - - // Disconnect wifi, and then reconnect as if the user had selected "yes, don't ask again" - // (i.e., with explicitlySelected=true and acceptUnvalidated=true). Expect to switch to - // wifi immediately. - mWiFiNetworkAgent.disconnect(); - callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.explicitlySelected(true, true); - mWiFiNetworkAgent.connect(false); - callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - callback.expectCallback(CallbackEntry.LOSING, mEthernetNetworkAgent); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - mEthernetNetworkAgent.disconnect(); - callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent); - - // Disconnect and reconnect with explicitlySelected=false and acceptUnvalidated=true. - // Check that the network is not scored specially and that the device prefers cell data. - mWiFiNetworkAgent.disconnect(); - callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.explicitlySelected(false, true); - mWiFiNetworkAgent.connect(false); - callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - - // Clean up. - mWiFiNetworkAgent.disconnect(); - mCellNetworkAgent.disconnect(); - - callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - } - - private void tryNetworkFactoryRequests(int capability) throws Exception { - // Verify NOT_RESTRICTED is set appropriately - final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability) - .build().networkCapabilities; - if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN - || capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA - || capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS - || capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP - || capability == NET_CAPABILITY_VSIM || capability == NET_CAPABILITY_BIP - || capability == NET_CAPABILITY_ENTERPRISE) { - assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); - } else { - assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); - } - - NetworkCapabilities filter = new NetworkCapabilities(); - filter.addTransportType(TRANSPORT_CELLULAR); - filter.addCapability(capability); - // Add NOT_VCN_MANAGED capability into filter unconditionally since some requests will add - // NOT_VCN_MANAGED automatically but not for NetworkCapabilities, - // see {@code NetworkCapabilities#deduceNotVcnManagedCapability} for more details. - filter.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); - final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests"); - handlerThread.start(); - final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), - mServiceContext, "testFactory", filter, mCsHandlerThread); - testFactory.setScoreFilter(45); - testFactory.register(); - - final NetworkCallback networkCallback; - if (capability != NET_CAPABILITY_INTERNET) { - // If the capability passed in argument is part of the default request, then the - // factory will see the default request. Otherwise the filter will prevent the - // factory from seeing it. In that case, add a request so it can be tested. - assertFalse(testFactory.getMyStartRequested()); - NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build(); - networkCallback = new NetworkCallback(); - mCm.requestNetwork(request, networkCallback); - } else { - networkCallback = null; - } - testFactory.expectRequestAdd(); - testFactory.assertRequestCountEquals(1); - assertTrue(testFactory.getMyStartRequested()); - - // Now bring in a higher scored network. - TestNetworkAgentWrapper testAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - // When testAgent connects, because of its score (50 legacy int / cell transport) - // it will beat or equal the testFactory's offer, so the request will be removed. - // Note the agent as validated only if the capability is INTERNET, as it's the only case - // where it makes sense. - testAgent.connect(NET_CAPABILITY_INTERNET == capability /* validated */); - testAgent.addCapability(capability); - testFactory.expectRequestRemove(); - testFactory.assertRequestCountEquals(0); - assertFalse(testFactory.getMyStartRequested()); - - // Add a request and make sure it's not sent to the factory, because the agent - // is satisfying it better. - final NetworkCallback cb = new ConnectivityManager.NetworkCallback(); - mCm.requestNetwork(new NetworkRequest.Builder().addCapability(capability).build(), cb); - expectNoRequestChanged(testFactory); - testFactory.assertRequestCountEquals(0); - assertFalse(testFactory.getMyStartRequested()); - - // If using legacy scores, make the test agent weak enough to have the exact same score as - // the factory (50 for cell - 5 adjustment). Make sure the factory doesn't see the request. - // If not using legacy score, this is a no-op and the "same score removes request" behavior - // has already been tested above. - testAgent.adjustScore(-5); - expectNoRequestChanged(testFactory); - assertFalse(testFactory.getMyStartRequested()); - - // Make the test agent weak enough that the factory will see the two requests (the one that - // was just sent, and either the default one or the one sent at the top of this test if - // the default won't be seen). - testAgent.setScore(new NetworkScore.Builder().setLegacyInt(2).setExiting(true).build()); - testFactory.expectRequestAdds(2); - testFactory.assertRequestCountEquals(2); - assertTrue(testFactory.getMyStartRequested()); - - // Now unregister and make sure the request is removed. - mCm.unregisterNetworkCallback(cb); - testFactory.expectRequestRemove(); - - // Bring in a bunch of requests. - assertEquals(1, testFactory.getMyRequestCount()); - ConnectivityManager.NetworkCallback[] networkCallbacks = - new ConnectivityManager.NetworkCallback[10]; - for (int i = 0; i< networkCallbacks.length; i++) { - networkCallbacks[i] = new ConnectivityManager.NetworkCallback(); - NetworkRequest.Builder builder = new NetworkRequest.Builder(); - builder.addCapability(capability); - mCm.requestNetwork(builder.build(), networkCallbacks[i]); - } - testFactory.expectRequestAdds(10); - testFactory.assertRequestCountEquals(11); // +1 for the default/test specific request - assertTrue(testFactory.getMyStartRequested()); - - // Remove the requests. - for (int i = 0; i < networkCallbacks.length; i++) { - mCm.unregisterNetworkCallback(networkCallbacks[i]); - } - testFactory.expectRequestRemoves(10); - testFactory.assertRequestCountEquals(1); - assertTrue(testFactory.getMyStartRequested()); - - // Adjust the agent score up again. Expect the request to be withdrawn. - testAgent.setScore(new NetworkScore.Builder().setLegacyInt(50).build()); - testFactory.expectRequestRemove(); - testFactory.assertRequestCountEquals(0); - assertFalse(testFactory.getMyStartRequested()); - - // Drop the higher scored network. - testAgent.disconnect(); - testFactory.expectRequestAdd(); - testFactory.assertRequestCountEquals(1); - assertEquals(1, testFactory.getMyRequestCount()); - assertTrue(testFactory.getMyStartRequested()); - - testFactory.terminate(); - if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback); - handlerThread.quit(); - } - - @Test - public void testNetworkFactoryRequests() throws Exception { - tryNetworkFactoryRequests(NET_CAPABILITY_MMS); - tryNetworkFactoryRequests(NET_CAPABILITY_SUPL); - tryNetworkFactoryRequests(NET_CAPABILITY_DUN); - tryNetworkFactoryRequests(NET_CAPABILITY_FOTA); - tryNetworkFactoryRequests(NET_CAPABILITY_IMS); - tryNetworkFactoryRequests(NET_CAPABILITY_CBS); - tryNetworkFactoryRequests(NET_CAPABILITY_WIFI_P2P); - tryNetworkFactoryRequests(NET_CAPABILITY_IA); - tryNetworkFactoryRequests(NET_CAPABILITY_RCS); - tryNetworkFactoryRequests(NET_CAPABILITY_XCAP); - tryNetworkFactoryRequests(NET_CAPABILITY_ENTERPRISE); - tryNetworkFactoryRequests(NET_CAPABILITY_EIMS); - tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED); - tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET); - tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED); - tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN); - tryNetworkFactoryRequests(NET_CAPABILITY_VSIM); - tryNetworkFactoryRequests(NET_CAPABILITY_BIP); - // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed. - } - - @Test - public void testRegisterIgnoringScore() throws Exception { - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.setScore(new NetworkScore.Builder().setLegacyInt(90).build()); - mWiFiNetworkAgent.connect(true /* validated */); - - // Make sure the factory sees the default network - final NetworkCapabilities filter = new NetworkCapabilities(); - filter.addTransportType(TRANSPORT_CELLULAR); - filter.addCapability(NET_CAPABILITY_INTERNET); - filter.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); - final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests"); - handlerThread.start(); - final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), - mServiceContext, "testFactory", filter, mCsHandlerThread); - testFactory.register(); - - final MockNetworkFactory testFactoryAll = new MockNetworkFactory(handlerThread.getLooper(), - mServiceContext, "testFactoryAll", filter, mCsHandlerThread); - testFactoryAll.registerIgnoringScore(); - - // The regular test factory should not see the request, because WiFi is stronger than cell. - expectNoRequestChanged(testFactory); - // With ignoringScore though the request is seen. - testFactoryAll.expectRequestAdd(); - - // The legacy int will be ignored anyway, set the only other knob to true - mWiFiNetworkAgent.setScore(new NetworkScore.Builder().setLegacyInt(110) - .setTransportPrimary(true).build()); - - expectNoRequestChanged(testFactory); // still not seeing the request - expectNoRequestChanged(testFactoryAll); // still seeing the request - - mWiFiNetworkAgent.disconnect(); - } - - @Test - public void testNetworkFactoryUnregister() throws Exception { - // Make sure the factory sees the default network - final NetworkCapabilities filter = new NetworkCapabilities(); - filter.addCapability(NET_CAPABILITY_INTERNET); - filter.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); - - final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests"); - handlerThread.start(); - - // Checks that calling setScoreFilter on a NetworkFactory immediately before closing it - // does not crash. - for (int i = 0; i < 100; i++) { - final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), - mServiceContext, "testFactory", filter, mCsHandlerThread); - // Register the factory and don't be surprised when the default request arrives. - testFactory.register(); - testFactory.expectRequestAdd(); - - testFactory.setScoreFilter(42); - testFactory.terminate(); - - if (i % 2 == 0) { - try { - testFactory.register(); - fail("Re-registering terminated NetworkFactory should throw"); - } catch (IllegalStateException expected) { - } - } - } - handlerThread.quit(); - } - - @Test - public void testNoMutableNetworkRequests() throws Exception { - final PendingIntent pendingIntent = PendingIntent.getBroadcast( - mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE); - NetworkRequest request1 = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_VALIDATED) - .build(); - NetworkRequest request2 = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL) - .build(); - - Class expected = IllegalArgumentException.class; - assertThrows(expected, () -> mCm.requestNetwork(request1, new NetworkCallback())); - assertThrows(expected, () -> mCm.requestNetwork(request1, pendingIntent)); - assertThrows(expected, () -> mCm.requestNetwork(request2, new NetworkCallback())); - assertThrows(expected, () -> mCm.requestNetwork(request2, pendingIntent)); - } - - @Test - public void testMMSonWiFi() throws Exception { - // Test bringing up cellular without MMS NetworkRequest gets reaped - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS); - mCellNetworkAgent.connectWithoutInternet(); - mCellNetworkAgent.expectDisconnected(); - waitForIdle(); - assertEmpty(mCm.getAllNetworks()); - verifyNoNetwork(); - - // Test bringing up validated WiFi. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - final ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED); - mWiFiNetworkAgent.connect(true); - b.expectBroadcast(); - verifyActiveNetwork(TRANSPORT_WIFI); - - // Register MMS NetworkRequest - NetworkRequest.Builder builder = new NetworkRequest.Builder(); - builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS); - final TestNetworkCallback networkCallback = new TestNetworkCallback(); - mCm.requestNetwork(builder.build(), networkCallback); - - // Test bringing up unvalidated cellular with MMS - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS); - mCellNetworkAgent.connectWithoutInternet(); - networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); - verifyActiveNetwork(TRANSPORT_WIFI); - - // Test releasing NetworkRequest disconnects cellular with MMS - mCm.unregisterNetworkCallback(networkCallback); - mCellNetworkAgent.expectDisconnected(); - verifyActiveNetwork(TRANSPORT_WIFI); - } - - @Test - public void testMMSonCell() throws Exception { - // Test bringing up cellular without MMS - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED); - mCellNetworkAgent.connect(false); - b.expectBroadcast(); - verifyActiveNetwork(TRANSPORT_CELLULAR); - - // Register MMS NetworkRequest - NetworkRequest.Builder builder = new NetworkRequest.Builder(); - builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS); - final TestNetworkCallback networkCallback = new TestNetworkCallback(); - mCm.requestNetwork(builder.build(), networkCallback); - - // Test bringing up MMS cellular network - TestNetworkAgentWrapper - mmsNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS); - mmsNetworkAgent.connectWithoutInternet(); - networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent); - verifyActiveNetwork(TRANSPORT_CELLULAR); - - // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent - mCm.unregisterNetworkCallback(networkCallback); - mmsNetworkAgent.expectDisconnected(); - verifyActiveNetwork(TRANSPORT_CELLULAR); - } - - @Test - public void testPartialConnectivity() throws Exception { - // Register network callback. - NetworkRequest request = new NetworkRequest.Builder() - .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET) - .build(); - TestNetworkCallback callback = new TestNetworkCallback(); - mCm.registerNetworkCallback(request, callback); - - // Bring up validated mobile data. - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - - // Bring up wifi with partial connectivity. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connectWithPartialConnectivity(); - callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent); - - // Mobile data should be the default network. - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - callback.assertNoCallback(); - - // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http - // probe. - mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */); - // If the user chooses yes to use this partial connectivity wifi, switch the default - // network to wifi and check if wifi becomes valid or not. - mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */, - false /* always */); - // If user accepts partial connectivity network, - // NetworkMonitor#setAcceptPartialConnectivity() should be called too. - waitForIdle(); - verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity(); - - // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is - // validated. - mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true); - callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); - NetworkCapabilities nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, - mWiFiNetworkAgent); - assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY)); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - - // Disconnect and reconnect wifi with partial connectivity again. - mWiFiNetworkAgent.disconnect(); - callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connectWithPartialConnectivity(); - callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent); - - // Mobile data should be the default network. - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - - // If the user chooses no, disconnect wifi immediately. - mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false/* accept */, - false /* always */); - callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - - // If user accepted partial connectivity before, and device reconnects to that network - // again, but now the network has full connectivity. The network shouldn't contain - // NET_CAPABILITY_PARTIAL_CONNECTIVITY. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - // acceptUnvalidated is also used as setting for accepting partial networks. - mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */, - true /* acceptUnvalidated */); - mWiFiNetworkAgent.connect(true); - - // If user accepted partial connectivity network before, - // NetworkMonitor#setAcceptPartialConnectivity() will be called in - // ConnectivityService#updateNetworkInfo(). - callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity(); - callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); - nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); - assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY)); - - // Wifi should be the default network. - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - mWiFiNetworkAgent.disconnect(); - callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - - // The user accepted partial connectivity and selected "don't ask again". Now the user - // reconnects to the partial connectivity network. Switch to wifi as soon as partial - // connectivity is detected. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */, - true /* acceptUnvalidated */); - mWiFiNetworkAgent.connectWithPartialConnectivity(); - // If user accepted partial connectivity network before, - // NetworkMonitor#setAcceptPartialConnectivity() will be called in - // ConnectivityService#updateNetworkInfo(). - callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity(); - callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent); - mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */); - - // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is - // validated. - mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true); - callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); - mWiFiNetworkAgent.disconnect(); - callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - - // If the user accepted partial connectivity, and the device auto-reconnects to the partial - // connectivity network, it should contain both PARTIAL_CONNECTIVITY and VALIDATED. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.explicitlySelected(false /* explicitlySelected */, - true /* acceptUnvalidated */); - - // NetworkMonitor will immediately (once the HTTPS probe fails...) report the network as - // valid, because ConnectivityService calls setAcceptPartialConnectivity before it calls - // notifyNetworkConnected. - mWiFiNetworkAgent.connectWithPartialValidConnectivity(false /* isStrictMode */); - callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity(); - callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); - callback.expectCapabilitiesWith( - NET_CAPABILITY_PARTIAL_CONNECTIVITY | NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); - mWiFiNetworkAgent.disconnect(); - callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - } - - @Test - public void testCaptivePortalOnPartialConnectivity() throws Exception { - final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); - final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build(); - mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback); - - final TestNetworkCallback validatedCallback = new TestNetworkCallback(); - final NetworkRequest validatedRequest = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_VALIDATED).build(); - mCm.registerNetworkCallback(validatedRequest, validatedCallback); - - // Bring up a network with a captive portal. - // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - String redirectUrl = "http://android.com/path"; - mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl, false /* isStrictMode */); - captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), redirectUrl); - - // Check that startCaptivePortalApp sends the expected command to NetworkMonitor. - mCm.startCaptivePortalApp(mWiFiNetworkAgent.getNetwork()); - verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1)) - .launchCaptivePortalApp(); - - // Report that the captive portal is dismissed with partial connectivity, and check that - // callbacks are fired. - mWiFiNetworkAgent.setNetworkPartial(); - mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true); - waitForIdle(); - captivePortalCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, - mWiFiNetworkAgent); - - // Report partial connectivity is accepted. - mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */); - mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */, - false /* always */); - waitForIdle(); - mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true); - captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent); - NetworkCapabilities nc = - validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, - mWiFiNetworkAgent); - - mCm.unregisterNetworkCallback(captivePortalCallback); - mCm.unregisterNetworkCallback(validatedCallback); - } - - @Test - public void testCaptivePortal() throws Exception { - final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); - final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build(); - mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback); - - final TestNetworkCallback validatedCallback = new TestNetworkCallback(); - final NetworkRequest validatedRequest = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_VALIDATED).build(); - mCm.registerNetworkCallback(validatedRequest, validatedCallback); - - // Bring up a network with a captive portal. - // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - String firstRedirectUrl = "http://example.com/firstPath"; - mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */); - captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl); - - // Take down network. - // Expect onLost callback. - mWiFiNetworkAgent.disconnect(); - captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - - // Bring up a network with a captive portal. - // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - String secondRedirectUrl = "http://example.com/secondPath"; - mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl, false /* isStrictMode */); - captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl); - - // Make captive portal disappear then revalidate. - // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL. - mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */); - mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true); - captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - - // Expect NET_CAPABILITY_VALIDATED onAvailable callback. - validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); - - // Break network connectivity. - // Expect NET_CAPABILITY_VALIDATED onLost callback. - mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */); - mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false); - validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - } - - @Test - public void testCaptivePortalApp() throws Exception { - final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); - final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build(); - mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback); - - final TestNetworkCallback validatedCallback = new TestNetworkCallback(); - final NetworkRequest validatedRequest = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_VALIDATED).build(); - mCm.registerNetworkCallback(validatedRequest, validatedCallback); - - // Bring up wifi. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true); - validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); - Network wifiNetwork = mWiFiNetworkAgent.getNetwork(); - - // Check that calling startCaptivePortalApp does nothing. - final int fastTimeoutMs = 100; - mCm.startCaptivePortalApp(wifiNetwork); - waitForIdle(); - verify(mWiFiNetworkAgent.mNetworkMonitor, never()).launchCaptivePortalApp(); - mServiceContext.expectNoStartActivityIntent(fastTimeoutMs); - - // Turn into a captive portal. - mWiFiNetworkAgent.setNetworkPortal("http://example.com", false /* isStrictMode */); - mCm.reportNetworkConnectivity(wifiNetwork, false); - captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - - // Check that startCaptivePortalApp sends the expected command to NetworkMonitor. - mCm.startCaptivePortalApp(wifiNetwork); - waitForIdle(); - verify(mWiFiNetworkAgent.mNetworkMonitor).launchCaptivePortalApp(); - - // NetworkMonitor uses startCaptivePortal(Network, Bundle) (startCaptivePortalAppInternal) - final Bundle testBundle = new Bundle(); - final String testKey = "testkey"; - final String testValue = "testvalue"; - testBundle.putString(testKey, testValue); - mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, - PERMISSION_GRANTED); - mCm.startCaptivePortalApp(wifiNetwork, testBundle); - final Intent signInIntent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS); - assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, signInIntent.getAction()); - assertEquals(testValue, signInIntent.getStringExtra(testKey)); - - // Report that the captive portal is dismissed, and check that callbacks are fired - mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */); - mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid()); - validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent); - captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - - mCm.unregisterNetworkCallback(validatedCallback); - mCm.unregisterNetworkCallback(captivePortalCallback); - } - - @Test - public void testAvoidOrIgnoreCaptivePortals() throws Exception { - final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); - final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build(); - mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback); - - final TestNetworkCallback validatedCallback = new TestNetworkCallback(); - final NetworkRequest validatedRequest = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_VALIDATED).build(); - mCm.registerNetworkCallback(validatedRequest, validatedCallback); - - setCaptivePortalMode(ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_AVOID); - // Bring up a network with a captive portal. - // Expect it to fail to connect and not result in any callbacks. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - String firstRedirectUrl = "http://example.com/firstPath"; - - mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */); - mWiFiNetworkAgent.expectDisconnected(); - mWiFiNetworkAgent.expectPreventReconnectReceived(); - - assertNoCallbacks(captivePortalCallback, validatedCallback); - } - - @Test - public void testCaptivePortalApi() throws Exception { - mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED); - - final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); - final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build(); - mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback); - - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - final String redirectUrl = "http://example.com/firstPath"; - - mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl, false /* isStrictMode */); - captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - - final CaptivePortalData testData = new CaptivePortalData.Builder() - .setUserPortalUrl(Uri.parse(redirectUrl)) - .setBytesRemaining(12345L) - .build(); - - mWiFiNetworkAgent.notifyCapportApiDataChanged(testData); - - captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, - lp -> testData.equals(lp.getCaptivePortalData())); - - final LinkProperties newLps = new LinkProperties(); - newLps.setMtu(1234); - mWiFiNetworkAgent.sendLinkProperties(newLps); - // CaptivePortalData is not lost and unchanged when LPs are received from the NetworkAgent - captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, - lp -> testData.equals(lp.getCaptivePortalData()) && lp.getMtu() == 1234); - } - - private TestNetworkCallback setupNetworkCallbackAndConnectToWifi() throws Exception { - // Grant NETWORK_SETTINGS permission to be able to receive LinkProperties change callbacks - // with sensitive (captive portal) data - mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED); - - final TestNetworkCallback captivePortalCallback = new TestNetworkCallback(); - final NetworkRequest captivePortalRequest = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build(); - mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback); - - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - - mWiFiNetworkAgent.connectWithCaptivePortal(TEST_REDIRECT_URL, false /* isStrictMode */); - captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - return captivePortalCallback; - } - - private class CaptivePortalTestData { - CaptivePortalTestData(CaptivePortalData naPasspointData, CaptivePortalData capportData, - CaptivePortalData naOtherData, CaptivePortalData expectedMergedPasspointData, - CaptivePortalData expectedMergedOtherData) { - mNaPasspointData = naPasspointData; - mCapportData = capportData; - mNaOtherData = naOtherData; - mExpectedMergedPasspointData = expectedMergedPasspointData; - mExpectedMergedOtherData = expectedMergedOtherData; - } - - public final CaptivePortalData mNaPasspointData; - public final CaptivePortalData mCapportData; - public final CaptivePortalData mNaOtherData; - public final CaptivePortalData mExpectedMergedPasspointData; - public final CaptivePortalData mExpectedMergedOtherData; - - } - - private CaptivePortalTestData setupCaptivePortalData() { - final CaptivePortalData capportData = new CaptivePortalData.Builder() - .setUserPortalUrl(Uri.parse(TEST_REDIRECT_URL)) - .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_CAPPORT)) - .setUserPortalUrl(Uri.parse(TEST_USER_PORTAL_API_URL_CAPPORT)) - .setExpiryTime(1000000L) - .setBytesRemaining(12345L) - .build(); - - final CaptivePortalData naPasspointData = new CaptivePortalData.Builder() - .setBytesRemaining(80802L) - .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_NA_PASSPOINT), - CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) - .setUserPortalUrl(Uri.parse(TEST_TERMS_AND_CONDITIONS_URL_NA_PASSPOINT), - CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) - .setVenueFriendlyName(TEST_FRIENDLY_NAME).build(); - - final CaptivePortalData naOtherData = new CaptivePortalData.Builder() - .setBytesRemaining(80802L) - .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_NA_OTHER), - CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER) - .setUserPortalUrl(Uri.parse(TEST_TERMS_AND_CONDITIONS_URL_NA_OTHER), - CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER) - .setVenueFriendlyName(TEST_FRIENDLY_NAME).build(); - - final CaptivePortalData expectedMergedPasspointData = new CaptivePortalData.Builder() - .setUserPortalUrl(Uri.parse(TEST_REDIRECT_URL)) - .setBytesRemaining(12345L) - .setExpiryTime(1000000L) - .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_NA_PASSPOINT), - CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) - .setUserPortalUrl(Uri.parse(TEST_TERMS_AND_CONDITIONS_URL_NA_PASSPOINT), - CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) - .setVenueFriendlyName(TEST_FRIENDLY_NAME).build(); - - final CaptivePortalData expectedMergedOtherData = new CaptivePortalData.Builder() - .setUserPortalUrl(Uri.parse(TEST_REDIRECT_URL)) - .setBytesRemaining(12345L) - .setExpiryTime(1000000L) - .setVenueInfoUrl(Uri.parse(TEST_VENUE_URL_CAPPORT)) - .setUserPortalUrl(Uri.parse(TEST_USER_PORTAL_API_URL_CAPPORT)) - .setVenueFriendlyName(TEST_FRIENDLY_NAME).build(); - return new CaptivePortalTestData(naPasspointData, capportData, naOtherData, - expectedMergedPasspointData, expectedMergedOtherData); - } - - @Test - public void testMergeCaptivePortalApiWithFriendlyNameAndVenueUrl() throws Exception { - final TestNetworkCallback captivePortalCallback = setupNetworkCallbackAndConnectToWifi(); - final CaptivePortalTestData captivePortalTestData = setupCaptivePortalData(); - - // Baseline capport data - mWiFiNetworkAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData); - - captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, - lp -> captivePortalTestData.mCapportData.equals(lp.getCaptivePortalData())); - - // Venue URL, T&C URL and friendly name from Network agent with Passpoint source, confirm - // that API data gets precedence on the bytes remaining. - final LinkProperties linkProperties = new LinkProperties(); - linkProperties.setCaptivePortalData(captivePortalTestData.mNaPasspointData); - mWiFiNetworkAgent.sendLinkProperties(linkProperties); - - // Make sure that the capport data is merged - captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, - lp -> captivePortalTestData.mExpectedMergedPasspointData - .equals(lp.getCaptivePortalData())); - - // Now send this information from non-Passpoint source, confirm that Capport data takes - // precedence - linkProperties.setCaptivePortalData(captivePortalTestData.mNaOtherData); - mWiFiNetworkAgent.sendLinkProperties(linkProperties); - - // Make sure that the capport data is merged - captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, - lp -> captivePortalTestData.mExpectedMergedOtherData - .equals(lp.getCaptivePortalData())); - - // Create a new LP with no Network agent capport data - final LinkProperties newLps = new LinkProperties(); - newLps.setMtu(1234); - mWiFiNetworkAgent.sendLinkProperties(newLps); - // CaptivePortalData is not lost and has the original values when LPs are received from the - // NetworkAgent - captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, - lp -> captivePortalTestData.mCapportData.equals(lp.getCaptivePortalData()) - && lp.getMtu() == 1234); - - // Now send capport data only from the Network agent - mWiFiNetworkAgent.notifyCapportApiDataChanged(null); - captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, - lp -> lp.getCaptivePortalData() == null); - - newLps.setCaptivePortalData(captivePortalTestData.mNaPasspointData); - mWiFiNetworkAgent.sendLinkProperties(newLps); - - // Make sure that only the network agent capport data is available - captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, - lp -> captivePortalTestData.mNaPasspointData.equals(lp.getCaptivePortalData())); - } - - @Test - public void testMergeCaptivePortalDataFromNetworkAgentFirstThenCapport() throws Exception { - final TestNetworkCallback captivePortalCallback = setupNetworkCallbackAndConnectToWifi(); - final CaptivePortalTestData captivePortalTestData = setupCaptivePortalData(); - - // Venue URL and friendly name from Network agent, confirm that API data gets precedence - // on the bytes remaining. - final LinkProperties linkProperties = new LinkProperties(); - linkProperties.setCaptivePortalData(captivePortalTestData.mNaPasspointData); - mWiFiNetworkAgent.sendLinkProperties(linkProperties); - - // Make sure that the data is saved correctly - captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, - lp -> captivePortalTestData.mNaPasspointData.equals(lp.getCaptivePortalData())); - - // Expected merged data: Network agent data is preferred, and values that are not used by - // it are merged from capport data - mWiFiNetworkAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData); - - // Make sure that the Capport data is merged correctly - captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, - lp -> captivePortalTestData.mExpectedMergedPasspointData.equals( - lp.getCaptivePortalData())); - - // Now set the naData to null - linkProperties.setCaptivePortalData(null); - mWiFiNetworkAgent.sendLinkProperties(linkProperties); - - // Make sure that the Capport data is retained correctly - captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, - lp -> captivePortalTestData.mCapportData.equals(lp.getCaptivePortalData())); - } - - @Test - public void testMergeCaptivePortalDataFromNetworkAgentOtherSourceFirstThenCapport() - throws Exception { - final TestNetworkCallback captivePortalCallback = setupNetworkCallbackAndConnectToWifi(); - final CaptivePortalTestData captivePortalTestData = setupCaptivePortalData(); - - // Venue URL and friendly name from Network agent, confirm that API data gets precedence - // on the bytes remaining. - final LinkProperties linkProperties = new LinkProperties(); - linkProperties.setCaptivePortalData(captivePortalTestData.mNaOtherData); - mWiFiNetworkAgent.sendLinkProperties(linkProperties); - - // Make sure that the data is saved correctly - captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, - lp -> captivePortalTestData.mNaOtherData.equals(lp.getCaptivePortalData())); - - // Expected merged data: Network agent data is preferred, and values that are not used by - // it are merged from capport data - mWiFiNetworkAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData); - - // Make sure that the Capport data is merged correctly - captivePortalCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, - lp -> captivePortalTestData.mExpectedMergedOtherData.equals( - lp.getCaptivePortalData())); - } - - private NetworkRequest.Builder newWifiRequestBuilder() { - return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI); - } - - /** - * Verify request matching behavior with network specifiers. - * - * This test does not check updating the specifier on a live network because the specifier is - * immutable and this triggers a WTF in - * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)}. - */ - @Test - public void testNetworkSpecifier() throws Exception { - // A NetworkSpecifier subclass that matches all networks but must not be visible to apps. - class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements - Parcelable { - @Override - public boolean canBeSatisfiedBy(NetworkSpecifier other) { - return true; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) {} - - @Override - public NetworkSpecifier redact() { - return null; - } - } - - // A network specifier that matches either another LocalNetworkSpecifier with the same - // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is. - class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable { - private String mString; - - LocalStringNetworkSpecifier(String string) { - mString = string; - } - - @Override - public boolean canBeSatisfiedBy(NetworkSpecifier other) { - if (other instanceof LocalStringNetworkSpecifier) { - return TextUtils.equals(mString, - ((LocalStringNetworkSpecifier) other).mString); - } - if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true; - return false; - } - - @Override - public int describeContents() { - return 0; - } - @Override - public void writeToParcel(Parcel dest, int flags) {} - } - - - NetworkRequest rEmpty1 = newWifiRequestBuilder().build(); - NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build(); - NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build(); - NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier( - (NetworkSpecifier) null).build(); - NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier( - new LocalStringNetworkSpecifier("foo")).build(); - NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier( - new LocalStringNetworkSpecifier("bar")).build(); - - TestNetworkCallback cEmpty1 = new TestNetworkCallback(); - TestNetworkCallback cEmpty2 = new TestNetworkCallback(); - TestNetworkCallback cEmpty3 = new TestNetworkCallback(); - TestNetworkCallback cEmpty4 = new TestNetworkCallback(); - TestNetworkCallback cFoo = new TestNetworkCallback(); - TestNetworkCallback cBar = new TestNetworkCallback(); - TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] { - cEmpty1, cEmpty2, cEmpty3, cEmpty4 }; - - mCm.registerNetworkCallback(rEmpty1, cEmpty1); - mCm.registerNetworkCallback(rEmpty2, cEmpty2); - mCm.registerNetworkCallback(rEmpty3, cEmpty3); - mCm.registerNetworkCallback(rEmpty4, cEmpty4); - mCm.registerNetworkCallback(rFoo, cFoo); - mCm.registerNetworkCallback(rBar, cBar); - - LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo"); - LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar"); - - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); - expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, null /* specifier */, - cEmpty1, cEmpty2, cEmpty3, cEmpty4); - assertNoCallbacks(cFoo, cBar); - - mWiFiNetworkAgent.disconnect(); - expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4); - - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.setNetworkSpecifier(nsFoo); - mWiFiNetworkAgent.connect(false); - expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, nsFoo, - cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo); - cBar.assertNoCallback(); - assertEquals(nsFoo, - mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier()); - assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo); - - mWiFiNetworkAgent.disconnect(); - expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo); - - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.setNetworkSpecifier(nsBar); - mWiFiNetworkAgent.connect(false); - expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, nsBar, - cEmpty1, cEmpty2, cEmpty3, cEmpty4, cBar); - cFoo.assertNoCallback(); - assertEquals(nsBar, - mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier()); - - mWiFiNetworkAgent.disconnect(); - expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cBar); - cFoo.assertNoCallback(); - - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier()); - mWiFiNetworkAgent.connect(false); - expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, null /* specifier */, - cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar); - assertNull( - mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier()); - - mWiFiNetworkAgent.disconnect(); - expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar); - } - - /** - * @return the context's attribution tag - */ - private String getAttributionTag() { - return mContext.getAttributionTag(); - } - - @Test - public void testInvalidNetworkSpecifier() { - assertThrows(IllegalArgumentException.class, () -> { - NetworkRequest.Builder builder = new NetworkRequest.Builder(); - builder.setNetworkSpecifier(new MatchAllNetworkSpecifier()); - }); - - assertThrows(IllegalArgumentException.class, () -> { - NetworkCapabilities networkCapabilities = new NetworkCapabilities(); - networkCapabilities.addTransportType(TRANSPORT_WIFI) - .setNetworkSpecifier(new MatchAllNetworkSpecifier()); - mService.requestNetwork(Process.INVALID_UID, networkCapabilities, - NetworkRequest.Type.REQUEST.ordinal(), null, 0, null, - ConnectivityManager.TYPE_WIFI, NetworkCallback.FLAG_NONE, - mContext.getPackageName(), getAttributionTag()); - }); - - class NonParcelableSpecifier extends NetworkSpecifier { - @Override - public boolean canBeSatisfiedBy(NetworkSpecifier other) { - return false; - } - }; - class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable { - @Override public int describeContents() { return 0; } - @Override public void writeToParcel(Parcel p, int flags) {} - } - - final NetworkRequest.Builder builder = - new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET); - assertThrows(ClassCastException.class, () -> { - builder.setNetworkSpecifier(new NonParcelableSpecifier()); - Parcel parcelW = Parcel.obtain(); - builder.build().writeToParcel(parcelW, 0); - }); - - final NetworkRequest nr = - new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET) - .setNetworkSpecifier(new ParcelableSpecifier()) - .build(); - assertNotNull(nr); - - assertThrows(BadParcelableException.class, () -> { - Parcel parcelW = Parcel.obtain(); - nr.writeToParcel(parcelW, 0); - byte[] bytes = parcelW.marshall(); - parcelW.recycle(); - - Parcel parcelR = Parcel.obtain(); - parcelR.unmarshall(bytes, 0, bytes.length); - parcelR.setDataPosition(0); - NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR); - }); - } - - @Test - public void testNetworkRequestUidSpoofSecurityException() throws Exception { - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); - NetworkRequest networkRequest = newWifiRequestBuilder().build(); - TestNetworkCallback networkCallback = new TestNetworkCallback(); - doThrow(new SecurityException()).when(mAppOpsManager).checkPackage(anyInt(), anyString()); - assertThrows(SecurityException.class, () -> { - mCm.requestNetwork(networkRequest, networkCallback); - }); - } - - @Test - public void testInvalidSignalStrength() { - NetworkRequest r = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_INTERNET) - .addTransportType(TRANSPORT_WIFI) - .setSignalStrength(-75) - .build(); - // Registering a NetworkCallback with signal strength but w/o NETWORK_SIGNAL_STRENGTH_WAKEUP - // permission should get SecurityException. - assertThrows(SecurityException.class, () -> - mCm.registerNetworkCallback(r, new NetworkCallback())); - - assertThrows(SecurityException.class, () -> - mCm.registerNetworkCallback(r, PendingIntent.getService( - mServiceContext, 0 /* requestCode */, new Intent(), FLAG_IMMUTABLE))); - - // Requesting a Network with signal strength should get IllegalArgumentException. - assertThrows(IllegalArgumentException.class, () -> - mCm.requestNetwork(r, new NetworkCallback())); - - assertThrows(IllegalArgumentException.class, () -> - mCm.requestNetwork(r, PendingIntent.getService( - mServiceContext, 0 /* requestCode */, new Intent(), FLAG_IMMUTABLE))); - } - - @Test - public void testRegisterDefaultNetworkCallback() throws Exception { - // NETWORK_SETTINGS is necessary to call registerSystemDefaultNetworkCallback. - mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED); - - final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback(); - mCm.registerDefaultNetworkCallback(defaultNetworkCallback); - defaultNetworkCallback.assertNoCallback(); - - final Handler handler = new Handler(ConnectivityThread.getInstanceLooper()); - final TestNetworkCallback systemDefaultCallback = new TestNetworkCallback(); - mCm.registerSystemDefaultNetworkCallback(systemDefaultCallback, handler); - systemDefaultCallback.assertNoCallback(); - - // Create a TRANSPORT_CELLULAR request to keep the mobile interface up - // whenever Wi-Fi is up. Without this, the mobile network agent is - // reaped before any other activity can take place. - final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); - final NetworkRequest cellRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR).build(); - mCm.requestNetwork(cellRequest, cellNetworkCallback); - cellNetworkCallback.assertNoCallback(); - - // Bring up cell and expect CALLBACK_AVAILABLE. - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - systemDefaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - - // Bring up wifi and expect CALLBACK_AVAILABLE. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true); - cellNetworkCallback.assertNoCallback(); - defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); - systemDefaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); - assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - - // Bring down cell. Expect no default network callback, since it wasn't the default. - mCellNetworkAgent.disconnect(); - cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - defaultNetworkCallback.assertNoCallback(); - systemDefaultCallback.assertNoCallback(); - assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - - // Bring up cell. Expect no default network callback, since it won't be the default. - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - defaultNetworkCallback.assertNoCallback(); - systemDefaultCallback.assertNoCallback(); - assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - assertEquals(systemDefaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - - // Bring down wifi. Expect the default network callback to notified of LOST wifi - // followed by AVAILABLE cell. - mWiFiNetworkAgent.disconnect(); - cellNetworkCallback.assertNoCallback(); - defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); - systemDefaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - systemDefaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); - mCellNetworkAgent.disconnect(); - cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - systemDefaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - waitForIdle(); - assertEquals(null, mCm.getActiveNetwork()); - - mMockVpn.establishForMyUid(); - assertUidRangesUpdatedForMyUid(true); - defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn); - systemDefaultCallback.assertNoCallback(); - assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - assertEquals(null, systemDefaultCallback.getLastAvailableNetwork()); - - mMockVpn.disconnect(); - defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn); - systemDefaultCallback.assertNoCallback(); - waitForIdle(); - assertEquals(null, mCm.getActiveNetwork()); - } - - @Test - public void testAdditionalStateCallbacks() throws Exception { - // File a network request for mobile. - final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); - final NetworkRequest cellRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR).build(); - mCm.requestNetwork(cellRequest, cellNetworkCallback); - - // Bring up the mobile network. - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - - // We should get onAvailable(), onCapabilitiesChanged(), and - // onLinkPropertiesChanged() in rapid succession. Additionally, we - // should get onCapabilitiesChanged() when the mobile network validates. - cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - cellNetworkCallback.assertNoCallback(); - - // Update LinkProperties. - final LinkProperties lp = new LinkProperties(); - lp.setInterfaceName("foonet_data0"); - mCellNetworkAgent.sendLinkProperties(lp); - // We should get onLinkPropertiesChanged(). - cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, - mCellNetworkAgent); - cellNetworkCallback.assertNoCallback(); - - // Suspend the network. - mCellNetworkAgent.suspend(); - cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED, - mCellNetworkAgent); - cellNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, mCellNetworkAgent); - cellNetworkCallback.assertNoCallback(); - assertEquals(NetworkInfo.State.SUSPENDED, mCm.getActiveNetworkInfo().getState()); - - // Register a garden variety default network request. - TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback(); - mCm.registerDefaultNetworkCallback(dfltNetworkCallback); - // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(), - // as well as onNetworkSuspended() in rapid succession. - dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true); - dfltNetworkCallback.assertNoCallback(); - mCm.unregisterNetworkCallback(dfltNetworkCallback); - - mCellNetworkAgent.resume(); - cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED, - mCellNetworkAgent); - cellNetworkCallback.expectCallback(CallbackEntry.RESUMED, mCellNetworkAgent); - cellNetworkCallback.assertNoCallback(); - assertEquals(NetworkInfo.State.CONNECTED, mCm.getActiveNetworkInfo().getState()); - - dfltNetworkCallback = new TestNetworkCallback(); - mCm.registerDefaultNetworkCallback(dfltNetworkCallback); - // This time onNetworkSuspended should not be called. - dfltNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); - dfltNetworkCallback.assertNoCallback(); - - mCm.unregisterNetworkCallback(dfltNetworkCallback); - mCm.unregisterNetworkCallback(cellNetworkCallback); - } - - @Test - public void testRegisterPrivilegedDefaultCallbacksRequireNetworkSettings() throws Exception { - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(false /* validated */); - - final Handler handler = new Handler(ConnectivityThread.getInstanceLooper()); - final TestNetworkCallback callback = new TestNetworkCallback(); - assertThrows(SecurityException.class, - () -> mCm.registerSystemDefaultNetworkCallback(callback, handler)); - callback.assertNoCallback(); - assertThrows(SecurityException.class, - () -> mCm.registerDefaultNetworkCallbackForUid(APP1_UID, callback, handler)); - callback.assertNoCallback(); - - mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED); - mCm.registerSystemDefaultNetworkCallback(callback, handler); - callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); - mCm.unregisterNetworkCallback(callback); - - mCm.registerDefaultNetworkCallbackForUid(APP1_UID, callback, handler); - callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); - mCm.unregisterNetworkCallback(callback); - } - - @Test - public void testNetworkCallbackWithNullUids() throws Exception { - final NetworkRequest request = new NetworkRequest.Builder() - .removeCapability(NET_CAPABILITY_NOT_VPN) - .build(); - final TestNetworkCallback callback = new TestNetworkCallback(); - mCm.registerNetworkCallback(request, callback); - - // Attempt to file a callback for networks applying to another UID. This does not actually - // work, because this code does not currently have permission to do so. The callback behaves - // exactly the same as the one registered just above. - final int otherUid = UserHandle.getUid(RESTRICTED_USER, VPN_UID); - final NetworkRequest otherUidRequest = new NetworkRequest.Builder() - .removeCapability(NET_CAPABILITY_NOT_VPN) - .setUids(UidRange.toIntRanges(uidRangesForUids(otherUid))) - .build(); - final TestNetworkCallback otherUidCallback = new TestNetworkCallback(); - mCm.registerNetworkCallback(otherUidRequest, otherUidCallback); - - final NetworkRequest includeOtherUidsRequest = new NetworkRequest.Builder() - .removeCapability(NET_CAPABILITY_NOT_VPN) - .setIncludeOtherUidNetworks(true) - .build(); - final TestNetworkCallback includeOtherUidsCallback = new TestNetworkCallback(); - mCm.registerNetworkCallback(includeOtherUidsRequest, includeOtherUidsCallback); - - // Both callbacks see a network with no specifier that applies to their UID. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false /* validated */); - callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - otherUidCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - includeOtherUidsCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - mWiFiNetworkAgent.disconnect(); - callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - otherUidCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - includeOtherUidsCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - - // Only the includeOtherUidsCallback sees a VPN that does not apply to its UID. - final UidRange range = UidRange.createForUser(UserHandle.of(RESTRICTED_USER)); - final Set vpnRanges = Collections.singleton(range); - mMockVpn.establish(new LinkProperties(), VPN_UID, vpnRanges); - includeOtherUidsCallback.expectAvailableThenValidatedCallbacks(mMockVpn); - callback.assertNoCallback(); - otherUidCallback.assertNoCallback(); - - mMockVpn.disconnect(); - includeOtherUidsCallback.expectCallback(CallbackEntry.LOST, mMockVpn); - callback.assertNoCallback(); - otherUidCallback.assertNoCallback(); - } - - private static class RedactableNetworkSpecifier extends NetworkSpecifier { - public static final int ID_INVALID = -1; - - public final int networkId; - - RedactableNetworkSpecifier(int networkId) { - this.networkId = networkId; - } - - @Override - public boolean canBeSatisfiedBy(NetworkSpecifier other) { - return other instanceof RedactableNetworkSpecifier - && this.networkId == ((RedactableNetworkSpecifier) other).networkId; - } - - @Override - public NetworkSpecifier redact() { - return new RedactableNetworkSpecifier(ID_INVALID); - } - } - - @Test - public void testNetworkCallbackWithNullUidsRedactsSpecifier() throws Exception { - final RedactableNetworkSpecifier specifier = new RedactableNetworkSpecifier(42); - final NetworkRequest request = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_INTERNET) - .addTransportType(TRANSPORT_WIFI) - .setNetworkSpecifier(specifier) - .build(); - final TestNetworkCallback callback = new TestNetworkCallback(); - mCm.registerNetworkCallback(request, callback); - - // Attempt to file a callback for networks applying to another UID. This does not actually - // work, because this code does not currently have permission to do so. The callback behaves - // exactly the same as the one registered just above. - final int otherUid = UserHandle.getUid(RESTRICTED_USER, VPN_UID); - final NetworkRequest otherUidRequest = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_INTERNET) - .addTransportType(TRANSPORT_WIFI) - .setNetworkSpecifier(specifier) - .setUids(UidRange.toIntRanges(uidRangesForUids(otherUid))) - .build(); - final TestNetworkCallback otherUidCallback = new TestNetworkCallback(); - mCm.registerNetworkCallback(otherUidRequest, otherUidCallback); - - final NetworkRequest includeOtherUidsRequest = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_INTERNET) - .addTransportType(TRANSPORT_WIFI) - .setNetworkSpecifier(specifier) - .setIncludeOtherUidNetworks(true) - .build(); - final TestNetworkCallback includeOtherUidsCallback = new TestNetworkCallback(); - mCm.registerNetworkCallback(includeOtherUidsRequest, callback); - - // Only the regular callback sees the network, because callbacks filed with no UID have - // their specifiers redacted. - final LinkProperties emptyLp = new LinkProperties(); - final NetworkCapabilities ncTemplate = new NetworkCapabilities() - .addTransportType(TRANSPORT_WIFI) - .setNetworkSpecifier(specifier); - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, emptyLp, ncTemplate); - mWiFiNetworkAgent.connect(false /* validated */); - callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - otherUidCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - includeOtherUidsCallback.assertNoCallback(); - } - - private void setCaptivePortalMode(int mode) { - ContentResolver cr = mServiceContext.getContentResolver(); - Settings.Global.putInt(cr, ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE, mode); - } - - private void setAlwaysOnNetworks(boolean enable) { - ContentResolver cr = mServiceContext.getContentResolver(); - Settings.Global.putInt(cr, ConnectivitySettingsManager.MOBILE_DATA_ALWAYS_ON, - enable ? 1 : 0); - mService.updateAlwaysOnNetworks(); - waitForIdle(); - } - - private void setPrivateDnsSettings(int mode, String specifier) { - ConnectivitySettingsManager.setPrivateDnsMode(mServiceContext, mode); - ConnectivitySettingsManager.setPrivateDnsHostname(mServiceContext, specifier); - mService.updatePrivateDnsSettings(); - waitForIdle(); - } - - private boolean isForegroundNetwork(TestNetworkAgentWrapper network) { - NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork()); - assertNotNull(nc); - return nc.hasCapability(NET_CAPABILITY_FOREGROUND); - } - - @Test - public void testBackgroundNetworks() throws Exception { - // Create a cellular background request. - grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid()); - final TestNetworkCallback cellBgCallback = new TestNetworkCallback(); - mCm.requestBackgroundNetwork(new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR).build(), - cellBgCallback, mCsHandlerThread.getThreadHandler()); - - // Make callbacks for monitoring. - final NetworkRequest request = new NetworkRequest.Builder().build(); - final NetworkRequest fgRequest = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_FOREGROUND).build(); - final TestNetworkCallback callback = new TestNetworkCallback(); - final TestNetworkCallback fgCallback = new TestNetworkCallback(); - mCm.registerNetworkCallback(request, callback); - mCm.registerNetworkCallback(fgRequest, fgCallback); - - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - assertTrue(isForegroundNetwork(mCellNetworkAgent)); - - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true); - - // When wifi connects, cell lingers. - callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); - callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); - fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - fgCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); - fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); - assertTrue(isForegroundNetwork(mCellNetworkAgent)); - assertTrue(isForegroundNetwork(mWiFiNetworkAgent)); - - // When lingering is complete, cell is still there but is now in the background. - waitForIdle(); - int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4; - fgCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, timeoutMs); - // Expect a network capabilities update sans FOREGROUND. - callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent); - assertFalse(isForegroundNetwork(mCellNetworkAgent)); - assertTrue(isForegroundNetwork(mWiFiNetworkAgent)); - - // File a cell request and check that cell comes into the foreground. - final NetworkRequest cellRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR).build(); - final TestNetworkCallback cellCallback = new TestNetworkCallback(); - mCm.requestNetwork(cellRequest, cellCallback); - cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); - fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); - // Expect a network capabilities update with FOREGROUND, because the most recent - // request causes its state to change. - cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent); - callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent); - assertTrue(isForegroundNetwork(mCellNetworkAgent)); - assertTrue(isForegroundNetwork(mWiFiNetworkAgent)); - - // Release the request. The network immediately goes into the background, since it was not - // lingering. - mCm.unregisterNetworkCallback(cellCallback); - fgCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - // Expect a network capabilities update sans FOREGROUND. - callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent); - assertFalse(isForegroundNetwork(mCellNetworkAgent)); - assertTrue(isForegroundNetwork(mWiFiNetworkAgent)); - - // Disconnect wifi and check that cell is foreground again. - mWiFiNetworkAgent.disconnect(); - callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - fgCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); - assertTrue(isForegroundNetwork(mCellNetworkAgent)); - - mCm.unregisterNetworkCallback(callback); - mCm.unregisterNetworkCallback(fgCallback); - mCm.unregisterNetworkCallback(cellBgCallback); - } - - @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing. - public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception { - // TODO: turn this unit test into a real benchmarking test. - // Benchmarks connecting and switching performance in the presence of a large number of - // NetworkRequests. - // 1. File NUM_REQUESTS requests. - // 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire. - // 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing - // and NUM_REQUESTS onAvailable callbacks to fire. - // See how long it took. - final int NUM_REQUESTS = 90; - final int REGISTER_TIME_LIMIT_MS = 200; - final int CONNECT_TIME_LIMIT_MS = 60; - final int SWITCH_TIME_LIMIT_MS = 60; - final int UNREGISTER_TIME_LIMIT_MS = 20; - - final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build(); - final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS]; - final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS); - final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS); - - for (int i = 0; i < NUM_REQUESTS; i++) { - callbacks[i] = new NetworkCallback() { - @Override public void onAvailable(Network n) { availableLatch.countDown(); } - @Override public void onLosing(Network n, int t) { losingLatch.countDown(); } - }; - } - - assertRunsInAtMost("Registering callbacks", REGISTER_TIME_LIMIT_MS, () -> { - for (NetworkCallback cb : callbacks) { - mCm.registerNetworkCallback(request, cb); - } - }); - - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - // Don't request that the network validate, because otherwise connect() will block until - // the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired, - // and we won't actually measure anything. - mCellNetworkAgent.connect(false); - - long onAvailableDispatchingDuration = durationOf(() -> { - await(availableLatch, 10 * CONNECT_TIME_LIMIT_MS); - }); - Log.d(TAG, String.format("Dispatched %d of %d onAvailable callbacks in %dms", - NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS, - onAvailableDispatchingDuration)); - assertTrue(String.format("Dispatching %d onAvailable callbacks in %dms, expected %dms", - NUM_REQUESTS, onAvailableDispatchingDuration, CONNECT_TIME_LIMIT_MS), - onAvailableDispatchingDuration <= CONNECT_TIME_LIMIT_MS); - - // Give wifi a high enough score that we'll linger cell when wifi comes up. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.adjustScore(40); - mWiFiNetworkAgent.connect(false); - - long onLostDispatchingDuration = durationOf(() -> { - await(losingLatch, 10 * SWITCH_TIME_LIMIT_MS); - }); - Log.d(TAG, String.format("Dispatched %d of %d onLosing callbacks in %dms", - NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, onLostDispatchingDuration)); - assertTrue(String.format("Dispatching %d onLosing callbacks in %dms, expected %dms", - NUM_REQUESTS, onLostDispatchingDuration, SWITCH_TIME_LIMIT_MS), - onLostDispatchingDuration <= SWITCH_TIME_LIMIT_MS); - - assertRunsInAtMost("Unregistering callbacks", UNREGISTER_TIME_LIMIT_MS, () -> { - for (NetworkCallback cb : callbacks) { - mCm.unregisterNetworkCallback(cb); - } - }); - } - - @Test - public void testMobileDataAlwaysOn() throws Exception { - grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid()); - final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); - final NetworkRequest cellRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR).build(); - mCm.registerNetworkCallback(cellRequest, cellNetworkCallback); - - final HandlerThread handlerThread = new HandlerThread("MobileDataAlwaysOnFactory"); - handlerThread.start(); - NetworkCapabilities filter = new NetworkCapabilities() - .addTransportType(TRANSPORT_CELLULAR) - .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) - .addCapability(NET_CAPABILITY_INTERNET); - final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), - mServiceContext, "testFactory", filter, mCsHandlerThread); - testFactory.setScoreFilter(40); - - // Register the factory and expect it to start looking for a network. - testFactory.register(); - - try { - // Expect the factory to receive the default network request. - testFactory.expectRequestAdd(); - testFactory.assertRequestCountEquals(1); - assertTrue(testFactory.getMyStartRequested()); - - // Bring up wifi. The factory stops looking for a network. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - // Score 60 - 40 penalty for not validated yet, then 60 when it validates - mWiFiNetworkAgent.connect(true); - // The network connects with a low score, so the offer can still beat it and - // nothing happens. Then the network validates, and the offer with its filter score - // of 40 can no longer beat it and the request is removed. - testFactory.expectRequestRemove(); - testFactory.assertRequestCountEquals(0); - - assertFalse(testFactory.getMyStartRequested()); - - // Turn on mobile data always on. This request will not match the wifi request, so - // it will be sent to the test factory whose filters allow to see it. - setAlwaysOnNetworks(true); - testFactory.expectRequestAdd(); - testFactory.assertRequestCountEquals(1); - - assertTrue(testFactory.getMyStartRequested()); - - // Bring up cell data and check that the factory stops looking. - assertLength(1, mCm.getAllNetworks()); - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(false); - cellNetworkCallback.expectAvailableCallbacks(mCellNetworkAgent, false, false, false, - TEST_CALLBACK_TIMEOUT_MS); - // When cell connects, it will satisfy the "mobile always on request" right away - // by virtue of being the only network that can satisfy the request. However, its - // score is low (50 - 40 = 10) so the test factory can still hope to beat it. - expectNoRequestChanged(testFactory); - - // Next, cell validates. This gives it a score of 50 and the test factory can't - // hope to beat that according to its filters. It will see the message that its - // offer is now unnecessary. - mCellNetworkAgent.setNetworkValid(true); - // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is - // validated – see testPartialConnectivity. - mCm.reportNetworkConnectivity(mCellNetworkAgent.getNetwork(), true); - cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent); - testFactory.expectRequestRemove(); - testFactory.assertRequestCountEquals(0); - // Accordingly, the factory shouldn't be started. - assertFalse(testFactory.getMyStartRequested()); - - // Check that cell data stays up. - waitForIdle(); - verifyActiveNetwork(TRANSPORT_WIFI); - assertLength(2, mCm.getAllNetworks()); - - // Cell disconnects. There is still the "mobile data always on" request outstanding, - // and the test factory should see it now that it isn't hopelessly outscored. - mCellNetworkAgent.disconnect(); - cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - assertLength(1, mCm.getAllNetworks()); - testFactory.expectRequestAdd(); - testFactory.assertRequestCountEquals(1); - - // Reconnect cell validated, see the request disappear again. Then withdraw the - // mobile always on request. This will tear down cell, and there shouldn't be a - // blip where the test factory briefly sees the request or anything. - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - assertLength(2, mCm.getAllNetworks()); - testFactory.expectRequestRemove(); - testFactory.assertRequestCountEquals(0); - setAlwaysOnNetworks(false); - expectNoRequestChanged(testFactory); - testFactory.assertRequestCountEquals(0); - assertFalse(testFactory.getMyStartRequested()); - // ... and cell data to be torn down immediately since it is no longer nascent. - cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - waitForIdle(); - assertLength(1, mCm.getAllNetworks()); - } finally { - testFactory.terminate(); - mCm.unregisterNetworkCallback(cellNetworkCallback); - handlerThread.quit(); - } - } - - @Test - public void testAvoidBadWifiSetting() throws Exception { - final ContentResolver cr = mServiceContext.getContentResolver(); - final String settingName = ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI; - - mPolicyTracker.mConfigRestrictsAvoidBadWifi = false; - String[] values = new String[] {null, "0", "1"}; - for (int i = 0; i < values.length; i++) { - Settings.Global.putInt(cr, settingName, 1); - mPolicyTracker.reevaluate(); - waitForIdle(); - String msg = String.format("config=false, setting=%s", values[i]); - assertTrue(mService.avoidBadWifi()); - assertFalse(msg, mPolicyTracker.shouldNotifyWifiUnvalidated()); - } - - mPolicyTracker.mConfigRestrictsAvoidBadWifi = true; - - Settings.Global.putInt(cr, settingName, 0); - mPolicyTracker.reevaluate(); - waitForIdle(); - assertFalse(mService.avoidBadWifi()); - assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated()); - - Settings.Global.putInt(cr, settingName, 1); - mPolicyTracker.reevaluate(); - waitForIdle(); - assertTrue(mService.avoidBadWifi()); - assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated()); - - Settings.Global.putString(cr, settingName, null); - mPolicyTracker.reevaluate(); - waitForIdle(); - assertFalse(mService.avoidBadWifi()); - assertTrue(mPolicyTracker.shouldNotifyWifiUnvalidated()); - } - - @Ignore("Refactoring in progress b/178071397") - @Test - public void testAvoidBadWifi() throws Exception { - final ContentResolver cr = mServiceContext.getContentResolver(); - - // Pretend we're on a carrier that restricts switching away from bad wifi. - mPolicyTracker.mConfigRestrictsAvoidBadWifi = true; - - // File a request for cell to ensure it doesn't go down. - final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); - final NetworkRequest cellRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR).build(); - mCm.requestNetwork(cellRequest, cellNetworkCallback); - - TestNetworkCallback defaultCallback = new TestNetworkCallback(); - mCm.registerDefaultNetworkCallback(defaultCallback); - - NetworkRequest validatedWifiRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_WIFI) - .addCapability(NET_CAPABILITY_VALIDATED) - .build(); - TestNetworkCallback validatedWifiCallback = new TestNetworkCallback(); - mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback); - - Settings.Global.putInt(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, 0); - mPolicyTracker.reevaluate(); - - // Bring up validated cell. - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - Network cellNetwork = mCellNetworkAgent.getNetwork(); - - // Bring up validated wifi. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true); - defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); - validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); - Network wifiNetwork = mWiFiNetworkAgent.getNetwork(); - - // Fail validation on wifi. - mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */); - mCm.reportNetworkConnectivity(wifiNetwork, false); - defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); - validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - - // Because avoid bad wifi is off, we don't switch to cellular. - defaultCallback.assertNoCallback(); - assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability( - NET_CAPABILITY_VALIDATED)); - assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability( - NET_CAPABILITY_VALIDATED)); - assertEquals(mCm.getActiveNetwork(), wifiNetwork); - - // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect - // that we switch back to cell. - mPolicyTracker.mConfigRestrictsAvoidBadWifi = false; - mPolicyTracker.reevaluate(); - defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); - assertEquals(mCm.getActiveNetwork(), cellNetwork); - - // Switch back to a restrictive carrier. - mPolicyTracker.mConfigRestrictsAvoidBadWifi = true; - mPolicyTracker.reevaluate(); - defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - assertEquals(mCm.getActiveNetwork(), wifiNetwork); - - // Simulate the user selecting "switch" on the dialog, and check that we switch to cell. - mCm.setAvoidUnvalidated(wifiNetwork); - defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); - assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability( - NET_CAPABILITY_VALIDATED)); - assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability( - NET_CAPABILITY_VALIDATED)); - assertEquals(mCm.getActiveNetwork(), cellNetwork); - - // Disconnect and reconnect wifi to clear the one-time switch above. - mWiFiNetworkAgent.disconnect(); - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true); - defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); - validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); - wifiNetwork = mWiFiNetworkAgent.getNetwork(); - - // Fail validation on wifi and expect the dialog to appear. - mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */); - mCm.reportNetworkConnectivity(wifiNetwork, false); - defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); - validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - - // Simulate the user selecting "switch" and checking the don't ask again checkbox. - Settings.Global.putInt(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, 1); - mPolicyTracker.reevaluate(); - - // We now switch to cell. - defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); - assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability( - NET_CAPABILITY_VALIDATED)); - assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability( - NET_CAPABILITY_VALIDATED)); - assertEquals(mCm.getActiveNetwork(), cellNetwork); - - // Simulate the user turning the cellular fallback setting off and then on. - // We switch to wifi and then to cell. - Settings.Global.putString(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, null); - mPolicyTracker.reevaluate(); - defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - assertEquals(mCm.getActiveNetwork(), wifiNetwork); - Settings.Global.putInt(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, 1); - mPolicyTracker.reevaluate(); - defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); - assertEquals(mCm.getActiveNetwork(), cellNetwork); - - // If cell goes down, we switch to wifi. - mCellNetworkAgent.disconnect(); - defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - validatedWifiCallback.assertNoCallback(); - - mCm.unregisterNetworkCallback(cellNetworkCallback); - mCm.unregisterNetworkCallback(validatedWifiCallback); - mCm.unregisterNetworkCallback(defaultCallback); - } - - @Test - public void testMeteredMultipathPreferenceSetting() throws Exception { - final ContentResolver cr = mServiceContext.getContentResolver(); - final String settingName = ConnectivitySettingsManager.NETWORK_METERED_MULTIPATH_PREFERENCE; - - for (int config : Arrays.asList(0, 3, 2)) { - for (String setting: Arrays.asList(null, "0", "2", "1")) { - mPolicyTracker.mConfigMeteredMultipathPreference = config; - Settings.Global.putString(cr, settingName, setting); - mPolicyTracker.reevaluate(); - waitForIdle(); - - final int expected = (setting != null) ? Integer.parseInt(setting) : config; - String msg = String.format("config=%d, setting=%s", config, setting); - assertEquals(msg, expected, mCm.getMultipathPreference(null)); - } - } - } - - /** - * Validate that a satisfied network request does not trigger onUnavailable() once the - * time-out period expires. - */ - @Test - public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() throws Exception { - NetworkRequest nr = new NetworkRequest.Builder().addTransportType( - NetworkCapabilities.TRANSPORT_WIFI).build(); - final TestNetworkCallback networkCallback = new TestNetworkCallback(); - mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS); - - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); - networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false, - TEST_CALLBACK_TIMEOUT_MS); - - // pass timeout and validate that UNAVAILABLE is not called - networkCallback.assertNoCallback(); - } - - /** - * Validate that a satisfied network request followed by a disconnected (lost) network does - * not trigger onUnavailable() once the time-out period expires. - */ - @Test - public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() throws Exception { - NetworkRequest nr = new NetworkRequest.Builder().addTransportType( - NetworkCapabilities.TRANSPORT_WIFI).build(); - final TestNetworkCallback networkCallback = new TestNetworkCallback(); - mCm.requestNetwork(nr, networkCallback, TEST_REQUEST_TIMEOUT_MS); - - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); - networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false, - TEST_CALLBACK_TIMEOUT_MS); - mWiFiNetworkAgent.disconnect(); - networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - - // Validate that UNAVAILABLE is not called - networkCallback.assertNoCallback(); - } - - /** - * Validate that when a time-out is specified for a network request the onUnavailable() - * callback is called when time-out expires. Then validate that if network request is - * (somehow) satisfied - the callback isn't called later. - */ - @Test - public void testTimedoutNetworkRequest() throws Exception { - NetworkRequest nr = new NetworkRequest.Builder().addTransportType( - NetworkCapabilities.TRANSPORT_WIFI).build(); - final TestNetworkCallback networkCallback = new TestNetworkCallback(); - final int timeoutMs = 10; - mCm.requestNetwork(nr, networkCallback, timeoutMs); - - // pass timeout and validate that UNAVAILABLE is called - networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, (Network) null); - - // create a network satisfying request - validate that request not triggered - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); - networkCallback.assertNoCallback(); - } - - /** - * Validate that when a network request is unregistered (cancelled), no posterior event can - * trigger the callback. - */ - @Test - public void testNoCallbackAfterUnregisteredNetworkRequest() throws Exception { - NetworkRequest nr = new NetworkRequest.Builder().addTransportType( - NetworkCapabilities.TRANSPORT_WIFI).build(); - final TestNetworkCallback networkCallback = new TestNetworkCallback(); - final int timeoutMs = 10; - - mCm.requestNetwork(nr, networkCallback, timeoutMs); - mCm.unregisterNetworkCallback(networkCallback); - // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures - // that this callback will not be called. - networkCallback.assertNoCallback(); - - // create a network satisfying request - validate that request not triggered - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); - networkCallback.assertNoCallback(); - } - - @Test - public void testUnfulfillableNetworkRequest() throws Exception { - runUnfulfillableNetworkRequest(false); - } - - @Test - public void testUnfulfillableNetworkRequestAfterUnregister() throws Exception { - runUnfulfillableNetworkRequest(true); - } - - /** - * Validate the callback flow for a factory releasing a request as unfulfillable. - */ - private void runUnfulfillableNetworkRequest(boolean preUnregister) throws Exception { - NetworkRequest nr = new NetworkRequest.Builder().addTransportType( - NetworkCapabilities.TRANSPORT_WIFI).build(); - final TestNetworkCallback networkCallback = new TestNetworkCallback(); - - final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest"); - handlerThread.start(); - NetworkCapabilities filter = new NetworkCapabilities() - .addTransportType(TRANSPORT_WIFI) - .addCapability(NET_CAPABILITY_INTERNET) - .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); - final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), - mServiceContext, "testFactory", filter, mCsHandlerThread); - testFactory.setScoreFilter(40); - - // Register the factory and expect it to receive the default request. - testFactory.register(); - testFactory.expectRequestAdd(); - - try { - // Now file the test request and expect it. - mCm.requestNetwork(nr, networkCallback); - final NetworkRequest newRequest = testFactory.expectRequestAdd().request; - - if (preUnregister) { - mCm.unregisterNetworkCallback(networkCallback); - - // The request has been released : the factory should see it removed - // immediately. - testFactory.expectRequestRemove(); - - // Simulate the factory releasing the request as unfulfillable: no-op since - // the callback has already been unregistered (but a test that no exceptions are - // thrown). - testFactory.triggerUnfulfillable(newRequest); - } else { - // Simulate the factory releasing the request as unfulfillable and expect - // onUnavailable! - testFactory.triggerUnfulfillable(newRequest); - - networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, (Network) null); - - // Declaring a request unfulfillable releases it automatically. - testFactory.expectRequestRemove(); - - // unregister network callback - a no-op (since already freed by the - // on-unavailable), but should not fail or throw exceptions. - mCm.unregisterNetworkCallback(networkCallback); - - // The factory should not see any further removal, as this request has - // already been removed. - } - } finally { - testFactory.terminate(); - handlerThread.quit(); - } - } - - private static class TestKeepaliveCallback extends PacketKeepaliveCallback { - - public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR } - - private class CallbackValue { - public CallbackType callbackType; - public int error; - - public CallbackValue(CallbackType type) { - this.callbackType = type; - this.error = PacketKeepalive.SUCCESS; - assertTrue("onError callback must have error", type != CallbackType.ON_ERROR); - } - - public CallbackValue(CallbackType type, int error) { - this.callbackType = type; - this.error = error; - assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR); - } - - @Override - public boolean equals(Object o) { - return o instanceof CallbackValue && - this.callbackType == ((CallbackValue) o).callbackType && - this.error == ((CallbackValue) o).error; - } - - @Override - public String toString() { - return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error); - } - } - - private final LinkedBlockingQueue mCallbacks = new LinkedBlockingQueue<>(); - - @Override - public void onStarted() { - mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED)); - } - - @Override - public void onStopped() { - mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED)); - } - - @Override - public void onError(int error) { - mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error)); - } - - private void expectCallback(CallbackValue callbackValue) throws InterruptedException { - assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - } - - public void expectStarted() throws Exception { - expectCallback(new CallbackValue(CallbackType.ON_STARTED)); - } - - public void expectStopped() throws Exception { - expectCallback(new CallbackValue(CallbackType.ON_STOPPED)); - } - - public void expectError(int error) throws Exception { - expectCallback(new CallbackValue(CallbackType.ON_ERROR, error)); - } - } - - private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback { - - public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }; - - private class CallbackValue { - public CallbackType callbackType; - public int error; - - CallbackValue(CallbackType type) { - this.callbackType = type; - this.error = SocketKeepalive.SUCCESS; - assertTrue("onError callback must have error", type != CallbackType.ON_ERROR); - } - - CallbackValue(CallbackType type, int error) { - this.callbackType = type; - this.error = error; - assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR); - } - - @Override - public boolean equals(Object o) { - return o instanceof CallbackValue - && this.callbackType == ((CallbackValue) o).callbackType - && this.error == ((CallbackValue) o).error; - } - - @Override - public String toString() { - return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, - error); - } - } - - private LinkedBlockingQueue mCallbacks = new LinkedBlockingQueue<>(); - private final Executor mExecutor; - - TestSocketKeepaliveCallback(@NonNull Executor executor) { - mExecutor = executor; - } - - @Override - public void onStarted() { - mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED)); - } - - @Override - public void onStopped() { - mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED)); - } - - @Override - public void onError(int error) { - mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error)); - } - - private void expectCallback(CallbackValue callbackValue) throws InterruptedException { - assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - - } - - public void expectStarted() throws InterruptedException { - expectCallback(new CallbackValue(CallbackType.ON_STARTED)); - } - - public void expectStopped() throws InterruptedException { - expectCallback(new CallbackValue(CallbackType.ON_STOPPED)); - } - - public void expectError(int error) throws InterruptedException { - expectCallback(new CallbackValue(CallbackType.ON_ERROR, error)); - } - - public void assertNoCallback() { - waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS); - CallbackValue cv = mCallbacks.peek(); - assertNull("Unexpected callback: " + cv, cv); - } - } - - private Network connectKeepaliveNetwork(LinkProperties lp) throws Exception { - // Ensure the network is disconnected before anything else occurs - if (mWiFiNetworkAgent != null) { - assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork())); - } - - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED); - mWiFiNetworkAgent.connect(true); - b.expectBroadcast(); - verifyActiveNetwork(TRANSPORT_WIFI); - mWiFiNetworkAgent.sendLinkProperties(lp); - waitForIdle(); - return mWiFiNetworkAgent.getNetwork(); - } - - @Test - public void testPacketKeepalives() throws Exception { - InetAddress myIPv4 = InetAddress.getByName("192.0.2.129"); - InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35"); - InetAddress myIPv6 = InetAddress.getByName("2001:db8::1"); - InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8"); - InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888"); - - final int validKaInterval = 15; - final int invalidKaInterval = 9; - - LinkProperties lp = new LinkProperties(); - lp.setInterfaceName("wlan12"); - lp.addLinkAddress(new LinkAddress(myIPv6, 64)); - lp.addLinkAddress(new LinkAddress(myIPv4, 25)); - lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234"))); - lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254"))); - - Network notMyNet = new Network(61234); - Network myNet = connectKeepaliveNetwork(lp); - - TestKeepaliveCallback callback = new TestKeepaliveCallback(); - PacketKeepalive ka; - - // Attempt to start keepalives with invalid parameters and check for errors. - ka = mCm.startNattKeepalive(notMyNet, validKaInterval, callback, myIPv4, 1234, dstIPv4); - callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK); - - ka = mCm.startNattKeepalive(myNet, invalidKaInterval, callback, myIPv4, 1234, dstIPv4); - callback.expectError(PacketKeepalive.ERROR_INVALID_INTERVAL); - - ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 1234, dstIPv6); - callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); - - ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv4); - callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); - - // NAT-T is only supported for IPv4. - ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv6, 1234, dstIPv6); - callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); - - ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4); - callback.expectError(PacketKeepalive.ERROR_INVALID_PORT); - - ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 123456, dstIPv4); - callback.expectError(PacketKeepalive.ERROR_INVALID_PORT); - - ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4); - callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED); - - ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4); - callback.expectError(PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED); - - // Check that a started keepalive can be stopped. - mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS); - ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4); - callback.expectStarted(); - mWiFiNetworkAgent.setStopKeepaliveEvent(PacketKeepalive.SUCCESS); - ka.stop(); - callback.expectStopped(); - - // Check that deleting the IP address stops the keepalive. - LinkProperties bogusLp = new LinkProperties(lp); - ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4); - callback.expectStarted(); - bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25)); - bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25)); - mWiFiNetworkAgent.sendLinkProperties(bogusLp); - callback.expectError(PacketKeepalive.ERROR_INVALID_IP_ADDRESS); - mWiFiNetworkAgent.sendLinkProperties(lp); - - // Check that a started keepalive is stopped correctly when the network disconnects. - ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4); - callback.expectStarted(); - mWiFiNetworkAgent.disconnect(); - mWiFiNetworkAgent.expectDisconnected(); - callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK); - - // ... and that stopping it after that has no adverse effects. - waitForIdle(); - final Network myNetAlias = myNet; - assertNull(mCm.getNetworkCapabilities(myNetAlias)); - ka.stop(); - - // Reconnect. - myNet = connectKeepaliveNetwork(lp); - mWiFiNetworkAgent.setStartKeepaliveEvent(PacketKeepalive.SUCCESS); - - // Check that keepalive slots start from 1 and increment. The first one gets slot 1. - mWiFiNetworkAgent.setExpectedKeepaliveSlot(1); - ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4); - callback.expectStarted(); - - // The second one gets slot 2. - mWiFiNetworkAgent.setExpectedKeepaliveSlot(2); - TestKeepaliveCallback callback2 = new TestKeepaliveCallback(); - PacketKeepalive ka2 = mCm.startNattKeepalive( - myNet, validKaInterval, callback2, myIPv4, 6789, dstIPv4); - callback2.expectStarted(); - - // Now stop the first one and create a third. This also gets slot 1. - ka.stop(); - callback.expectStopped(); - - mWiFiNetworkAgent.setExpectedKeepaliveSlot(1); - TestKeepaliveCallback callback3 = new TestKeepaliveCallback(); - PacketKeepalive ka3 = mCm.startNattKeepalive( - myNet, validKaInterval, callback3, myIPv4, 9876, dstIPv4); - callback3.expectStarted(); - - ka2.stop(); - callback2.expectStopped(); - - ka3.stop(); - callback3.expectStopped(); - } - - // Helper method to prepare the executor and run test - private void runTestWithSerialExecutors(ExceptionUtils.ThrowingConsumer functor) - throws Exception { - final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor(); - final Executor executorInline = (Runnable r) -> r.run(); - functor.accept(executorSingleThread); - executorSingleThread.shutdown(); - functor.accept(executorInline); - } - - @Test - public void testNattSocketKeepalives() throws Exception { - runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor)); - runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor)); - } - - private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception { - // TODO: 1. Move this outside of ConnectivityServiceTest. - // 2. Make test to verify that Nat-T keepalive socket is created by IpSecService. - // 3. Mock ipsec service. - final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129"); - final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35"); - final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1"); - final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8"); - final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888"); - - final int validKaInterval = 15; - final int invalidKaInterval = 9; - - final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE); - final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket(); - final int srcPort = testSocket.getPort(); - - LinkProperties lp = new LinkProperties(); - lp.setInterfaceName("wlan12"); - lp.addLinkAddress(new LinkAddress(myIPv6, 64)); - lp.addLinkAddress(new LinkAddress(myIPv4, 25)); - lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234"))); - lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254"))); - - Network notMyNet = new Network(61234); - Network myNet = connectKeepaliveNetwork(lp); - - TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor); - - // Attempt to start keepalives with invalid parameters and check for errors. - // Invalid network. - try (SocketKeepalive ka = mCm.createSocketKeepalive( - notMyNet, testSocket, myIPv4, dstIPv4, executor, callback)) { - ka.start(validKaInterval); - callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK); - } - - // Invalid interval. - try (SocketKeepalive ka = mCm.createSocketKeepalive( - myNet, testSocket, myIPv4, dstIPv4, executor, callback)) { - ka.start(invalidKaInterval); - callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL); - } - - // Invalid destination. - try (SocketKeepalive ka = mCm.createSocketKeepalive( - myNet, testSocket, myIPv4, dstIPv6, executor, callback)) { - ka.start(validKaInterval); - callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS); - } - - // Invalid source; - try (SocketKeepalive ka = mCm.createSocketKeepalive( - myNet, testSocket, myIPv6, dstIPv4, executor, callback)) { - ka.start(validKaInterval); - callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS); - } - - // NAT-T is only supported for IPv4. - try (SocketKeepalive ka = mCm.createSocketKeepalive( - myNet, testSocket, myIPv6, dstIPv6, executor, callback)) { - ka.start(validKaInterval); - callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS); - } - - // Basic check before testing started keepalive. - try (SocketKeepalive ka = mCm.createSocketKeepalive( - myNet, testSocket, myIPv4, dstIPv4, executor, callback)) { - ka.start(validKaInterval); - callback.expectError(SocketKeepalive.ERROR_UNSUPPORTED); - } - - // Check that a started keepalive can be stopped. - mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS); - try (SocketKeepalive ka = mCm.createSocketKeepalive( - myNet, testSocket, myIPv4, dstIPv4, executor, callback)) { - ka.start(validKaInterval); - callback.expectStarted(); - mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS); - ka.stop(); - callback.expectStopped(); - - // Check that keepalive could be restarted. - ka.start(validKaInterval); - callback.expectStarted(); - ka.stop(); - callback.expectStopped(); - - // Check that keepalive can be restarted without waiting for callback. - ka.start(validKaInterval); - callback.expectStarted(); - ka.stop(); - ka.start(validKaInterval); - callback.expectStopped(); - callback.expectStarted(); - ka.stop(); - callback.expectStopped(); - } - - // Check that deleting the IP address stops the keepalive. - LinkProperties bogusLp = new LinkProperties(lp); - try (SocketKeepalive ka = mCm.createSocketKeepalive( - myNet, testSocket, myIPv4, dstIPv4, executor, callback)) { - ka.start(validKaInterval); - callback.expectStarted(); - bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25)); - bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25)); - mWiFiNetworkAgent.sendLinkProperties(bogusLp); - callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS); - mWiFiNetworkAgent.sendLinkProperties(lp); - } - - // Check that a started keepalive is stopped correctly when the network disconnects. - try (SocketKeepalive ka = mCm.createSocketKeepalive( - myNet, testSocket, myIPv4, dstIPv4, executor, callback)) { - ka.start(validKaInterval); - callback.expectStarted(); - mWiFiNetworkAgent.disconnect(); - mWiFiNetworkAgent.expectDisconnected(); - callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK); - - // ... and that stopping it after that has no adverse effects. - waitForIdle(); - final Network myNetAlias = myNet; - assertNull(mCm.getNetworkCapabilities(myNetAlias)); - ka.stop(); - callback.assertNoCallback(); - } - - // Reconnect. - myNet = connectKeepaliveNetwork(lp); - mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS); - - // Check that a stop followed by network disconnects does not result in crash. - try (SocketKeepalive ka = mCm.createSocketKeepalive( - myNet, testSocket, myIPv4, dstIPv4, executor, callback)) { - ka.start(validKaInterval); - callback.expectStarted(); - // Delay the response of keepalive events in networkAgent long enough to make sure - // the follow-up network disconnection will be processed first. - mWiFiNetworkAgent.setKeepaliveResponseDelay(3 * TIMEOUT_MS); - ka.stop(); - - // Make sure the stop has been processed. Wait for executor idle is needed to prevent - // flaky since the actual stop call to the service is delegated to executor thread. - waitForIdleSerialExecutor(executor, TIMEOUT_MS); - waitForIdle(); - - mWiFiNetworkAgent.disconnect(); - mWiFiNetworkAgent.expectDisconnected(); - callback.expectStopped(); - callback.assertNoCallback(); - } - - // Reconnect. - waitForIdle(); - myNet = connectKeepaliveNetwork(lp); - mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS); - - // Check that keepalive slots start from 1 and increment. The first one gets slot 1. - mWiFiNetworkAgent.setExpectedKeepaliveSlot(1); - int srcPort2 = 0; - try (SocketKeepalive ka = mCm.createSocketKeepalive( - myNet, testSocket, myIPv4, dstIPv4, executor, callback)) { - ka.start(validKaInterval); - callback.expectStarted(); - - // The second one gets slot 2. - mWiFiNetworkAgent.setExpectedKeepaliveSlot(2); - final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket(); - srcPort2 = testSocket2.getPort(); - TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor); - try (SocketKeepalive ka2 = mCm.createSocketKeepalive( - myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) { - ka2.start(validKaInterval); - callback2.expectStarted(); - - ka.stop(); - callback.expectStopped(); - - ka2.stop(); - callback2.expectStopped(); - - testSocket.close(); - testSocket2.close(); - } - } - - // Check that there is no port leaked after all keepalives and sockets are closed. - // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7. - // assertFalse(isUdpPortInUse(srcPort)); - // assertFalse(isUdpPortInUse(srcPort2)); - - mWiFiNetworkAgent.disconnect(); - mWiFiNetworkAgent.expectDisconnected(); - mWiFiNetworkAgent = null; - } - - @Test - public void testTcpSocketKeepalives() throws Exception { - runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor)); - } - - private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception { - final int srcPortV4 = 12345; - final int srcPortV6 = 23456; - final InetAddress myIPv4 = InetAddress.getByName("127.0.0.1"); - final InetAddress myIPv6 = InetAddress.getByName("::1"); - - final int validKaInterval = 15; - - final LinkProperties lp = new LinkProperties(); - lp.setInterfaceName("wlan12"); - lp.addLinkAddress(new LinkAddress(myIPv6, 64)); - lp.addLinkAddress(new LinkAddress(myIPv4, 25)); - lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234"))); - lp.addRoute(new RouteInfo(InetAddress.getByName("127.0.0.254"))); - - final Network notMyNet = new Network(61234); - final Network myNet = connectKeepaliveNetwork(lp); - - final Socket testSocketV4 = new Socket(); - final Socket testSocketV6 = new Socket(); - - TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor); - - // Attempt to start Tcp keepalives with invalid parameters and check for errors. - // Invalid network. - try (SocketKeepalive ka = mCm.createSocketKeepalive( - notMyNet, testSocketV4, executor, callback)) { - ka.start(validKaInterval); - callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK); - } - - // Invalid Socket (socket is not bound with IPv4 address). - try (SocketKeepalive ka = mCm.createSocketKeepalive( - myNet, testSocketV4, executor, callback)) { - ka.start(validKaInterval); - callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET); - } - - // Invalid Socket (socket is not bound with IPv6 address). - try (SocketKeepalive ka = mCm.createSocketKeepalive( - myNet, testSocketV6, executor, callback)) { - ka.start(validKaInterval); - callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET); - } - - // Bind the socket address - testSocketV4.bind(new InetSocketAddress(myIPv4, srcPortV4)); - testSocketV6.bind(new InetSocketAddress(myIPv6, srcPortV6)); - - // Invalid Socket (socket is bound with IPv4 address). - try (SocketKeepalive ka = mCm.createSocketKeepalive( - myNet, testSocketV4, executor, callback)) { - ka.start(validKaInterval); - callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET); - } - - // Invalid Socket (socket is bound with IPv6 address). - try (SocketKeepalive ka = mCm.createSocketKeepalive( - myNet, testSocketV6, executor, callback)) { - ka.start(validKaInterval); - callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET); - } - - testSocketV4.close(); - testSocketV6.close(); - - mWiFiNetworkAgent.disconnect(); - mWiFiNetworkAgent.expectDisconnected(); - mWiFiNetworkAgent = null; - } - - private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception { - final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129"); - final InetAddress anyIPv4 = InetAddress.getByName("0.0.0.0"); - final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8"); - final int validKaInterval = 15; - - // Prepare the target network. - LinkProperties lp = new LinkProperties(); - lp.setInterfaceName("wlan12"); - lp.addLinkAddress(new LinkAddress(myIPv4, 25)); - lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254"))); - Network myNet = connectKeepaliveNetwork(lp); - mWiFiNetworkAgent.setStartKeepaliveEvent(SocketKeepalive.SUCCESS); - mWiFiNetworkAgent.setStopKeepaliveEvent(SocketKeepalive.SUCCESS); - - TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor); - - // Prepare the target file descriptor, keep only one instance. - final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE); - final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket(); - final int srcPort = testSocket.getPort(); - final ParcelFileDescriptor testPfd = - ParcelFileDescriptor.dup(testSocket.getFileDescriptor()); - testSocket.close(); - assertTrue(isUdpPortInUse(srcPort)); - - // Start keepalive and explicit make the variable goes out of scope with try-with-resources - // block. - try (SocketKeepalive ka = mCm.createNattKeepalive( - myNet, testPfd, myIPv4, dstIPv4, executor, callback)) { - ka.start(validKaInterval); - callback.expectStarted(); - ka.stop(); - callback.expectStopped(); - } - - // Check that the ParcelFileDescriptor is still valid after keepalive stopped, - // ErrnoException with EBADF will be thrown if the socket is closed when checking local - // address. - assertTrue(isUdpPortInUse(srcPort)); - final InetSocketAddress sa = - (InetSocketAddress) Os.getsockname(testPfd.getFileDescriptor()); - assertEquals(anyIPv4, sa.getAddress()); - - testPfd.close(); - // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7. - // assertFalse(isUdpPortInUse(srcPort)); - - mWiFiNetworkAgent.disconnect(); - mWiFiNetworkAgent.expectDisconnected(); - mWiFiNetworkAgent = null; - } - - private static boolean isUdpPortInUse(int port) { - try (DatagramSocket ignored = new DatagramSocket(port)) { - return false; - } catch (IOException alreadyInUse) { - return true; - } - } - - @Test - public void testGetCaptivePortalServerUrl() throws Exception { - String url = mCm.getCaptivePortalServerUrl(); - assertEquals("http://connectivitycheck.gstatic.com/generate_204", url); - } - - private static class TestNetworkPinner extends NetworkPinner { - public static boolean awaitPin(int timeoutMs) throws InterruptedException { - synchronized(sLock) { - if (sNetwork == null) { - sLock.wait(timeoutMs); - } - return sNetwork != null; - } - } - - public static boolean awaitUnpin(int timeoutMs) throws InterruptedException { - synchronized(sLock) { - if (sNetwork != null) { - sLock.wait(timeoutMs); - } - return sNetwork == null; - } - } - } - - private void assertPinnedToWifiWithCellDefault() { - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess()); - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - } - - private void assertPinnedToWifiWithWifiDefault() { - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess()); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - } - - private void assertNotPinnedToWifi() { - assertNull(mCm.getBoundNetworkForProcess()); - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - } - - @Test - public void testNetworkPinner() throws Exception { - NetworkRequest wifiRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_WIFI) - .build(); - assertNull(mCm.getBoundNetworkForProcess()); - - TestNetworkPinner.pin(mServiceContext, wifiRequest); - assertNull(mCm.getBoundNetworkForProcess()); - - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); - - // When wi-fi connects, expect to be pinned. - assertTrue(TestNetworkPinner.awaitPin(100)); - assertPinnedToWifiWithCellDefault(); - - // Disconnect and expect the pin to drop. - mWiFiNetworkAgent.disconnect(); - assertTrue(TestNetworkPinner.awaitUnpin(100)); - assertNotPinnedToWifi(); - - // Reconnecting does not cause the pin to come back. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); - assertFalse(TestNetworkPinner.awaitPin(100)); - assertNotPinnedToWifi(); - - // Pinning while connected causes the pin to take effect immediately. - TestNetworkPinner.pin(mServiceContext, wifiRequest); - assertTrue(TestNetworkPinner.awaitPin(100)); - assertPinnedToWifiWithCellDefault(); - - // Explicitly unpin and expect to use the default network again. - TestNetworkPinner.unpin(); - assertNotPinnedToWifi(); - - // Disconnect cell and wifi. - ExpectedBroadcast b = registerConnectivityBroadcast(3); // cell down, wifi up, wifi down. - mCellNetworkAgent.disconnect(); - mWiFiNetworkAgent.disconnect(); - b.expectBroadcast(); - - // Pinning takes effect even if the pinned network is the default when the pin is set... - TestNetworkPinner.pin(mServiceContext, wifiRequest); - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); - assertTrue(TestNetworkPinner.awaitPin(100)); - assertPinnedToWifiWithWifiDefault(); - - // ... and is maintained even when that network is no longer the default. - b = registerConnectivityBroadcast(1); - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mCellNetworkAgent.connect(true); - b.expectBroadcast(); - assertPinnedToWifiWithCellDefault(); - } - - @Test - public void testNetworkCallbackMaximum() throws Exception { - final int MAX_REQUESTS = 100; - final int CALLBACKS = 89; - final int INTENTS = 11; - final int SYSTEM_ONLY_MAX_REQUESTS = 250; - assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS); - - NetworkRequest networkRequest = new NetworkRequest.Builder().build(); - ArrayList registered = new ArrayList<>(); - - int j = 0; - while (j++ < CALLBACKS / 2) { - NetworkCallback cb = new NetworkCallback(); - mCm.requestNetwork(networkRequest, cb); - registered.add(cb); - } - while (j++ < CALLBACKS) { - NetworkCallback cb = new NetworkCallback(); - mCm.registerNetworkCallback(networkRequest, cb); - registered.add(cb); - } - j = 0; - while (j++ < INTENTS / 2) { - final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */, - new Intent("a" + j), FLAG_IMMUTABLE); - mCm.requestNetwork(networkRequest, pi); - registered.add(pi); - } - while (j++ < INTENTS) { - final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */, - new Intent("b" + j), FLAG_IMMUTABLE); - mCm.registerNetworkCallback(networkRequest, pi); - registered.add(pi); - } - - // Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added. - assertThrows(TooManyRequestsException.class, () -> - mCm.requestNetwork(networkRequest, new NetworkCallback()) - ); - assertThrows(TooManyRequestsException.class, () -> - mCm.registerNetworkCallback(networkRequest, new NetworkCallback()) - ); - assertThrows(TooManyRequestsException.class, () -> - mCm.requestNetwork(networkRequest, - PendingIntent.getBroadcast(mContext, 0 /* requestCode */, - new Intent("c"), FLAG_IMMUTABLE)) - ); - assertThrows(TooManyRequestsException.class, () -> - mCm.registerNetworkCallback(networkRequest, - PendingIntent.getBroadcast(mContext, 0 /* requestCode */, - new Intent("d"), FLAG_IMMUTABLE)) - ); - - // The system gets another SYSTEM_ONLY_MAX_REQUESTS slots. - final Handler handler = new Handler(ConnectivityThread.getInstanceLooper()); - withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, () -> { - ArrayList systemRegistered = new ArrayList<>(); - for (int i = 0; i < SYSTEM_ONLY_MAX_REQUESTS - 1; i++) { - NetworkCallback cb = new NetworkCallback(); - if (i % 2 == 0) { - mCm.registerDefaultNetworkCallbackForUid(1000000 + i, cb, handler); - } else { - mCm.registerNetworkCallback(networkRequest, cb); - } - systemRegistered.add(cb); - } - waitForIdle(); - - assertThrows(TooManyRequestsException.class, () -> - mCm.registerDefaultNetworkCallbackForUid(1001042, new NetworkCallback(), - handler)); - assertThrows(TooManyRequestsException.class, () -> - mCm.registerNetworkCallback(networkRequest, new NetworkCallback())); - - for (NetworkCallback callback : systemRegistered) { - mCm.unregisterNetworkCallback(callback); - } - waitForIdle(); // Wait for requests to be unregistered before giving up the permission. - }); - - for (Object o : registered) { - if (o instanceof NetworkCallback) { - mCm.unregisterNetworkCallback((NetworkCallback)o); - } - if (o instanceof PendingIntent) { - mCm.unregisterNetworkCallback((PendingIntent)o); - } - } - waitForIdle(); - - // Test that the limit is not hit when MAX_REQUESTS requests are added and removed. - for (int i = 0; i < MAX_REQUESTS; i++) { - NetworkCallback networkCallback = new NetworkCallback(); - mCm.requestNetwork(networkRequest, networkCallback); - mCm.unregisterNetworkCallback(networkCallback); - } - waitForIdle(); - - for (int i = 0; i < MAX_REQUESTS; i++) { - NetworkCallback networkCallback = new NetworkCallback(); - mCm.registerNetworkCallback(networkRequest, networkCallback); - mCm.unregisterNetworkCallback(networkCallback); - } - waitForIdle(); - - for (int i = 0; i < MAX_REQUESTS; i++) { - NetworkCallback networkCallback = new NetworkCallback(); - mCm.registerDefaultNetworkCallback(networkCallback); - mCm.unregisterNetworkCallback(networkCallback); - } - waitForIdle(); - - for (int i = 0; i < MAX_REQUESTS; i++) { - NetworkCallback networkCallback = new NetworkCallback(); - mCm.registerDefaultNetworkCallback(networkCallback); - mCm.unregisterNetworkCallback(networkCallback); - } - waitForIdle(); - - withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, () -> { - for (int i = 0; i < MAX_REQUESTS; i++) { - NetworkCallback networkCallback = new NetworkCallback(); - mCm.registerDefaultNetworkCallbackForUid(1000000 + i, networkCallback, - new Handler(ConnectivityThread.getInstanceLooper())); - mCm.unregisterNetworkCallback(networkCallback); - } - }); - waitForIdle(); - - for (int i = 0; i < MAX_REQUESTS; i++) { - final PendingIntent pendingIntent = PendingIntent.getBroadcast( - mContext, 0 /* requestCode */, new Intent("e" + i), FLAG_IMMUTABLE); - mCm.requestNetwork(networkRequest, pendingIntent); - mCm.unregisterNetworkCallback(pendingIntent); - } - waitForIdle(); - - for (int i = 0; i < MAX_REQUESTS; i++) { - final PendingIntent pendingIntent = PendingIntent.getBroadcast( - mContext, 0 /* requestCode */, new Intent("f" + i), FLAG_IMMUTABLE); - mCm.registerNetworkCallback(networkRequest, pendingIntent); - mCm.unregisterNetworkCallback(pendingIntent); - } - } - - @Test - public void testNetworkInfoOfTypeNone() throws Exception { - ExpectedBroadcast b = registerConnectivityBroadcast(1); - - verifyNoNetwork(); - TestNetworkAgentWrapper wifiAware = new TestNetworkAgentWrapper(TRANSPORT_WIFI_AWARE); - assertNull(mCm.getActiveNetworkInfo()); - - Network[] allNetworks = mCm.getAllNetworks(); - assertLength(1, allNetworks); - Network network = allNetworks[0]; - NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network); - assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE)); - - final NetworkRequest request = - new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build(); - final TestNetworkCallback callback = new TestNetworkCallback(); - mCm.registerNetworkCallback(request, callback); - - // Bring up wifi aware network. - wifiAware.connect(false, false, false /* isStrictMode */); - callback.expectAvailableCallbacksUnvalidated(wifiAware); - - assertNull(mCm.getActiveNetworkInfo()); - assertNull(mCm.getActiveNetwork()); - // TODO: getAllNetworkInfo is dirty and returns a non-empty array right from the start - // of this test. Fix it and uncomment the assert below. - //assertEmpty(mCm.getAllNetworkInfo()); - - // Disconnect wifi aware network. - wifiAware.disconnect(); - callback.expectCallbackThat(TIMEOUT_MS, (info) -> info instanceof CallbackEntry.Lost); - mCm.unregisterNetworkCallback(callback); - - verifyNoNetwork(); - b.expectNoBroadcast(10); - } - - @Test - public void testDeprecatedAndUnsupportedOperations() throws Exception { - final int TYPE_NONE = ConnectivityManager.TYPE_NONE; - assertNull(mCm.getNetworkInfo(TYPE_NONE)); - assertNull(mCm.getNetworkForType(TYPE_NONE)); - assertNull(mCm.getLinkProperties(TYPE_NONE)); - assertFalse(mCm.isNetworkSupported(TYPE_NONE)); - - assertThrows(IllegalArgumentException.class, - () -> mCm.networkCapabilitiesForType(TYPE_NONE)); - - Class unsupported = UnsupportedOperationException.class; - assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_WIFI, "")); - assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_WIFI, "")); - // TODO: let test context have configuration application target sdk version - // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED - assertThrows(unsupported, () -> mCm.startUsingNetworkFeature(TYPE_NONE, "")); - assertThrows(unsupported, () -> mCm.stopUsingNetworkFeature(TYPE_NONE, "")); - assertThrows(unsupported, () -> mCm.requestRouteToHostAddress(TYPE_NONE, null)); - } - - @Test - public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() throws Exception { - final NetworkRequest networkRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_WIFI).build(); - final TestNetworkCallback networkCallback = new TestNetworkCallback(); - mCm.registerNetworkCallback(networkRequest, networkCallback); - - LinkProperties lp = new LinkProperties(); - lp.setInterfaceName(WIFI_IFNAME); - LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24"); - RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null, - InetAddresses.parseNumericAddress("192.168.12.1"), lp.getInterfaceName()); - lp.addLinkAddress(myIpv4Address); - lp.addRoute(myIpv4DefaultRoute); - - // Verify direct routes are added when network agent is first registered in - // ConnectivityService. - TestNetworkAgentWrapper networkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp); - networkAgent.connect(true); - networkCallback.expectCallback(CallbackEntry.AVAILABLE, networkAgent); - networkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, networkAgent); - CallbackEntry.LinkPropertiesChanged cbi = - networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, - networkAgent); - networkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, networkAgent); - networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent); - networkCallback.assertNoCallback(); - checkDirectlyConnectedRoutes(cbi.getLp(), Arrays.asList(myIpv4Address), - Arrays.asList(myIpv4DefaultRoute)); - checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()), - Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute)); - - // Verify direct routes are added during subsequent link properties updates. - LinkProperties newLp = new LinkProperties(lp); - LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64"); - LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64"); - newLp.addLinkAddress(myIpv6Address1); - newLp.addLinkAddress(myIpv6Address2); - networkAgent.sendLinkProperties(newLp); - cbi = networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, networkAgent); - networkCallback.assertNoCallback(); - checkDirectlyConnectedRoutes(cbi.getLp(), - Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2), - Arrays.asList(myIpv4DefaultRoute)); - mCm.unregisterNetworkCallback(networkCallback); - } - - private void expectNotifyNetworkStatus(List networks, String defaultIface, - Integer vpnUid, String vpnIfname, List underlyingIfaces) throws Exception { - ArgumentCaptor> networksCaptor = ArgumentCaptor.forClass(List.class); - ArgumentCaptor> vpnInfosCaptor = - ArgumentCaptor.forClass(List.class); - - verify(mStatsManager, atLeastOnce()).notifyNetworkStatus(networksCaptor.capture(), - any(List.class), eq(defaultIface), vpnInfosCaptor.capture()); - - assertSameElements(networksCaptor.getValue(), networks); - - List infos = vpnInfosCaptor.getValue(); - if (vpnUid != null) { - assertEquals("Should have exactly one VPN:", 1, infos.size()); - UnderlyingNetworkInfo info = infos.get(0); - assertEquals("Unexpected VPN owner:", (int) vpnUid, info.getOwnerUid()); - assertEquals("Unexpected VPN interface:", vpnIfname, info.getInterface()); - assertSameElements(underlyingIfaces, info.getUnderlyingInterfaces()); - } else { - assertEquals(0, infos.size()); - return; - } - } - - private void expectNotifyNetworkStatus( - List networks, String defaultIface) throws Exception { - expectNotifyNetworkStatus(networks, defaultIface, null, null, List.of()); - } - - @Test - public void testStatsIfacesChanged() throws Exception { - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - - final List onlyCell = List.of(mCellNetworkAgent.getNetwork()); - final List onlyWifi = List.of(mWiFiNetworkAgent.getNetwork()); - - LinkProperties cellLp = new LinkProperties(); - cellLp.setInterfaceName(MOBILE_IFNAME); - LinkProperties wifiLp = new LinkProperties(); - wifiLp.setInterfaceName(WIFI_IFNAME); - - // Simple connection should have updated ifaces - mCellNetworkAgent.connect(false); - mCellNetworkAgent.sendLinkProperties(cellLp); - waitForIdle(); - expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME); - reset(mStatsManager); - - // Default network switch should update ifaces. - mWiFiNetworkAgent.connect(false); - mWiFiNetworkAgent.sendLinkProperties(wifiLp); - waitForIdle(); - assertEquals(wifiLp, mService.getActiveLinkProperties()); - expectNotifyNetworkStatus(onlyWifi, WIFI_IFNAME); - reset(mStatsManager); - - // Disconnect should update ifaces. - mWiFiNetworkAgent.disconnect(); - waitForIdle(); - expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME); - reset(mStatsManager); - - // Metered change should update ifaces - mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); - waitForIdle(); - expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME); - reset(mStatsManager); - - mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); - waitForIdle(); - expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME); - reset(mStatsManager); - - // Temp metered change shouldn't update ifaces - mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED); - waitForIdle(); - verify(mStatsManager, never()).notifyNetworkStatus(eq(onlyCell), - any(List.class), eq(MOBILE_IFNAME), any(List.class)); - reset(mStatsManager); - - // Roaming change should update ifaces - mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); - waitForIdle(); - expectNotifyNetworkStatus(onlyCell, MOBILE_IFNAME); - reset(mStatsManager); - - // Test VPNs. - final LinkProperties lp = new LinkProperties(); - lp.setInterfaceName(VPN_IFNAME); - - mMockVpn.establishForMyUid(lp); - assertUidRangesUpdatedForMyUid(true); - - final List cellAndVpn = - List.of(mCellNetworkAgent.getNetwork(), mMockVpn.getNetwork()); - - // A VPN with default (null) underlying networks sets the underlying network's interfaces... - expectNotifyNetworkStatus(cellAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME, - List.of(MOBILE_IFNAME)); - - // ...and updates them as the default network switches. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); - mWiFiNetworkAgent.sendLinkProperties(wifiLp); - final Network[] onlyNull = new Network[]{null}; - final List wifiAndVpn = - List.of(mWiFiNetworkAgent.getNetwork(), mMockVpn.getNetwork()); - final List cellAndWifi = - List.of(mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork()); - final Network[] cellNullAndWifi = - new Network[]{mCellNetworkAgent.getNetwork(), null, mWiFiNetworkAgent.getNetwork()}; - - waitForIdle(); - assertEquals(wifiLp, mService.getActiveLinkProperties()); - expectNotifyNetworkStatus(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME, - List.of(WIFI_IFNAME)); - reset(mStatsManager); - - // A VPN that sets its underlying networks passes the underlying interfaces, and influences - // the default interface sent to NetworkStatsService by virtue of applying to the system - // server UID (or, in this test, to the test's UID). This is the reason for sending - // MOBILE_IFNAME even though the default network is wifi. - // TODO: fix this to pass in the actual default network interface. Whether or not the VPN - // applies to the system server UID should not have any bearing on network stats. - mMockVpn.setUnderlyingNetworks(onlyCell.toArray(new Network[0])); - waitForIdle(); - expectNotifyNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME, - List.of(MOBILE_IFNAME)); - reset(mStatsManager); - - mMockVpn.setUnderlyingNetworks(cellAndWifi.toArray(new Network[0])); - waitForIdle(); - expectNotifyNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME, - List.of(MOBILE_IFNAME, WIFI_IFNAME)); - reset(mStatsManager); - - // Null underlying networks are ignored. - mMockVpn.setUnderlyingNetworks(cellNullAndWifi); - waitForIdle(); - expectNotifyNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME, - List.of(MOBILE_IFNAME, WIFI_IFNAME)); - reset(mStatsManager); - - // If an underlying network disconnects, that interface should no longer be underlying. - // This doesn't actually work because disconnectAndDestroyNetwork only notifies - // NetworkStatsService before the underlying network is actually removed. So the underlying - // network will only be removed if notifyIfacesChangedForNetworkStats is called again. This - // could result in incorrect data usage measurements if the interface used by the - // disconnected network is reused by a system component that does not register an agent for - // it (e.g., tethering). - mCellNetworkAgent.disconnect(); - waitForIdle(); - assertNull(mService.getLinkProperties(mCellNetworkAgent.getNetwork())); - expectNotifyNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME, - List.of(MOBILE_IFNAME, WIFI_IFNAME)); - - // Confirm that we never tell NetworkStatsService that cell is no longer the underlying - // network for the VPN... - verify(mStatsManager, never()).notifyNetworkStatus(any(List.class), - any(List.class), any() /* anyString() doesn't match null */, - argThat(infos -> infos.get(0).getUnderlyingInterfaces().size() == 1 - && WIFI_IFNAME.equals(infos.get(0).getUnderlyingInterfaces().get(0)))); - verifyNoMoreInteractions(mStatsManager); - reset(mStatsManager); - - // ... but if something else happens that causes notifyIfacesChangedForNetworkStats to be - // called again, it does. For example, connect Ethernet, but with a low score, such that it - // does not become the default network. - mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET); - mEthernetNetworkAgent.setScore( - new NetworkScore.Builder().setLegacyInt(30).setExiting(true).build()); - mEthernetNetworkAgent.connect(false); - waitForIdle(); - verify(mStatsManager).notifyNetworkStatus(any(List.class), - any(List.class), any() /* anyString() doesn't match null */, - argThat(vpnInfos -> vpnInfos.get(0).getUnderlyingInterfaces().size() == 1 - && WIFI_IFNAME.equals(vpnInfos.get(0).getUnderlyingInterfaces().get(0)))); - mEthernetNetworkAgent.disconnect(); - waitForIdle(); - reset(mStatsManager); - - // When a VPN declares no underlying networks (i.e., no connectivity), getAllVpnInfo - // does not return the VPN, so CS does not pass it to NetworkStatsService. This causes - // NetworkStatsFactory#adjustForTunAnd464Xlat not to attempt any VPN data migration, which - // is probably a performance improvement (though it's very unlikely that a VPN would declare - // no underlying networks). - // Also, for the same reason as above, the active interface passed in is null. - mMockVpn.setUnderlyingNetworks(new Network[0]); - waitForIdle(); - expectNotifyNetworkStatus(wifiAndVpn, null); - reset(mStatsManager); - - // Specifying only a null underlying network is the same as no networks. - mMockVpn.setUnderlyingNetworks(onlyNull); - waitForIdle(); - expectNotifyNetworkStatus(wifiAndVpn, null); - reset(mStatsManager); - - // Specifying networks that are all disconnected is the same as specifying no networks. - mMockVpn.setUnderlyingNetworks(onlyCell.toArray(new Network[0])); - waitForIdle(); - expectNotifyNetworkStatus(wifiAndVpn, null); - reset(mStatsManager); - - // Passing in null again means follow the default network again. - mMockVpn.setUnderlyingNetworks(null); - waitForIdle(); - expectNotifyNetworkStatus(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME, - List.of(WIFI_IFNAME)); - reset(mStatsManager); - } - - @Test - public void testBasicDnsConfigurationPushed() throws Exception { - setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com"); - - // Clear any interactions that occur as a result of CS starting up. - reset(mMockDnsResolver); - - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - waitForIdle(); - verify(mMockDnsResolver, never()).setResolverConfiguration(any()); - verifyNoMoreInteractions(mMockDnsResolver); - - final LinkProperties cellLp = new LinkProperties(); - cellLp.setInterfaceName(MOBILE_IFNAME); - // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does - // "is-reachable" testing in order to not program netd with unreachable - // nameservers that it might try repeated to validate. - cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24")); - cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"), - MOBILE_IFNAME)); - cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64")); - cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"), - MOBILE_IFNAME)); - mCellNetworkAgent.sendLinkProperties(cellLp); - mCellNetworkAgent.connect(false); - waitForIdle(); - - verify(mMockDnsResolver, times(1)).createNetworkCache( - eq(mCellNetworkAgent.getNetwork().netId)); - // CS tells dnsresolver about the empty DNS config for this network. - verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any()); - reset(mMockDnsResolver); - - cellLp.addDnsServer(InetAddress.getByName("2001:db8::1")); - mCellNetworkAgent.sendLinkProperties(cellLp); - waitForIdle(); - verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration( - mResolverParamsParcelCaptor.capture()); - ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue(); - assertEquals(1, resolvrParams.servers.length); - assertTrue(ArrayUtils.contains(resolvrParams.servers, "2001:db8::1")); - // Opportunistic mode. - assertTrue(ArrayUtils.contains(resolvrParams.tlsServers, "2001:db8::1")); - reset(mMockDnsResolver); - - cellLp.addDnsServer(InetAddress.getByName("192.0.2.1")); - mCellNetworkAgent.sendLinkProperties(cellLp); - waitForIdle(); - verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration( - mResolverParamsParcelCaptor.capture()); - resolvrParams = mResolverParamsParcelCaptor.getValue(); - assertEquals(2, resolvrParams.servers.length); - assertTrue(ArrayUtils.containsAll(resolvrParams.servers, - new String[]{"2001:db8::1", "192.0.2.1"})); - // Opportunistic mode. - assertEquals(2, resolvrParams.tlsServers.length); - assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers, - new String[]{"2001:db8::1", "192.0.2.1"})); - reset(mMockDnsResolver); - - final String TLS_SPECIFIER = "tls.example.com"; - final String TLS_SERVER6 = "2001:db8:53::53"; - final InetAddress[] TLS_IPS = new InetAddress[]{ InetAddress.getByName(TLS_SERVER6) }; - final String[] TLS_SERVERS = new String[]{ TLS_SERVER6 }; - mCellNetworkAgent.mNmCallbacks.notifyPrivateDnsConfigResolved( - new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel()); - - waitForIdle(); - verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration( - mResolverParamsParcelCaptor.capture()); - resolvrParams = mResolverParamsParcelCaptor.getValue(); - assertEquals(2, resolvrParams.servers.length); - assertTrue(ArrayUtils.containsAll(resolvrParams.servers, - new String[]{"2001:db8::1", "192.0.2.1"})); - reset(mMockDnsResolver); - } - - @Test - public void testDnsConfigurationTransTypesPushed() throws Exception { - // Clear any interactions that occur as a result of CS starting up. - reset(mMockDnsResolver); - - final NetworkRequest request = new NetworkRequest.Builder() - .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET) - .build(); - final TestNetworkCallback callback = new TestNetworkCallback(); - mCm.registerNetworkCallback(request, callback); - - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); - callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - verify(mMockDnsResolver, times(1)).createNetworkCache( - eq(mWiFiNetworkAgent.getNetwork().netId)); - verify(mMockDnsResolver, times(2)).setResolverConfiguration( - mResolverParamsParcelCaptor.capture()); - final ResolverParamsParcel resolverParams = mResolverParamsParcelCaptor.getValue(); - assertContainsExactly(resolverParams.transportTypes, TRANSPORT_WIFI); - reset(mMockDnsResolver); - } - - @Test - public void testPrivateDnsNotification() throws Exception { - NetworkRequest request = new NetworkRequest.Builder() - .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET) - .build(); - TestNetworkCallback callback = new TestNetworkCallback(); - mCm.registerNetworkCallback(request, callback); - // Bring up wifi. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); - callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - // Private DNS resolution failed, checking if the notification will be shown or not. - mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */); - mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid()); - waitForIdle(); - // If network validation failed, NetworkMonitor will re-evaluate the network. - // ConnectivityService should filter the redundant notification. This part is trying to - // simulate that situation and check if ConnectivityService could filter that case. - mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid()); - waitForIdle(); - verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).notify(anyString(), - eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any()); - // If private DNS resolution successful, the PRIVATE_DNS_BROKEN notification shouldn't be - // shown. - mWiFiNetworkAgent.setNetworkValid(true /* isStrictMode */); - mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid()); - waitForIdle(); - verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).cancel(anyString(), - eq(NotificationType.PRIVATE_DNS_BROKEN.eventId)); - // If private DNS resolution failed again, the PRIVATE_DNS_BROKEN notification should be - // shown again. - mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */); - mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid()); - waitForIdle(); - verify(mNotificationManager, timeout(TIMEOUT_MS).times(2)).notify(anyString(), - eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any()); - } - - @Test - public void testPrivateDnsSettingsChange() throws Exception { - // Clear any interactions that occur as a result of CS starting up. - reset(mMockDnsResolver); - - // The default on Android is opportunistic mode ("Automatic"). - setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com"); - - final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); - final NetworkRequest cellRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR).build(); - mCm.requestNetwork(cellRequest, cellNetworkCallback); - - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - waitForIdle(); - // CS tells netd about the empty DNS config for this network. - verify(mMockDnsResolver, never()).setResolverConfiguration(any()); - verifyNoMoreInteractions(mMockDnsResolver); - - final LinkProperties cellLp = new LinkProperties(); - cellLp.setInterfaceName(MOBILE_IFNAME); - // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does - // "is-reachable" testing in order to not program netd with unreachable - // nameservers that it might try repeated to validate. - cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24")); - cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"), - MOBILE_IFNAME)); - cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64")); - cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"), - MOBILE_IFNAME)); - cellLp.addDnsServer(InetAddress.getByName("2001:db8::1")); - cellLp.addDnsServer(InetAddress.getByName("192.0.2.1")); - - mCellNetworkAgent.sendLinkProperties(cellLp); - mCellNetworkAgent.connect(false); - waitForIdle(); - verify(mMockDnsResolver, times(1)).createNetworkCache( - eq(mCellNetworkAgent.getNetwork().netId)); - verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration( - mResolverParamsParcelCaptor.capture()); - ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue(); - assertEquals(2, resolvrParams.tlsServers.length); - assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers, - new String[] { "2001:db8::1", "192.0.2.1" })); - // Opportunistic mode. - assertEquals(2, resolvrParams.tlsServers.length); - assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers, - new String[] { "2001:db8::1", "192.0.2.1" })); - reset(mMockDnsResolver); - cellNetworkCallback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent); - cellNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, - mCellNetworkAgent); - CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback( - CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); - cellNetworkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent); - cellNetworkCallback.assertNoCallback(); - assertFalse(cbi.getLp().isPrivateDnsActive()); - assertNull(cbi.getLp().getPrivateDnsServerName()); - - setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com"); - verify(mMockDnsResolver, times(1)).setResolverConfiguration( - mResolverParamsParcelCaptor.capture()); - resolvrParams = mResolverParamsParcelCaptor.getValue(); - assertEquals(2, resolvrParams.servers.length); - assertTrue(ArrayUtils.containsAll(resolvrParams.servers, - new String[] { "2001:db8::1", "192.0.2.1" })); - reset(mMockDnsResolver); - cellNetworkCallback.assertNoCallback(); - - setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com"); - verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration( - mResolverParamsParcelCaptor.capture()); - resolvrParams = mResolverParamsParcelCaptor.getValue(); - assertEquals(2, resolvrParams.servers.length); - assertTrue(ArrayUtils.containsAll(resolvrParams.servers, - new String[] { "2001:db8::1", "192.0.2.1" })); - assertEquals(2, resolvrParams.tlsServers.length); - assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers, - new String[] { "2001:db8::1", "192.0.2.1" })); - reset(mMockDnsResolver); - cellNetworkCallback.assertNoCallback(); - - setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com"); - // Can't test dns configuration for strict mode without properly mocking - // out the DNS lookups, but can test that LinkProperties is updated. - cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, - mCellNetworkAgent); - cellNetworkCallback.assertNoCallback(); - assertTrue(cbi.getLp().isPrivateDnsActive()); - assertEquals("strict.example.com", cbi.getLp().getPrivateDnsServerName()); - } - - private PrivateDnsValidationEventParcel makePrivateDnsValidationEvent( - final int netId, final String ipAddress, final String hostname, final int validation) { - final PrivateDnsValidationEventParcel event = new PrivateDnsValidationEventParcel(); - event.netId = netId; - event.ipAddress = ipAddress; - event.hostname = hostname; - event.validation = validation; - return event; - } - - @Test - public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception { - // The default on Android is opportunistic mode ("Automatic"). - setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com"); - - final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); - final NetworkRequest cellRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR).build(); - mCm.requestNetwork(cellRequest, cellNetworkCallback); - - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - waitForIdle(); - LinkProperties lp = new LinkProperties(); - mCellNetworkAgent.sendLinkProperties(lp); - mCellNetworkAgent.connect(false); - waitForIdle(); - cellNetworkCallback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent); - cellNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, - mCellNetworkAgent); - CallbackEntry.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback( - CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); - cellNetworkCallback.expectCallback(CallbackEntry.BLOCKED_STATUS, mCellNetworkAgent); - cellNetworkCallback.assertNoCallback(); - assertFalse(cbi.getLp().isPrivateDnsActive()); - assertNull(cbi.getLp().getPrivateDnsServerName()); - Set dnsServers = new HashSet<>(); - checkDnsServers(cbi.getLp(), dnsServers); - - // Send a validation event for a server that is not part of the current - // resolver config. The validation event should be ignored. - mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent( - makePrivateDnsValidationEvent(mCellNetworkAgent.getNetwork().netId, "", - "145.100.185.18", VALIDATION_RESULT_SUCCESS)); - cellNetworkCallback.assertNoCallback(); - - // Add a dns server to the LinkProperties. - LinkProperties lp2 = new LinkProperties(lp); - lp2.addDnsServer(InetAddress.getByName("145.100.185.16")); - mCellNetworkAgent.sendLinkProperties(lp2); - cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, - mCellNetworkAgent); - cellNetworkCallback.assertNoCallback(); - assertFalse(cbi.getLp().isPrivateDnsActive()); - assertNull(cbi.getLp().getPrivateDnsServerName()); - dnsServers.add(InetAddress.getByName("145.100.185.16")); - checkDnsServers(cbi.getLp(), dnsServers); - - // Send a validation event containing a hostname that is not part of - // the current resolver config. The validation event should be ignored. - mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent( - makePrivateDnsValidationEvent(mCellNetworkAgent.getNetwork().netId, - "145.100.185.16", "hostname", VALIDATION_RESULT_SUCCESS)); - cellNetworkCallback.assertNoCallback(); - - // Send a validation event where validation failed. - mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent( - makePrivateDnsValidationEvent(mCellNetworkAgent.getNetwork().netId, - "145.100.185.16", "", VALIDATION_RESULT_FAILURE)); - cellNetworkCallback.assertNoCallback(); - - // Send a validation event where validation succeeded for a server in - // the current resolver config. A LinkProperties callback with updated - // private dns fields should be sent. - mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent( - makePrivateDnsValidationEvent(mCellNetworkAgent.getNetwork().netId, - "145.100.185.16", "", VALIDATION_RESULT_SUCCESS)); - cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, - mCellNetworkAgent); - cellNetworkCallback.assertNoCallback(); - assertTrue(cbi.getLp().isPrivateDnsActive()); - assertNull(cbi.getLp().getPrivateDnsServerName()); - checkDnsServers(cbi.getLp(), dnsServers); - - // The private dns fields in LinkProperties should be preserved when - // the network agent sends unrelated changes. - LinkProperties lp3 = new LinkProperties(lp2); - lp3.setMtu(1300); - mCellNetworkAgent.sendLinkProperties(lp3); - cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, - mCellNetworkAgent); - cellNetworkCallback.assertNoCallback(); - assertTrue(cbi.getLp().isPrivateDnsActive()); - assertNull(cbi.getLp().getPrivateDnsServerName()); - checkDnsServers(cbi.getLp(), dnsServers); - assertEquals(1300, cbi.getLp().getMtu()); - - // Removing the only validated server should affect the private dns - // fields in LinkProperties. - LinkProperties lp4 = new LinkProperties(lp3); - lp4.removeDnsServer(InetAddress.getByName("145.100.185.16")); - mCellNetworkAgent.sendLinkProperties(lp4); - cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, - mCellNetworkAgent); - cellNetworkCallback.assertNoCallback(); - assertFalse(cbi.getLp().isPrivateDnsActive()); - assertNull(cbi.getLp().getPrivateDnsServerName()); - dnsServers.remove(InetAddress.getByName("145.100.185.16")); - checkDnsServers(cbi.getLp(), dnsServers); - assertEquals(1300, cbi.getLp().getMtu()); - } - - private void checkDirectlyConnectedRoutes(Object callbackObj, - Collection linkAddresses, Collection otherRoutes) { - assertTrue(callbackObj instanceof LinkProperties); - LinkProperties lp = (LinkProperties) callbackObj; - - Set expectedRoutes = new ArraySet<>(); - expectedRoutes.addAll(otherRoutes); - for (LinkAddress address : linkAddresses) { - RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName()); - // Duplicates in linkAddresses are considered failures - assertTrue(expectedRoutes.add(localRoute)); - } - List observedRoutes = lp.getRoutes(); - assertEquals(expectedRoutes.size(), observedRoutes.size()); - assertTrue(observedRoutes.containsAll(expectedRoutes)); - } - - private static void checkDnsServers(Object callbackObj, Set dnsServers) { - assertTrue(callbackObj instanceof LinkProperties); - LinkProperties lp = (LinkProperties) callbackObj; - assertEquals(dnsServers.size(), lp.getDnsServers().size()); - assertTrue(lp.getDnsServers().containsAll(dnsServers)); - } - - @Test - public void testApplyUnderlyingCapabilities() throws Exception { - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mCellNetworkAgent.connect(false /* validated */); - mWiFiNetworkAgent.connect(false /* validated */); - - final NetworkCapabilities cellNc = new NetworkCapabilities() - .addTransportType(TRANSPORT_CELLULAR) - .addCapability(NET_CAPABILITY_INTERNET) - .addCapability(NET_CAPABILITY_NOT_CONGESTED) - .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) - .setLinkDownstreamBandwidthKbps(10); - final NetworkCapabilities wifiNc = new NetworkCapabilities() - .addTransportType(TRANSPORT_WIFI) - .addCapability(NET_CAPABILITY_INTERNET) - .addCapability(NET_CAPABILITY_NOT_METERED) - .addCapability(NET_CAPABILITY_NOT_ROAMING) - .addCapability(NET_CAPABILITY_NOT_CONGESTED) - .addCapability(NET_CAPABILITY_NOT_SUSPENDED) - .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) - .setLinkUpstreamBandwidthKbps(20); - mCellNetworkAgent.setNetworkCapabilities(cellNc, true /* sendToConnectivityService */); - mWiFiNetworkAgent.setNetworkCapabilities(wifiNc, true /* sendToConnectivityService */); - waitForIdle(); - - final Network mobile = mCellNetworkAgent.getNetwork(); - final Network wifi = mWiFiNetworkAgent.getNetwork(); - - final NetworkCapabilities initialCaps = new NetworkCapabilities(); - initialCaps.addTransportType(TRANSPORT_VPN); - initialCaps.addCapability(NET_CAPABILITY_INTERNET); - initialCaps.removeCapability(NET_CAPABILITY_NOT_VPN); - - final NetworkCapabilities withNoUnderlying = new NetworkCapabilities(); - withNoUnderlying.addCapability(NET_CAPABILITY_INTERNET); - withNoUnderlying.addCapability(NET_CAPABILITY_NOT_CONGESTED); - withNoUnderlying.addCapability(NET_CAPABILITY_NOT_ROAMING); - withNoUnderlying.addCapability(NET_CAPABILITY_NOT_SUSPENDED); - withNoUnderlying.addTransportType(TRANSPORT_VPN); - withNoUnderlying.removeCapability(NET_CAPABILITY_NOT_VPN); - - final NetworkCapabilities withMobileUnderlying = new NetworkCapabilities(withNoUnderlying); - withMobileUnderlying.addTransportType(TRANSPORT_CELLULAR); - withMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_ROAMING); - withMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_SUSPENDED); - withMobileUnderlying.setLinkDownstreamBandwidthKbps(10); - - final NetworkCapabilities withWifiUnderlying = new NetworkCapabilities(withNoUnderlying); - withWifiUnderlying.addTransportType(TRANSPORT_WIFI); - withWifiUnderlying.addCapability(NET_CAPABILITY_NOT_METERED); - withWifiUnderlying.setLinkUpstreamBandwidthKbps(20); - - final NetworkCapabilities withWifiAndMobileUnderlying = - new NetworkCapabilities(withNoUnderlying); - withWifiAndMobileUnderlying.addTransportType(TRANSPORT_CELLULAR); - withWifiAndMobileUnderlying.addTransportType(TRANSPORT_WIFI); - withWifiAndMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_METERED); - withWifiAndMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_ROAMING); - withWifiAndMobileUnderlying.setLinkDownstreamBandwidthKbps(10); - withWifiAndMobileUnderlying.setLinkUpstreamBandwidthKbps(20); - - final NetworkCapabilities initialCapsNotMetered = new NetworkCapabilities(initialCaps); - initialCapsNotMetered.addCapability(NET_CAPABILITY_NOT_METERED); - - NetworkCapabilities caps = new NetworkCapabilities(initialCaps); - mService.applyUnderlyingCapabilities(new Network[]{}, initialCapsNotMetered, caps); - assertEquals(withNoUnderlying, caps); - - caps = new NetworkCapabilities(initialCaps); - mService.applyUnderlyingCapabilities(new Network[]{null}, initialCapsNotMetered, caps); - assertEquals(withNoUnderlying, caps); - - caps = new NetworkCapabilities(initialCaps); - mService.applyUnderlyingCapabilities(new Network[]{mobile}, initialCapsNotMetered, caps); - assertEquals(withMobileUnderlying, caps); - - mService.applyUnderlyingCapabilities(new Network[]{wifi}, initialCapsNotMetered, caps); - assertEquals(withWifiUnderlying, caps); - - withWifiUnderlying.removeCapability(NET_CAPABILITY_NOT_METERED); - caps = new NetworkCapabilities(initialCaps); - mService.applyUnderlyingCapabilities(new Network[]{wifi}, initialCaps, caps); - assertEquals(withWifiUnderlying, caps); - - caps = new NetworkCapabilities(initialCaps); - mService.applyUnderlyingCapabilities(new Network[]{mobile, wifi}, initialCaps, caps); - assertEquals(withWifiAndMobileUnderlying, caps); - - withWifiUnderlying.addCapability(NET_CAPABILITY_NOT_METERED); - caps = new NetworkCapabilities(initialCaps); - mService.applyUnderlyingCapabilities(new Network[]{null, mobile, null, wifi}, - initialCapsNotMetered, caps); - assertEquals(withWifiAndMobileUnderlying, caps); - - caps = new NetworkCapabilities(initialCaps); - mService.applyUnderlyingCapabilities(new Network[]{null, mobile, null, wifi}, - initialCapsNotMetered, caps); - assertEquals(withWifiAndMobileUnderlying, caps); - - mService.applyUnderlyingCapabilities(null, initialCapsNotMetered, caps); - assertEquals(withWifiUnderlying, caps); - } - - @Test - public void testVpnConnectDisconnectUnderlyingNetwork() throws Exception { - final TestNetworkCallback callback = new TestNetworkCallback(); - final NetworkRequest request = new NetworkRequest.Builder() - .removeCapability(NET_CAPABILITY_NOT_VPN).build(); - - mCm.registerNetworkCallback(request, callback); - - // Bring up a VPN that specifies an underlying network that does not exist yet. - // Note: it's sort of meaningless for a VPN app to declare a network that doesn't exist yet, - // (and doing so is difficult without using reflection) but it's good to test that the code - // behaves approximately correctly. - mMockVpn.establishForMyUid(false, true, false); - assertUidRangesUpdatedForMyUid(true); - final Network wifiNetwork = new Network(mNetIdManager.peekNextNetId()); - mMockVpn.setUnderlyingNetworks(new Network[]{wifiNetwork}); - callback.expectAvailableCallbacksUnvalidated(mMockVpn); - assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork()) - .hasTransport(TRANSPORT_VPN)); - assertFalse(mCm.getNetworkCapabilities(mMockVpn.getNetwork()) - .hasTransport(TRANSPORT_WIFI)); - - // Make that underlying network connect, and expect to see its capabilities immediately - // reflected in the VPN's capabilities. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - assertEquals(wifiNetwork, mWiFiNetworkAgent.getNetwork()); - mWiFiNetworkAgent.connect(false); - // TODO: the callback for the VPN happens before any callbacks are called for the wifi - // network that has just connected. There appear to be two issues here: - // 1. The VPN code will accept an underlying network as soon as getNetworkCapabilities() for - // it returns non-null (which happens very early, during handleRegisterNetworkAgent). - // This is not correct because that that point the network is not connected and cannot - // pass any traffic. - // 2. When a network connects, updateNetworkInfo propagates underlying network capabilities - // before rematching networks. - // Given that this scenario can't really happen, this is probably fine for now. - callback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn); - callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork()) - .hasTransport(TRANSPORT_VPN)); - assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork()) - .hasTransport(TRANSPORT_WIFI)); - - // Disconnect the network, and expect to see the VPN capabilities change accordingly. - mWiFiNetworkAgent.disconnect(); - callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - callback.expectCapabilitiesThat(mMockVpn, (nc) -> - nc.getTransportTypes().length == 1 && nc.hasTransport(TRANSPORT_VPN)); - - mMockVpn.disconnect(); - mCm.unregisterNetworkCallback(callback); - } - - private void assertGetNetworkInfoOfGetActiveNetworkIsConnected(boolean expectedConnectivity) { - // What Chromium used to do before https://chromium-review.googlesource.com/2605304 - assertEquals("Unexpected result for getActiveNetworkInfo(getActiveNetwork())", - expectedConnectivity, mCm.getNetworkInfo(mCm.getActiveNetwork()).isConnected()); - } - - @Test - public void testVpnUnderlyingNetworkSuspended() throws Exception { - final TestNetworkCallback callback = new TestNetworkCallback(); - mCm.registerDefaultNetworkCallback(callback); - - // Connect a VPN. - mMockVpn.establishForMyUid(false /* validated */, true /* hasInternet */, - false /* isStrictMode */); - callback.expectAvailableCallbacksUnvalidated(mMockVpn); - - // Connect cellular data. - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(false /* validated */); - callback.expectCapabilitiesThat(mMockVpn, - nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED) - && nc.hasTransport(TRANSPORT_CELLULAR)); - callback.assertNoCallback(); - - assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork()) - .hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); - assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); - assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED); - assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED); - assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); - assertGetNetworkInfoOfGetActiveNetworkIsConnected(true); - - // Suspend the cellular network and expect the VPN to be suspended. - mCellNetworkAgent.suspend(); - callback.expectCapabilitiesThat(mMockVpn, - nc -> !nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED) - && nc.hasTransport(TRANSPORT_CELLULAR)); - callback.expectCallback(CallbackEntry.SUSPENDED, mMockVpn); - callback.assertNoCallback(); - - assertFalse(mCm.getNetworkCapabilities(mMockVpn.getNetwork()) - .hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); - assertNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED); - assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED); - assertNetworkInfo(TYPE_VPN, DetailedState.SUSPENDED); - assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED); - // VPN's main underlying network is suspended, so no connectivity. - assertGetNetworkInfoOfGetActiveNetworkIsConnected(false); - - // Switch to another network. The VPN should no longer be suspended. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false /* validated */); - callback.expectCapabilitiesThat(mMockVpn, - nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED) - && nc.hasTransport(TRANSPORT_WIFI)); - callback.expectCallback(CallbackEntry.RESUMED, mMockVpn); - callback.assertNoCallback(); - - assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork()) - .hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); - assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); - assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); - assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED); - assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); - assertGetNetworkInfoOfGetActiveNetworkIsConnected(true); - - // Unsuspend cellular and then switch back to it. The VPN remains not suspended. - mCellNetworkAgent.resume(); - callback.assertNoCallback(); - mWiFiNetworkAgent.disconnect(); - callback.expectCapabilitiesThat(mMockVpn, - nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED) - && nc.hasTransport(TRANSPORT_CELLULAR)); - // Spurious double callback? - callback.expectCapabilitiesThat(mMockVpn, - nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED) - && nc.hasTransport(TRANSPORT_CELLULAR)); - callback.assertNoCallback(); - - assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork()) - .hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); - assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); - assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED); - assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED); - assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); - assertGetNetworkInfoOfGetActiveNetworkIsConnected(true); - - // Suspend cellular and expect no connectivity. - mCellNetworkAgent.suspend(); - callback.expectCapabilitiesThat(mMockVpn, - nc -> !nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED) - && nc.hasTransport(TRANSPORT_CELLULAR)); - callback.expectCallback(CallbackEntry.SUSPENDED, mMockVpn); - callback.assertNoCallback(); - - assertFalse(mCm.getNetworkCapabilities(mMockVpn.getNetwork()) - .hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); - assertNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED); - assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED); - assertNetworkInfo(TYPE_VPN, DetailedState.SUSPENDED); - assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.SUSPENDED); - assertGetNetworkInfoOfGetActiveNetworkIsConnected(false); - - // Resume cellular and expect that connectivity comes back. - mCellNetworkAgent.resume(); - callback.expectCapabilitiesThat(mMockVpn, - nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED) - && nc.hasTransport(TRANSPORT_CELLULAR)); - callback.expectCallback(CallbackEntry.RESUMED, mMockVpn); - callback.assertNoCallback(); - - assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork()) - .hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); - assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); - assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED); - assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED); - assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); - assertGetNetworkInfoOfGetActiveNetworkIsConnected(true); - } - - @Test - public void testVpnNetworkActive() throws Exception { - // NETWORK_SETTINGS is necessary to call registerSystemDefaultNetworkCallback. - mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED); - - final int uid = Process.myUid(); - - final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback(); - final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback(); - final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback(); - final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback(); - final TestNetworkCallback defaultCallback = new TestNetworkCallback(); - final TestNetworkCallback systemDefaultCallback = new TestNetworkCallback(); - final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build(); - final NetworkRequest genericRequest = new NetworkRequest.Builder() - .removeCapability(NET_CAPABILITY_NOT_VPN).build(); - final NetworkRequest wifiRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_WIFI).build(); - final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder() - .removeCapability(NET_CAPABILITY_NOT_VPN) - .addTransportType(TRANSPORT_VPN).build(); - mCm.registerNetworkCallback(genericRequest, genericNetworkCallback); - mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback); - mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback); - mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback); - mCm.registerDefaultNetworkCallback(defaultCallback); - mCm.registerSystemDefaultNetworkCallback(systemDefaultCallback, - new Handler(ConnectivityThread.getInstanceLooper())); - defaultCallback.assertNoCallback(); - - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false); - - genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - systemDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - vpnNetworkCallback.assertNoCallback(); - assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - - final Set ranges = uidRangesForUids(uid); - mMockVpn.registerAgent(ranges); - mMockVpn.setUnderlyingNetworks(new Network[0]); - - // VPN networks do not satisfy the default request and are automatically validated - // by NetworkMonitor - assertFalse(NetworkMonitorUtils.isValidationRequired( - mMockVpn.getAgent().getNetworkCapabilities())); - mMockVpn.getAgent().setNetworkValid(false /* isStrictMode */); - - mMockVpn.connect(false); - - genericNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn); - genericNotVpnNetworkCallback.assertNoCallback(); - wifiNetworkCallback.assertNoCallback(); - vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn); - defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn); - systemDefaultCallback.assertNoCallback(); - assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - assertEquals(mWiFiNetworkAgent.getNetwork(), - systemDefaultCallback.getLastAvailableNetwork()); - - ranges.clear(); - mMockVpn.setUids(ranges); - - genericNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn); - genericNotVpnNetworkCallback.assertNoCallback(); - wifiNetworkCallback.assertNoCallback(); - vpnNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn); - - // TODO : The default network callback should actually get a LOST call here (also see the - // comment below for AVAILABLE). This is because ConnectivityService does not look at UID - // ranges at all when determining whether a network should be rematched. In practice, VPNs - // can't currently update their UIDs without disconnecting, so this does not matter too - // much, but that is the reason the test here has to check for an update to the - // capabilities instead of the expected LOST then AVAILABLE. - defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn); - systemDefaultCallback.assertNoCallback(); - - ranges.add(new UidRange(uid, uid)); - mMockVpn.setUids(ranges); - - genericNetworkCallback.expectAvailableCallbacksValidated(mMockVpn); - genericNotVpnNetworkCallback.assertNoCallback(); - wifiNetworkCallback.assertNoCallback(); - vpnNetworkCallback.expectAvailableCallbacksValidated(mMockVpn); - // TODO : Here like above, AVAILABLE would be correct, but because this can't actually - // happen outside of the test, ConnectivityService does not rematch callbacks. - defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn); - systemDefaultCallback.assertNoCallback(); - - mWiFiNetworkAgent.disconnect(); - - genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - genericNotVpnNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - vpnNetworkCallback.assertNoCallback(); - defaultCallback.assertNoCallback(); - systemDefaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - - mMockVpn.disconnect(); - - genericNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn); - genericNotVpnNetworkCallback.assertNoCallback(); - wifiNetworkCallback.assertNoCallback(); - vpnNetworkCallback.expectCallback(CallbackEntry.LOST, mMockVpn); - defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn); - systemDefaultCallback.assertNoCallback(); - assertEquals(null, mCm.getActiveNetwork()); - - mCm.unregisterNetworkCallback(genericNetworkCallback); - mCm.unregisterNetworkCallback(wifiNetworkCallback); - mCm.unregisterNetworkCallback(vpnNetworkCallback); - mCm.unregisterNetworkCallback(defaultCallback); - mCm.unregisterNetworkCallback(systemDefaultCallback); - } - - @Test - public void testVpnWithoutInternet() throws Exception { - final int uid = Process.myUid(); - - final TestNetworkCallback defaultCallback = new TestNetworkCallback(); - mCm.registerDefaultNetworkCallback(defaultCallback); - - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true); - - defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent); - assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - - mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */, - false /* isStrictMode */); - assertUidRangesUpdatedForMyUid(true); - - defaultCallback.assertNoCallback(); - assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - - mMockVpn.disconnect(); - defaultCallback.assertNoCallback(); - - mCm.unregisterNetworkCallback(defaultCallback); - } - - @Test - public void testVpnWithInternet() throws Exception { - final int uid = Process.myUid(); - - final TestNetworkCallback defaultCallback = new TestNetworkCallback(); - mCm.registerDefaultNetworkCallback(defaultCallback); - - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true); - - defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent); - assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - - mMockVpn.establishForMyUid(true /* validated */, true /* hasInternet */, - false /* isStrictMode */); - assertUidRangesUpdatedForMyUid(true); - - defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn); - assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - - mMockVpn.disconnect(); - defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn); - defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent); - - mCm.unregisterNetworkCallback(defaultCallback); - } - - @Test - public void testVpnUnvalidated() throws Exception { - final TestNetworkCallback callback = new TestNetworkCallback(); - mCm.registerDefaultNetworkCallback(callback); - - // Bring up Ethernet. - mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET); - mEthernetNetworkAgent.connect(true); - callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent); - callback.assertNoCallback(); - - // Bring up a VPN that has the INTERNET capability, initially unvalidated. - mMockVpn.establishForMyUid(false /* validated */, true /* hasInternet */, - false /* isStrictMode */); - assertUidRangesUpdatedForMyUid(true); - - // Even though the VPN is unvalidated, it becomes the default network for our app. - callback.expectAvailableCallbacksUnvalidated(mMockVpn); - callback.assertNoCallback(); - - assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork()); - - NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork()); - assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED)); - assertTrue(nc.hasCapability(NET_CAPABILITY_INTERNET)); - - assertFalse(NetworkMonitorUtils.isValidationRequired( - mMockVpn.getAgent().getNetworkCapabilities())); - assertTrue(NetworkMonitorUtils.isPrivateDnsValidationRequired( - mMockVpn.getAgent().getNetworkCapabilities())); - - // Pretend that the VPN network validates. - mMockVpn.getAgent().setNetworkValid(false /* isStrictMode */); - mMockVpn.getAgent().mNetworkMonitor.forceReevaluation(Process.myUid()); - // Expect to see the validated capability, but no other changes, because the VPN is already - // the default network for the app. - callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mMockVpn); - callback.assertNoCallback(); - - mMockVpn.disconnect(); - callback.expectCallback(CallbackEntry.LOST, mMockVpn); - callback.expectAvailableCallbacksValidated(mEthernetNetworkAgent); - } - - @Test - public void testVpnStartsWithUnderlyingCaps() throws Exception { - final int uid = Process.myUid(); - - final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback(); - final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder() - .removeCapability(NET_CAPABILITY_NOT_VPN) - .addTransportType(TRANSPORT_VPN) - .build(); - mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback); - vpnNetworkCallback.assertNoCallback(); - - // Connect cell. It will become the default network, and in the absence of setting - // underlying networks explicitly it will become the sole underlying network for the vpn. - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED); - mCellNetworkAgent.connect(true); - - mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */, - false /* isStrictMode */); - assertUidRangesUpdatedForMyUid(true); - - vpnNetworkCallback.expectAvailableCallbacks(mMockVpn.getNetwork(), - false /* suspended */, false /* validated */, false /* blocked */, TIMEOUT_MS); - vpnNetworkCallback.expectCapabilitiesThat(mMockVpn.getNetwork(), TIMEOUT_MS, - nc -> nc.hasCapability(NET_CAPABILITY_VALIDATED)); - - final NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork()); - assertTrue(nc.hasTransport(TRANSPORT_VPN)); - assertTrue(nc.hasTransport(TRANSPORT_CELLULAR)); - assertFalse(nc.hasTransport(TRANSPORT_WIFI)); - assertTrue(nc.hasCapability(NET_CAPABILITY_VALIDATED)); - assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED)); - assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); - - assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE); - } - - private void assertDefaultNetworkCapabilities(int userId, NetworkAgentWrapper... networks) { - final NetworkCapabilities[] defaultCaps = mService.getDefaultNetworkCapabilitiesForUser( - userId, "com.android.calling.package", "com.test"); - final String defaultCapsString = Arrays.toString(defaultCaps); - assertEquals(defaultCapsString, defaultCaps.length, networks.length); - final Set defaultCapsSet = new ArraySet<>(defaultCaps); - for (NetworkAgentWrapper network : networks) { - final NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork()); - final String msg = "Did not find " + nc + " in " + Arrays.toString(defaultCaps); - assertTrue(msg, defaultCapsSet.contains(nc)); - } - } - - @Test - public void testVpnSetUnderlyingNetworks() throws Exception { - final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback(); - final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder() - .removeCapability(NET_CAPABILITY_NOT_VPN) - .addTransportType(TRANSPORT_VPN) - .build(); - NetworkCapabilities nc; - mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback); - vpnNetworkCallback.assertNoCallback(); - - mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */, - false /* isStrictMode */); - assertUidRangesUpdatedForMyUid(true); - - vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn); - nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork()); - assertTrue(nc.hasTransport(TRANSPORT_VPN)); - assertFalse(nc.hasTransport(TRANSPORT_CELLULAR)); - assertFalse(nc.hasTransport(TRANSPORT_WIFI)); - // For safety reasons a VPN without underlying networks is considered metered. - assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED)); - // A VPN without underlying networks is not suspended. - assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); - assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE); - - final int userId = UserHandle.getUserId(Process.myUid()); - assertDefaultNetworkCapabilities(userId /* no networks */); - - // Connect cell and use it as an underlying network. - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED); - mCellNetworkAgent.connect(true); - - mMockVpn.setUnderlyingNetworks( - new Network[] { mCellNetworkAgent.getNetwork() }); - - vpnNetworkCallback.expectCapabilitiesThat(mMockVpn, - (caps) -> caps.hasTransport(TRANSPORT_VPN) - && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) - && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) - && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); - assertDefaultNetworkCapabilities(userId, mCellNetworkAgent); - - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); - mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED); - mWiFiNetworkAgent.connect(true); - - mMockVpn.setUnderlyingNetworks( - new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() }); - - vpnNetworkCallback.expectCapabilitiesThat(mMockVpn, - (caps) -> caps.hasTransport(TRANSPORT_VPN) - && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) - && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) - && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); - assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent); - - // Don't disconnect, but note the VPN is not using wifi any more. - mMockVpn.setUnderlyingNetworks( - new Network[] { mCellNetworkAgent.getNetwork() }); - - vpnNetworkCallback.expectCapabilitiesThat(mMockVpn, - (caps) -> caps.hasTransport(TRANSPORT_VPN) - && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) - && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) - && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); - // The return value of getDefaultNetworkCapabilitiesForUser always includes the default - // network (wifi) as well as the underlying networks (cell). - assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent); - - // Remove NOT_SUSPENDED from the only network and observe VPN is now suspended. - mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED); - vpnNetworkCallback.expectCapabilitiesThat(mMockVpn, - (caps) -> caps.hasTransport(TRANSPORT_VPN) - && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) - && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) - && !caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); - vpnNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, mMockVpn); - - // Add NOT_SUSPENDED again and observe VPN is no longer suspended. - mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED); - vpnNetworkCallback.expectCapabilitiesThat(mMockVpn, - (caps) -> caps.hasTransport(TRANSPORT_VPN) - && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) - && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) - && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); - vpnNetworkCallback.expectCallback(CallbackEntry.RESUMED, mMockVpn); - - // Use Wifi but not cell. Note the VPN is now unmetered and not suspended. - mMockVpn.setUnderlyingNetworks( - new Network[] { mWiFiNetworkAgent.getNetwork() }); - - vpnNetworkCallback.expectCapabilitiesThat(mMockVpn, - (caps) -> caps.hasTransport(TRANSPORT_VPN) - && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) - && caps.hasCapability(NET_CAPABILITY_NOT_METERED) - && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); - assertDefaultNetworkCapabilities(userId, mWiFiNetworkAgent); - - // Use both again. - mMockVpn.setUnderlyingNetworks( - new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() }); - - vpnNetworkCallback.expectCapabilitiesThat(mMockVpn, - (caps) -> caps.hasTransport(TRANSPORT_VPN) - && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) - && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) - && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); - assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent); - - // Cell is suspended again. As WiFi is not, this should not cause a callback. - mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED); - vpnNetworkCallback.assertNoCallback(); - - // Stop using WiFi. The VPN is suspended again. - mMockVpn.setUnderlyingNetworks( - new Network[] { mCellNetworkAgent.getNetwork() }); - vpnNetworkCallback.expectCapabilitiesThat(mMockVpn, - (caps) -> caps.hasTransport(TRANSPORT_VPN) - && caps.hasTransport(TRANSPORT_CELLULAR) - && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) - && !caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); - vpnNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, mMockVpn); - assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent); - - // Use both again. - mMockVpn.setUnderlyingNetworks( - new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() }); - - vpnNetworkCallback.expectCapabilitiesThat(mMockVpn, - (caps) -> caps.hasTransport(TRANSPORT_VPN) - && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) - && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) - && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); - vpnNetworkCallback.expectCallback(CallbackEntry.RESUMED, mMockVpn); - assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent); - - // Disconnect cell. Receive update without even removing the dead network from the - // underlying networks – it's dead anyway. Not metered any more. - mCellNetworkAgent.disconnect(); - vpnNetworkCallback.expectCapabilitiesThat(mMockVpn, - (caps) -> caps.hasTransport(TRANSPORT_VPN) - && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) - && caps.hasCapability(NET_CAPABILITY_NOT_METERED)); - assertDefaultNetworkCapabilities(userId, mWiFiNetworkAgent); - - // Disconnect wifi too. No underlying networks means this is now metered. - mWiFiNetworkAgent.disconnect(); - vpnNetworkCallback.expectCapabilitiesThat(mMockVpn, - (caps) -> caps.hasTransport(TRANSPORT_VPN) - && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) - && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)); - // When a network disconnects, the callbacks are fired before all state is updated, so for a - // short time, synchronous calls will behave as if the network is still connected. Wait for - // things to settle. - waitForIdle(); - assertDefaultNetworkCapabilities(userId /* no networks */); - - mMockVpn.disconnect(); - } - - @Test - public void testNullUnderlyingNetworks() throws Exception { - final int uid = Process.myUid(); - - final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback(); - final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder() - .removeCapability(NET_CAPABILITY_NOT_VPN) - .addTransportType(TRANSPORT_VPN) - .build(); - NetworkCapabilities nc; - mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback); - vpnNetworkCallback.assertNoCallback(); - - mMockVpn.establishForMyUid(true /* validated */, false /* hasInternet */, - false /* isStrictMode */); - assertUidRangesUpdatedForMyUid(true); - - vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn); - nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork()); - assertTrue(nc.hasTransport(TRANSPORT_VPN)); - assertFalse(nc.hasTransport(TRANSPORT_CELLULAR)); - assertFalse(nc.hasTransport(TRANSPORT_WIFI)); - // By default, VPN is set to track default network (i.e. its underlying networks is null). - // In case of no default network, VPN is considered metered. - assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED)); - assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE); - - // Connect to Cell; Cell is the default network. - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - - vpnNetworkCallback.expectCapabilitiesThat(mMockVpn, - (caps) -> caps.hasTransport(TRANSPORT_VPN) - && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) - && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)); - - // Connect to WiFi; WiFi is the new default. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); - mWiFiNetworkAgent.connect(true); - - vpnNetworkCallback.expectCapabilitiesThat(mMockVpn, - (caps) -> caps.hasTransport(TRANSPORT_VPN) - && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) - && caps.hasCapability(NET_CAPABILITY_NOT_METERED)); - - // Disconnect Cell. The default network did not change, so there shouldn't be any changes in - // the capabilities. - mCellNetworkAgent.disconnect(); - - // Disconnect wifi too. Now we have no default network. - mWiFiNetworkAgent.disconnect(); - - vpnNetworkCallback.expectCapabilitiesThat(mMockVpn, - (caps) -> caps.hasTransport(TRANSPORT_VPN) - && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) - && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)); - - mMockVpn.disconnect(); - } - - @Test - public void testRestrictedProfileAffectsVpnUidRanges() throws Exception { - // NETWORK_SETTINGS is necessary to see the UID ranges in NetworkCapabilities. - mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED); - - final NetworkRequest request = new NetworkRequest.Builder() - .removeCapability(NET_CAPABILITY_NOT_VPN) - .build(); - final TestNetworkCallback callback = new TestNetworkCallback(); - mCm.registerNetworkCallback(request, callback); - - // Bring up a VPN - mMockVpn.establishForMyUid(); - assertUidRangesUpdatedForMyUid(true); - callback.expectAvailableThenValidatedCallbacks(mMockVpn); - callback.assertNoCallback(); - - final int uid = Process.myUid(); - NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork()); - assertNotNull("nc=" + nc, nc.getUids()); - assertEquals(nc.getUids(), UidRange.toIntRanges(uidRangesForUids(uid))); - assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE); - - // Set an underlying network and expect to see the VPN transports change. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true); - callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - callback.expectCapabilitiesThat(mMockVpn, (caps) - -> caps.hasTransport(TRANSPORT_VPN) - && caps.hasTransport(TRANSPORT_WIFI)); - callback.expectCapabilitiesThat(mWiFiNetworkAgent, (caps) - -> caps.hasCapability(NET_CAPABILITY_VALIDATED)); - - when(mPackageManager.getPackageUidAsUser(ALWAYS_ON_PACKAGE, RESTRICTED_USER)) - .thenReturn(UserHandle.getUid(RESTRICTED_USER, VPN_UID)); - - final Intent addedIntent = new Intent(ACTION_USER_ADDED); - addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER)); - addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER); - - // Send a USER_ADDED broadcast for it. - processBroadcast(addedIntent); - - // Expect that the VPN UID ranges contain both |uid| and the UID range for the newly-added - // restricted user. - final UidRange rRange = UidRange.createForUser(UserHandle.of(RESTRICTED_USER)); - final Range restrictUidRange = new Range(rRange.start, rRange.stop); - final Range singleUidRange = new Range(uid, uid); - callback.expectCapabilitiesThat(mMockVpn, (caps) - -> caps.getUids().size() == 2 - && caps.getUids().contains(singleUidRange) - && caps.getUids().contains(restrictUidRange) - && caps.hasTransport(TRANSPORT_VPN) - && caps.hasTransport(TRANSPORT_WIFI)); - - // Change the VPN's capabilities somehow (specifically, disconnect wifi). - mWiFiNetworkAgent.disconnect(); - callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - callback.expectCapabilitiesThat(mMockVpn, (caps) - -> caps.getUids().size() == 2 - && caps.getUids().contains(singleUidRange) - && caps.getUids().contains(restrictUidRange) - && caps.hasTransport(TRANSPORT_VPN) - && !caps.hasTransport(TRANSPORT_WIFI)); - - // Send a USER_REMOVED broadcast and expect to lose the UID range for the restricted user. - final Intent removedIntent = new Intent(ACTION_USER_REMOVED); - removedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER)); - removedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER); - processBroadcast(removedIntent); - - // Expect that the VPN gains the UID range for the restricted user, and that the capability - // change made just before that (i.e., loss of TRANSPORT_WIFI) is preserved. - callback.expectCapabilitiesThat(mMockVpn, (caps) - -> caps.getUids().size() == 1 - && caps.getUids().contains(singleUidRange) - && caps.hasTransport(TRANSPORT_VPN) - && !caps.hasTransport(TRANSPORT_WIFI)); - } - - @Test - public void testLockdownVpnWithRestrictedProfiles() throws Exception { - // For ConnectivityService#setAlwaysOnVpnPackage. - mServiceContext.setPermission( - Manifest.permission.CONTROL_ALWAYS_ON_VPN, PERMISSION_GRANTED); - // For call Vpn#setAlwaysOnPackage. - mServiceContext.setPermission( - Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED); - // Necessary to see the UID ranges in NetworkCapabilities. - mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED); - - final NetworkRequest request = new NetworkRequest.Builder() - .removeCapability(NET_CAPABILITY_NOT_VPN) - .build(); - final TestNetworkCallback callback = new TestNetworkCallback(); - mCm.registerNetworkCallback(request, callback); - - final int uid = Process.myUid(); - - // Connect wifi and check that UIDs in the main and restricted profiles have network access. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true /* validated */); - final int restrictedUid = UserHandle.getUid(RESTRICTED_USER, 42 /* appId */); - assertNotNull(mCm.getActiveNetworkForUid(uid)); - assertNotNull(mCm.getActiveNetworkForUid(restrictedUid)); - - // Enable always-on VPN lockdown. The main user loses network access because no VPN is up. - final ArrayList allowList = new ArrayList<>(); - mVpnManagerService.setAlwaysOnVpnPackage(PRIMARY_USER, ALWAYS_ON_PACKAGE, - true /* lockdown */, allowList); - waitForIdle(); - assertNull(mCm.getActiveNetworkForUid(uid)); - // This is arguably overspecified: a UID that is not running doesn't have an active network. - // But it's useful to check that non-default users do not lose network access, and to prove - // that the loss of connectivity below is indeed due to the restricted profile coming up. - assertNotNull(mCm.getActiveNetworkForUid(restrictedUid)); - - // Start the restricted profile, and check that the UID within it loses network access. - when(mPackageManager.getPackageUidAsUser(ALWAYS_ON_PACKAGE, RESTRICTED_USER)) - .thenReturn(UserHandle.getUid(RESTRICTED_USER, VPN_UID)); - when(mUserManager.getAliveUsers()).thenReturn(Arrays.asList(PRIMARY_USER_INFO, - RESTRICTED_USER_INFO)); - // TODO: check that VPN app within restricted profile still has access, etc. - final Intent addedIntent = new Intent(ACTION_USER_ADDED); - addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER)); - addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER); - processBroadcast(addedIntent); - assertNull(mCm.getActiveNetworkForUid(uid)); - assertNull(mCm.getActiveNetworkForUid(restrictedUid)); - - // Stop the restricted profile, and check that the UID within it has network access again. - when(mUserManager.getAliveUsers()).thenReturn(Arrays.asList(PRIMARY_USER_INFO)); - - // Send a USER_REMOVED broadcast and expect to lose the UID range for the restricted user. - final Intent removedIntent = new Intent(ACTION_USER_REMOVED); - removedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER)); - removedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER); - processBroadcast(removedIntent); - assertNull(mCm.getActiveNetworkForUid(uid)); - assertNotNull(mCm.getActiveNetworkForUid(restrictedUid)); - - mVpnManagerService.setAlwaysOnVpnPackage(PRIMARY_USER, null, false /* lockdown */, - allowList); - waitForIdle(); - } - - @Test - public void testIsActiveNetworkMeteredOverWifi() throws Exception { - // Returns true by default when no network is available. - assertTrue(mCm.isActiveNetworkMetered()); - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); - mWiFiNetworkAgent.connect(true); - waitForIdle(); - - assertFalse(mCm.isActiveNetworkMetered()); - } - - @Test - public void testIsActiveNetworkMeteredOverCell() throws Exception { - // Returns true by default when no network is available. - assertTrue(mCm.isActiveNetworkMetered()); - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED); - mCellNetworkAgent.connect(true); - waitForIdle(); - - assertTrue(mCm.isActiveNetworkMetered()); - } - - @Test - public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() throws Exception { - // Returns true by default when no network is available. - assertTrue(mCm.isActiveNetworkMetered()); - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED); - mCellNetworkAgent.connect(true); - waitForIdle(); - assertTrue(mCm.isActiveNetworkMetered()); - - // Connect VPN network. By default it is using current default network (Cell). - mMockVpn.establishForMyUid(); - assertUidRangesUpdatedForMyUid(true); - - // Ensure VPN is now the active network. - assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork()); - - // Expect VPN to be metered. - assertTrue(mCm.isActiveNetworkMetered()); - - // Connect WiFi. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); - mWiFiNetworkAgent.connect(true); - waitForIdle(); - // VPN should still be the active network. - assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork()); - - // Expect VPN to be unmetered as it should now be using WiFi (new default). - assertFalse(mCm.isActiveNetworkMetered()); - - // Disconnecting Cell should not affect VPN's meteredness. - mCellNetworkAgent.disconnect(); - waitForIdle(); - - assertFalse(mCm.isActiveNetworkMetered()); - - // Disconnect WiFi; Now there is no platform default network. - mWiFiNetworkAgent.disconnect(); - waitForIdle(); - - // VPN without any underlying networks is treated as metered. - assertTrue(mCm.isActiveNetworkMetered()); - - mMockVpn.disconnect(); - } - - @Test - public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() throws Exception { - // Returns true by default when no network is available. - assertTrue(mCm.isActiveNetworkMetered()); - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED); - mCellNetworkAgent.connect(true); - waitForIdle(); - assertTrue(mCm.isActiveNetworkMetered()); - - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); - mWiFiNetworkAgent.connect(true); - waitForIdle(); - assertFalse(mCm.isActiveNetworkMetered()); - - // Connect VPN network. - mMockVpn.establishForMyUid(); - assertUidRangesUpdatedForMyUid(true); - - // Ensure VPN is now the active network. - assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork()); - // VPN is using Cell - mMockVpn.setUnderlyingNetworks( - new Network[] { mCellNetworkAgent.getNetwork() }); - waitForIdle(); - - // Expect VPN to be metered. - assertTrue(mCm.isActiveNetworkMetered()); - - // VPN is now using WiFi - mMockVpn.setUnderlyingNetworks( - new Network[] { mWiFiNetworkAgent.getNetwork() }); - waitForIdle(); - - // Expect VPN to be unmetered - assertFalse(mCm.isActiveNetworkMetered()); - - // VPN is using Cell | WiFi. - mMockVpn.setUnderlyingNetworks( - new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() }); - waitForIdle(); - - // Expect VPN to be metered. - assertTrue(mCm.isActiveNetworkMetered()); - - // VPN is using WiFi | Cell. - mMockVpn.setUnderlyingNetworks( - new Network[] { mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork() }); - waitForIdle(); - - // Order should not matter and VPN should still be metered. - assertTrue(mCm.isActiveNetworkMetered()); - - // VPN is not using any underlying networks. - mMockVpn.setUnderlyingNetworks(new Network[0]); - waitForIdle(); - - // VPN without underlying networks is treated as metered. - assertTrue(mCm.isActiveNetworkMetered()); - - mMockVpn.disconnect(); - } - - @Test - public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() throws Exception { - // Returns true by default when no network is available. - assertTrue(mCm.isActiveNetworkMetered()); - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); - mWiFiNetworkAgent.connect(true); - waitForIdle(); - assertFalse(mCm.isActiveNetworkMetered()); - - // Connect VPN network. - mMockVpn.registerAgent(true /* isAlwaysMetered */, uidRangesForUids(Process.myUid()), - new LinkProperties()); - mMockVpn.connect(true); - waitForIdle(); - assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork()); - - // VPN is tracking current platform default (WiFi). - mMockVpn.setUnderlyingNetworks(null); - waitForIdle(); - - // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered. - assertTrue(mCm.isActiveNetworkMetered()); - - - // VPN explicitly declares WiFi as its underlying network. - mMockVpn.setUnderlyingNetworks( - new Network[] { mWiFiNetworkAgent.getNetwork() }); - waitForIdle(); - - // Doesn't really matter whether VPN declares its underlying networks explicitly. - assertTrue(mCm.isActiveNetworkMetered()); - - // With WiFi lost, VPN is basically without any underlying networks. And in that case it is - // anyways suppose to be metered. - mWiFiNetworkAgent.disconnect(); - waitForIdle(); - - assertTrue(mCm.isActiveNetworkMetered()); - - mMockVpn.disconnect(); - } - - private class DetailedBlockedStatusCallback extends TestNetworkCallback { - public void expectAvailableThenValidatedCallbacks(HasNetwork n, int blockedStatus) { - super.expectAvailableThenValidatedCallbacks(n.getNetwork(), blockedStatus, TIMEOUT_MS); - } - public void expectBlockedStatusCallback(HasNetwork n, int blockedStatus) { - // This doesn't work: - // super.expectBlockedStatusCallback(blockedStatus, n.getNetwork()); - super.expectBlockedStatusCallback(blockedStatus, n.getNetwork(), TIMEOUT_MS); - } - public void onBlockedStatusChanged(Network network, int blockedReasons) { - getHistory().add(new CallbackEntry.BlockedStatusInt(network, blockedReasons)); - } - } - - @Test - public void testNetworkBlockedStatus() throws Exception { - final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); - final NetworkRequest cellRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR) - .build(); - mCm.registerNetworkCallback(cellRequest, cellNetworkCallback); - final DetailedBlockedStatusCallback detailedCallback = new DetailedBlockedStatusCallback(); - mCm.registerNetworkCallback(cellRequest, detailedCallback); - - mockUidNetworkingBlocked(); - - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - detailedCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent, - BLOCKED_REASON_NONE); - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); - assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); - assertExtraInfoFromCmPresent(mCellNetworkAgent); - - setBlockedReasonChanged(BLOCKED_REASON_BATTERY_SAVER); - cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent); - detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent, - BLOCKED_REASON_BATTERY_SAVER); - assertNull(mCm.getActiveNetwork()); - assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); - assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); - assertExtraInfoFromCmBlocked(mCellNetworkAgent); - - // If blocked state does not change but blocked reason does, the boolean callback is called. - // TODO: investigate de-duplicating. - setBlockedReasonChanged(BLOCKED_METERED_REASON_USER_RESTRICTED); - cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent); - detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent, - BLOCKED_METERED_REASON_USER_RESTRICTED); - - setBlockedReasonChanged(BLOCKED_REASON_NONE); - cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent); - detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent, BLOCKED_REASON_NONE); - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); - assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); - assertExtraInfoFromCmPresent(mCellNetworkAgent); - - setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER); - cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent); - detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent, - BLOCKED_METERED_REASON_DATA_SAVER); - assertNull(mCm.getActiveNetwork()); - assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); - assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); - assertExtraInfoFromCmBlocked(mCellNetworkAgent); - - // Restrict the network based on UID rule and NOT_METERED capability change. - mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); - cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent); - cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent); - detailedCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent); - detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent, BLOCKED_REASON_NONE); - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); - assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); - assertExtraInfoFromCmPresent(mCellNetworkAgent); - - mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED); - cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, - mCellNetworkAgent); - cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent); - detailedCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, - mCellNetworkAgent); - detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent, - BLOCKED_METERED_REASON_DATA_SAVER); - assertNull(mCm.getActiveNetwork()); - assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); - assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); - assertExtraInfoFromCmBlocked(mCellNetworkAgent); - - setBlockedReasonChanged(BLOCKED_REASON_NONE); - cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent); - detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent, BLOCKED_REASON_NONE); - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); - assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); - assertExtraInfoFromCmPresent(mCellNetworkAgent); - - setBlockedReasonChanged(BLOCKED_REASON_NONE); - cellNetworkCallback.assertNoCallback(); - detailedCallback.assertNoCallback(); - - // Restrict background data. Networking is not blocked because the network is unmetered. - setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER); - cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent); - detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent, - BLOCKED_METERED_REASON_DATA_SAVER); - assertNull(mCm.getActiveNetwork()); - assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); - assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); - assertExtraInfoFromCmBlocked(mCellNetworkAgent); - setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER); - cellNetworkCallback.assertNoCallback(); - - setBlockedReasonChanged(BLOCKED_REASON_NONE); - cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent); - detailedCallback.expectBlockedStatusCallback(mCellNetworkAgent, BLOCKED_REASON_NONE); - assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); - assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); - assertExtraInfoFromCmPresent(mCellNetworkAgent); - - setBlockedReasonChanged(BLOCKED_REASON_NONE); - cellNetworkCallback.assertNoCallback(); - detailedCallback.assertNoCallback(); - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); - assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); - assertExtraInfoFromCmPresent(mCellNetworkAgent); - - mCm.unregisterNetworkCallback(cellNetworkCallback); - } - - @Test - public void testNetworkBlockedStatusBeforeAndAfterConnect() throws Exception { - final TestNetworkCallback defaultCallback = new TestNetworkCallback(); - mCm.registerDefaultNetworkCallback(defaultCallback); - mockUidNetworkingBlocked(); - - // No Networkcallbacks invoked before any network is active. - setBlockedReasonChanged(BLOCKED_REASON_BATTERY_SAVER); - setBlockedReasonChanged(BLOCKED_REASON_NONE); - setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER); - defaultCallback.assertNoCallback(); - - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent); - defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellNetworkAgent); - - // Allow to use the network after switching to NOT_METERED network. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); - mWiFiNetworkAgent.connect(true); - defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); - - // Switch to METERED network. Restrict the use of the network. - mWiFiNetworkAgent.disconnect(); - defaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent); - - // Network becomes NOT_METERED. - mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); - defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent); - defaultCallback.expectBlockedStatusCallback(false, mCellNetworkAgent); - - // Verify there's no Networkcallbacks invoked after data saver on/off. - setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER); - setBlockedReasonChanged(BLOCKED_REASON_NONE); - defaultCallback.assertNoCallback(); - - mCellNetworkAgent.disconnect(); - defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - defaultCallback.assertNoCallback(); - - mCm.unregisterNetworkCallback(defaultCallback); - } - - private void expectNetworkRejectNonSecureVpn(InOrder inOrder, boolean add, - UidRangeParcel... expected) throws Exception { - inOrder.verify(mMockNetd).networkRejectNonSecureVpn(eq(add), aryEq(expected)); - } - - private void checkNetworkInfo(NetworkInfo ni, int type, DetailedState state) { - assertNotNull(ni); - assertEquals(type, ni.getType()); - assertEquals(ConnectivityManager.getNetworkTypeName(type), state, ni.getDetailedState()); - if (state == DetailedState.CONNECTED || state == DetailedState.SUSPENDED) { - assertNotNull(ni.getExtraInfo()); - } else { - // Technically speaking, a network that's in CONNECTING state will generally have a - // non-null extraInfo. This doesn't actually happen in this test because it never calls - // a legacy API while a network is connecting. When a network is in CONNECTING state - // because of legacy lockdown VPN, its extraInfo is always null. - assertNull(ni.getExtraInfo()); - } - } - - private void assertActiveNetworkInfo(int type, DetailedState state) { - checkNetworkInfo(mCm.getActiveNetworkInfo(), type, state); - } - private void assertNetworkInfo(int type, DetailedState state) { - checkNetworkInfo(mCm.getNetworkInfo(type), type, state); - } - - private void assertExtraInfoFromCm(TestNetworkAgentWrapper network, boolean present) { - final NetworkInfo niForNetwork = mCm.getNetworkInfo(network.getNetwork()); - final NetworkInfo niForType = mCm.getNetworkInfo(network.getLegacyType()); - if (present) { - assertEquals(network.getExtraInfo(), niForNetwork.getExtraInfo()); - assertEquals(network.getExtraInfo(), niForType.getExtraInfo()); - } else { - assertNull(niForNetwork.getExtraInfo()); - assertNull(niForType.getExtraInfo()); - } - } - - private void assertExtraInfoFromCmBlocked(TestNetworkAgentWrapper network) { - assertExtraInfoFromCm(network, false); - } - - private void assertExtraInfoFromCmPresent(TestNetworkAgentWrapper network) { - assertExtraInfoFromCm(network, true); - } - - // Checks that each of the |agents| receive a blocked status change callback with the specified - // |blocked| value, in any order. This is needed because when an event affects multiple - // networks, ConnectivityService does not guarantee the order in which callbacks are fired. - private void assertBlockedCallbackInAnyOrder(TestNetworkCallback callback, boolean blocked, - TestNetworkAgentWrapper... agents) { - final List expectedNetworks = Arrays.asList(agents).stream() - .map((agent) -> agent.getNetwork()) - .collect(Collectors.toList()); - - // Expect exactly one blocked callback for each agent. - for (int i = 0; i < agents.length; i++) { - CallbackEntry e = callback.expectCallbackThat(TIMEOUT_MS, (c) -> - c instanceof CallbackEntry.BlockedStatus - && ((CallbackEntry.BlockedStatus) c).getBlocked() == blocked); - Network network = e.getNetwork(); - assertTrue("Received unexpected blocked callback for network " + network, - expectedNetworks.remove(network)); - } - } - - @Test - public void testNetworkBlockedStatusAlwaysOnVpn() throws Exception { - mServiceContext.setPermission( - Manifest.permission.CONTROL_ALWAYS_ON_VPN, PERMISSION_GRANTED); - mServiceContext.setPermission( - Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED); - mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED); - - final TestNetworkCallback callback = new TestNetworkCallback(); - final NetworkRequest request = new NetworkRequest.Builder() - .removeCapability(NET_CAPABILITY_NOT_VPN) - .build(); - mCm.registerNetworkCallback(request, callback); - - final TestNetworkCallback defaultCallback = new TestNetworkCallback(); - mCm.registerDefaultNetworkCallback(defaultCallback); - - final TestNetworkCallback vpnUidCallback = new TestNetworkCallback(); - final NetworkRequest vpnUidRequest = new NetworkRequest.Builder().build(); - registerNetworkCallbackAsUid(vpnUidRequest, vpnUidCallback, VPN_UID); - - final TestNetworkCallback vpnUidDefaultCallback = new TestNetworkCallback(); - registerDefaultNetworkCallbackAsUid(vpnUidDefaultCallback, VPN_UID); - - final TestNetworkCallback vpnDefaultCallbackAsUid = new TestNetworkCallback(); - mCm.registerDefaultNetworkCallbackForUid(VPN_UID, vpnDefaultCallbackAsUid, - new Handler(ConnectivityThread.getInstanceLooper())); - - final int uid = Process.myUid(); - final int userId = UserHandle.getUserId(uid); - final ArrayList allowList = new ArrayList<>(); - mVpnManagerService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, - allowList); - waitForIdle(); - - UidRangeParcel firstHalf = new UidRangeParcel(1, VPN_UID - 1); - UidRangeParcel secondHalf = new UidRangeParcel(VPN_UID + 1, 99999); - InOrder inOrder = inOrder(mMockNetd); - expectNetworkRejectNonSecureVpn(inOrder, true, firstHalf, secondHalf); - - // Connect a network when lockdown is active, expect to see it blocked. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(false /* validated */); - callback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent); - defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent); - vpnUidCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - vpnUidDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - vpnDefaultCallbackAsUid.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); - assertNull(mCm.getActiveNetwork()); - assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED); - // Mobile is BLOCKED even though it's not actually connected. - assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); - assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED); - - // Disable lockdown, expect to see the network unblocked. - mVpnManagerService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList); - callback.expectBlockedStatusCallback(false, mWiFiNetworkAgent); - defaultCallback.expectBlockedStatusCallback(false, mWiFiNetworkAgent); - vpnUidCallback.assertNoCallback(); - vpnUidDefaultCallback.assertNoCallback(); - vpnDefaultCallbackAsUid.assertNoCallback(); - expectNetworkRejectNonSecureVpn(inOrder, false, firstHalf, secondHalf); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); - assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); - assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); - - // Add our UID to the allowlist and re-enable lockdown, expect network is not blocked. - allowList.add(TEST_PACKAGE_NAME); - mVpnManagerService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, - allowList); - callback.assertNoCallback(); - defaultCallback.assertNoCallback(); - vpnUidCallback.assertNoCallback(); - vpnUidDefaultCallback.assertNoCallback(); - vpnDefaultCallbackAsUid.assertNoCallback(); - - // The following requires that the UID of this test package is greater than VPN_UID. This - // is always true in practice because a plain AOSP build with no apps installed has almost - // 200 packages installed. - final UidRangeParcel piece1 = new UidRangeParcel(1, VPN_UID - 1); - final UidRangeParcel piece2 = new UidRangeParcel(VPN_UID + 1, uid - 1); - final UidRangeParcel piece3 = new UidRangeParcel(uid + 1, 99999); - expectNetworkRejectNonSecureVpn(inOrder, true, piece1, piece2, piece3); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); - assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); - assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); - - // Connect a new network, expect it to be unblocked. - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(false /* validated */); - callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); - defaultCallback.assertNoCallback(); - vpnUidCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); - vpnUidDefaultCallback.assertNoCallback(); - vpnDefaultCallbackAsUid.assertNoCallback(); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); - // Cellular is DISCONNECTED because it's not the default and there are no requests for it. - assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); - assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); - - // Disable lockdown, remove our UID from the allowlist, and re-enable lockdown. - // Everything should now be blocked. - mVpnManagerService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList); - waitForIdle(); - expectNetworkRejectNonSecureVpn(inOrder, false, piece1, piece2, piece3); - allowList.clear(); - mVpnManagerService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, - allowList); - waitForIdle(); - expectNetworkRejectNonSecureVpn(inOrder, true, firstHalf, secondHalf); - defaultCallback.expectBlockedStatusCallback(true, mWiFiNetworkAgent); - assertBlockedCallbackInAnyOrder(callback, true, mWiFiNetworkAgent, mCellNetworkAgent); - vpnUidCallback.assertNoCallback(); - vpnUidDefaultCallback.assertNoCallback(); - vpnDefaultCallbackAsUid.assertNoCallback(); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); - assertNull(mCm.getActiveNetwork()); - assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED); - assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); - assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED); - - // Disable lockdown. Everything is unblocked. - mVpnManagerService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList); - defaultCallback.expectBlockedStatusCallback(false, mWiFiNetworkAgent); - assertBlockedCallbackInAnyOrder(callback, false, mWiFiNetworkAgent, mCellNetworkAgent); - vpnUidCallback.assertNoCallback(); - vpnUidDefaultCallback.assertNoCallback(); - vpnDefaultCallbackAsUid.assertNoCallback(); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); - assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); - assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); - - // Enable and disable an always-on VPN package without lockdown. Expect no changes. - reset(mMockNetd); - mVpnManagerService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, false /* lockdown */, - allowList); - inOrder.verify(mMockNetd, never()).networkRejectNonSecureVpn(anyBoolean(), any()); - callback.assertNoCallback(); - defaultCallback.assertNoCallback(); - vpnUidCallback.assertNoCallback(); - vpnUidDefaultCallback.assertNoCallback(); - vpnDefaultCallbackAsUid.assertNoCallback(); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); - assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); - assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); - - mVpnManagerService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList); - inOrder.verify(mMockNetd, never()).networkRejectNonSecureVpn(anyBoolean(), any()); - callback.assertNoCallback(); - defaultCallback.assertNoCallback(); - vpnUidCallback.assertNoCallback(); - vpnUidDefaultCallback.assertNoCallback(); - vpnDefaultCallbackAsUid.assertNoCallback(); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); - assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); - assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); - - // Enable lockdown and connect a VPN. The VPN is not blocked. - mVpnManagerService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, - allowList); - defaultCallback.expectBlockedStatusCallback(true, mWiFiNetworkAgent); - assertBlockedCallbackInAnyOrder(callback, true, mWiFiNetworkAgent, mCellNetworkAgent); - vpnUidCallback.assertNoCallback(); - vpnUidDefaultCallback.assertNoCallback(); - vpnDefaultCallbackAsUid.assertNoCallback(); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); - assertNull(mCm.getActiveNetwork()); - assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED); - assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); - assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED); - - mMockVpn.establishForMyUid(); - assertUidRangesUpdatedForMyUid(true); - defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn); - vpnUidCallback.assertNoCallback(); // vpnUidCallback has NOT_VPN capability. - vpnUidDefaultCallback.assertNoCallback(); // VPN does not apply to VPN_UID - vpnDefaultCallbackAsUid.assertNoCallback(); - assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork()); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); - assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); - assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); - assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED); - assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); - - mMockVpn.disconnect(); - defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn); - defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent); - vpnUidCallback.assertNoCallback(); - vpnUidDefaultCallback.assertNoCallback(); - vpnDefaultCallbackAsUid.assertNoCallback(); - assertNull(mCm.getActiveNetwork()); - - mCm.unregisterNetworkCallback(callback); - mCm.unregisterNetworkCallback(defaultCallback); - mCm.unregisterNetworkCallback(vpnUidCallback); - mCm.unregisterNetworkCallback(vpnUidDefaultCallback); - mCm.unregisterNetworkCallback(vpnDefaultCallbackAsUid); - } - - private void setupLegacyLockdownVpn() { - final String profileName = "testVpnProfile"; - final byte[] profileTag = profileName.getBytes(StandardCharsets.UTF_8); - when(mVpnProfileStore.get(Credentials.LOCKDOWN_VPN)).thenReturn(profileTag); - - final VpnProfile profile = new VpnProfile(profileName); - profile.name = "My VPN"; - profile.server = "192.0.2.1"; - profile.dnsServers = "8.8.8.8"; - profile.type = VpnProfile.TYPE_IPSEC_XAUTH_PSK; - final byte[] encodedProfile = profile.encode(); - when(mVpnProfileStore.get(Credentials.VPN + profileName)).thenReturn(encodedProfile); - } - - private void establishLegacyLockdownVpn(Network underlying) throws Exception { - // The legacy lockdown VPN only supports userId 0, and must have an underlying network. - assertNotNull(underlying); - mMockVpn.setVpnType(VpnManager.TYPE_VPN_LEGACY); - // The legacy lockdown VPN only supports userId 0. - final Set ranges = Collections.singleton(PRIMARY_UIDRANGE); - mMockVpn.registerAgent(ranges); - mMockVpn.setUnderlyingNetworks(new Network[]{underlying}); - mMockVpn.connect(true); - } - - @Test - public void testLegacyLockdownVpn() throws Exception { - mServiceContext.setPermission( - Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED); - // For LockdownVpnTracker to call registerSystemDefaultNetworkCallback. - mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED); - - final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build(); - final TestNetworkCallback callback = new TestNetworkCallback(); - mCm.registerNetworkCallback(request, callback); - - final TestNetworkCallback defaultCallback = new TestNetworkCallback(); - mCm.registerDefaultNetworkCallback(defaultCallback); - - final TestNetworkCallback systemDefaultCallback = new TestNetworkCallback(); - mCm.registerSystemDefaultNetworkCallback(systemDefaultCallback, - new Handler(ConnectivityThread.getInstanceLooper())); - - // Pretend lockdown VPN was configured. - setupLegacyLockdownVpn(); - - // LockdownVpnTracker disables the Vpn teardown code and enables lockdown. - // Check the VPN's state before it does so. - assertTrue(mMockVpn.getEnableTeardown()); - assertFalse(mMockVpn.getLockdown()); - - // Send a USER_UNLOCKED broadcast so CS starts LockdownVpnTracker. - final int userId = UserHandle.getUserId(Process.myUid()); - final Intent addedIntent = new Intent(ACTION_USER_UNLOCKED); - addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(userId)); - addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId); - processBroadcast(addedIntent); - - // Lockdown VPN disables teardown and enables lockdown. - assertFalse(mMockVpn.getEnableTeardown()); - assertTrue(mMockVpn.getLockdown()); - - // Bring up a network. - // Expect nothing to happen because the network does not have an IPv4 default route: legacy - // VPN only supports IPv4. - final LinkProperties cellLp = new LinkProperties(); - cellLp.setInterfaceName("rmnet0"); - cellLp.addLinkAddress(new LinkAddress("2001:db8::1/64")); - cellLp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, "rmnet0")); - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp); - mCellNetworkAgent.connect(false /* validated */); - callback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent); - defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent); - systemDefaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent); - waitForIdle(); - assertNull(mMockVpn.getAgent()); - - // Add an IPv4 address. Ideally the VPN should start, but it doesn't because nothing calls - // LockdownVpnTracker#handleStateChangedLocked. This is a bug. - // TODO: consider fixing this. - cellLp.addLinkAddress(new LinkAddress("192.0.2.2/25")); - cellLp.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0"), null, "rmnet0")); - mCellNetworkAgent.sendLinkProperties(cellLp); - callback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); - defaultCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); - systemDefaultCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, - mCellNetworkAgent); - waitForIdle(); - assertNull(mMockVpn.getAgent()); - - // Disconnect, then try again with a network that supports IPv4 at connection time. - // Expect lockdown VPN to come up. - ExpectedBroadcast b1 = expectConnectivityAction(TYPE_MOBILE, DetailedState.DISCONNECTED); - mCellNetworkAgent.disconnect(); - callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - systemDefaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - b1.expectBroadcast(); - - // When lockdown VPN is active, the NetworkInfo state in CONNECTIVITY_ACTION is overwritten - // with the state of the VPN network. So expect a CONNECTING broadcast. - b1 = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTING); - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp); - mCellNetworkAgent.connect(false /* validated */); - callback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent); - defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent); - systemDefaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent); - b1.expectBroadcast(); - assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); - assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); - assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED); - assertNetworkInfo(TYPE_VPN, DetailedState.BLOCKED); - assertExtraInfoFromCmBlocked(mCellNetworkAgent); - - // TODO: it would be nice if we could simply rely on the production code here, and have - // LockdownVpnTracker start the VPN, have the VPN code register its NetworkAgent with - // ConnectivityService, etc. That would require duplicating a fair bit of code from the - // Vpn tests around how to mock out LegacyVpnRunner. But even if we did that, this does not - // work for at least two reasons: - // 1. In this test, calling registerNetworkAgent does not actually result in an agent being - // registered. This is because nothing calls onNetworkMonitorCreated, which is what - // actually ends up causing handleRegisterNetworkAgent to be called. Code in this test - // that wants to register an agent must use TestNetworkAgentWrapper. - // 2. Even if we exposed Vpn#agentConnect to the test, and made MockVpn#agentConnect call - // the TestNetworkAgentWrapper code, this would deadlock because the - // TestNetworkAgentWrapper code cannot be called on the handler thread since it calls - // waitForIdle(). - mMockVpn.expectStartLegacyVpnRunner(); - b1 = expectConnectivityAction(TYPE_VPN, DetailedState.CONNECTED); - ExpectedBroadcast b2 = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED); - establishLegacyLockdownVpn(mCellNetworkAgent.getNetwork()); - callback.expectAvailableThenValidatedCallbacks(mMockVpn); - defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn); - systemDefaultCallback.assertNoCallback(); - NetworkCapabilities vpnNc = mCm.getNetworkCapabilities(mMockVpn.getNetwork()); - b1.expectBroadcast(); - b2.expectBroadcast(); - assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); - assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); - assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED); - assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED); - assertExtraInfoFromCmPresent(mCellNetworkAgent); - assertTrue(vpnNc.hasTransport(TRANSPORT_VPN)); - assertTrue(vpnNc.hasTransport(TRANSPORT_CELLULAR)); - assertFalse(vpnNc.hasTransport(TRANSPORT_WIFI)); - assertFalse(vpnNc.hasCapability(NET_CAPABILITY_NOT_METERED)); - assertVpnTransportInfo(vpnNc, VpnManager.TYPE_VPN_LEGACY); - - // Switch default network from cell to wifi. Expect VPN to disconnect and reconnect. - final LinkProperties wifiLp = new LinkProperties(); - wifiLp.setInterfaceName("wlan0"); - wifiLp.addLinkAddress(new LinkAddress("192.0.2.163/25")); - wifiLp.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0"), null, "wlan0")); - final NetworkCapabilities wifiNc = new NetworkCapabilities(); - wifiNc.addTransportType(TRANSPORT_WIFI); - wifiNc.addCapability(NET_CAPABILITY_NOT_METERED); - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp, wifiNc); - - b1 = expectConnectivityAction(TYPE_MOBILE, DetailedState.DISCONNECTED); - // Wifi is CONNECTING because the VPN isn't up yet. - b2 = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTING); - ExpectedBroadcast b3 = expectConnectivityAction(TYPE_VPN, DetailedState.DISCONNECTED); - mWiFiNetworkAgent.connect(false /* validated */); - b1.expectBroadcast(); - b2.expectBroadcast(); - b3.expectBroadcast(); - mMockVpn.expectStopVpnRunnerPrivileged(); - mMockVpn.expectStartLegacyVpnRunner(); - - // TODO: why is wifi not blocked? Is it because when this callback is sent, the VPN is still - // connected, so the network is not considered blocked by the lockdown UID ranges? But the - // fact that a VPN is connected should only result in the VPN itself being unblocked, not - // any other network. Bug in isUidBlockedByVpn? - callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - callback.expectCallback(CallbackEntry.LOST, mMockVpn); - defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn); - defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent); - systemDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - - // While the VPN is reconnecting on the new network, everything is blocked. - assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED); - assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); - assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED); - assertNetworkInfo(TYPE_VPN, DetailedState.BLOCKED); - assertExtraInfoFromCmBlocked(mWiFiNetworkAgent); - - // The VPN comes up again on wifi. - b1 = expectConnectivityAction(TYPE_VPN, DetailedState.CONNECTED); - b2 = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED); - establishLegacyLockdownVpn(mWiFiNetworkAgent.getNetwork()); - callback.expectAvailableThenValidatedCallbacks(mMockVpn); - defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn); - systemDefaultCallback.assertNoCallback(); - b1.expectBroadcast(); - b2.expectBroadcast(); - assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); - assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); - assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); - assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED); - assertExtraInfoFromCmPresent(mWiFiNetworkAgent); - vpnNc = mCm.getNetworkCapabilities(mMockVpn.getNetwork()); - assertTrue(vpnNc.hasTransport(TRANSPORT_VPN)); - assertTrue(vpnNc.hasTransport(TRANSPORT_WIFI)); - assertFalse(vpnNc.hasTransport(TRANSPORT_CELLULAR)); - assertTrue(vpnNc.hasCapability(NET_CAPABILITY_NOT_METERED)); - - // Disconnect cell. Nothing much happens since it's not the default network. - mCellNetworkAgent.disconnect(); - callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - defaultCallback.assertNoCallback(); - systemDefaultCallback.assertNoCallback(); - - assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); - assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); - assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); - assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED); - assertExtraInfoFromCmPresent(mWiFiNetworkAgent); - - b1 = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED); - b2 = expectConnectivityAction(TYPE_VPN, DetailedState.DISCONNECTED); - mWiFiNetworkAgent.disconnect(); - callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - systemDefaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - b1.expectBroadcast(); - callback.expectCapabilitiesThat(mMockVpn, nc -> !nc.hasTransport(TRANSPORT_WIFI)); - mMockVpn.expectStopVpnRunnerPrivileged(); - callback.expectCallback(CallbackEntry.LOST, mMockVpn); - b2.expectBroadcast(); - } - - /** - * Test mutable and requestable network capabilities such as - * {@link NetworkCapabilities#NET_CAPABILITY_TRUSTED} and - * {@link NetworkCapabilities#NET_CAPABILITY_NOT_VCN_MANAGED}. Verify that the - * {@code ConnectivityService} re-assign the networks accordingly. - */ - @Test - public final void testLoseMutableAndRequestableCaps() throws Exception { - final int[] testCaps = new int [] { - NET_CAPABILITY_TRUSTED, - NET_CAPABILITY_NOT_VCN_MANAGED - }; - for (final int testCap : testCaps) { - // Create requests with and without the testing capability. - final TestNetworkCallback callbackWithCap = new TestNetworkCallback(); - final TestNetworkCallback callbackWithoutCap = new TestNetworkCallback(); - mCm.requestNetwork(new NetworkRequest.Builder().addCapability(testCap).build(), - callbackWithCap); - mCm.requestNetwork(new NetworkRequest.Builder().removeCapability(testCap).build(), - callbackWithoutCap); - - // Setup networks with testing capability and verify the default network changes. - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.addCapability(testCap); - mCellNetworkAgent.connect(true); - callbackWithCap.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - callbackWithoutCap.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - verify(mMockNetd).networkSetDefault(eq(mCellNetworkAgent.getNetwork().netId)); - reset(mMockNetd); - - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.addCapability(testCap); - mWiFiNetworkAgent.connect(true); - callbackWithCap.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); - callbackWithoutCap.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); - verify(mMockNetd).networkSetDefault(eq(mWiFiNetworkAgent.getNetwork().netId)); - reset(mMockNetd); - - // Remove the testing capability on wifi, verify the callback and default network - // changes back to cellular. - mWiFiNetworkAgent.removeCapability(testCap); - callbackWithCap.expectAvailableCallbacksValidated(mCellNetworkAgent); - callbackWithoutCap.expectCapabilitiesWithout(testCap, mWiFiNetworkAgent); - verify(mMockNetd).networkSetDefault(eq(mCellNetworkAgent.getNetwork().netId)); - reset(mMockNetd); - - mCellNetworkAgent.removeCapability(testCap); - callbackWithCap.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - callbackWithoutCap.assertNoCallback(); - verify(mMockNetd).networkClearDefault(); - - mCm.unregisterNetworkCallback(callbackWithCap); - mCm.unregisterNetworkCallback(callbackWithoutCap); - } - } - - @Test - public final void testBatteryStatsNetworkType() throws Exception { - final LinkProperties cellLp = new LinkProperties(); - cellLp.setInterfaceName("cell0"); - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp); - mCellNetworkAgent.connect(true); - waitForIdle(); - verify(mDeps).reportNetworkInterfaceForTransports(mServiceContext, - cellLp.getInterfaceName(), - new int[] { TRANSPORT_CELLULAR }); - - final LinkProperties wifiLp = new LinkProperties(); - wifiLp.setInterfaceName("wifi0"); - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp); - mWiFiNetworkAgent.connect(true); - waitForIdle(); - verify(mDeps).reportNetworkInterfaceForTransports(mServiceContext, - wifiLp.getInterfaceName(), - new int[] { TRANSPORT_WIFI }); - - mCellNetworkAgent.disconnect(); - mWiFiNetworkAgent.disconnect(); - - cellLp.setInterfaceName("wifi0"); - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp); - mCellNetworkAgent.connect(true); - waitForIdle(); - verify(mDeps).reportNetworkInterfaceForTransports(mServiceContext, - cellLp.getInterfaceName(), - new int[] { TRANSPORT_CELLULAR }); - mCellNetworkAgent.disconnect(); - } - - /** - * Make simulated InterfaceConfigParcel for Nat464Xlat to query clat lower layer info. - */ - private InterfaceConfigurationParcel getClatInterfaceConfigParcel(LinkAddress la) { - final InterfaceConfigurationParcel cfg = new InterfaceConfigurationParcel(); - cfg.hwAddr = "11:22:33:44:55:66"; - cfg.ipv4Addr = la.getAddress().getHostAddress(); - cfg.prefixLength = la.getPrefixLength(); - return cfg; - } - - /** - * Make expected stack link properties, copied from Nat464Xlat. - */ - private LinkProperties makeClatLinkProperties(LinkAddress la) { - LinkAddress clatAddress = la; - LinkProperties stacked = new LinkProperties(); - stacked.setInterfaceName(CLAT_PREFIX + MOBILE_IFNAME); - RouteInfo ipv4Default = new RouteInfo( - new LinkAddress(Inet4Address.ANY, 0), - clatAddress.getAddress(), CLAT_PREFIX + MOBILE_IFNAME); - stacked.addRoute(ipv4Default); - stacked.addLinkAddress(clatAddress); - return stacked; - } - - private Nat64PrefixEventParcel makeNat64PrefixEvent(final int netId, final int prefixOperation, - final String prefixAddress, final int prefixLength) { - final Nat64PrefixEventParcel event = new Nat64PrefixEventParcel(); - event.netId = netId; - event.prefixOperation = prefixOperation; - event.prefixAddress = prefixAddress; - event.prefixLength = prefixLength; - return event; - } - - @Test - public void testStackedLinkProperties() throws Exception { - final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24"); - final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64"); - final String kNat64PrefixString = "2001:db8:64:64:64:64::"; - final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96); - final String kOtherNat64PrefixString = "64:ff9b::"; - final IpPrefix kOtherNat64Prefix = new IpPrefix( - InetAddress.getByName(kOtherNat64PrefixString), 96); - final RouteInfo defaultRoute = new RouteInfo((IpPrefix) null, myIpv6.getAddress(), - MOBILE_IFNAME); - final RouteInfo ipv6Subnet = new RouteInfo(myIpv6, null, MOBILE_IFNAME); - final RouteInfo ipv4Subnet = new RouteInfo(myIpv4, null, MOBILE_IFNAME); - final RouteInfo stackedDefault = new RouteInfo((IpPrefix) null, myIpv4.getAddress(), - CLAT_PREFIX + MOBILE_IFNAME); - - final NetworkRequest networkRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR) - .addCapability(NET_CAPABILITY_INTERNET) - .build(); - final TestNetworkCallback networkCallback = new TestNetworkCallback(); - mCm.registerNetworkCallback(networkRequest, networkCallback); - - // Prepare ipv6 only link properties. - final LinkProperties cellLp = new LinkProperties(); - cellLp.setInterfaceName(MOBILE_IFNAME); - cellLp.addLinkAddress(myIpv6); - cellLp.addRoute(defaultRoute); - cellLp.addRoute(ipv6Subnet); - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp); - reset(mMockDnsResolver); - reset(mMockNetd); - - // Connect with ipv6 link properties. Expect prefix discovery to be started. - mCellNetworkAgent.connect(true); - final int cellNetId = mCellNetworkAgent.getNetwork().netId; - waitForIdle(); - - verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(cellNetId, - INetd.PERMISSION_NONE)); - assertRoutesAdded(cellNetId, ipv6Subnet, defaultRoute); - verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId)); - verify(mMockNetd, times(1)).networkAddInterface(cellNetId, MOBILE_IFNAME); - verify(mDeps).reportNetworkInterfaceForTransports(mServiceContext, - cellLp.getInterfaceName(), - new int[] { TRANSPORT_CELLULAR }); - - networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId); - - // Switching default network updates TCP buffer sizes. - verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES); - // Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that - // the NAT64 prefix was removed because one was never discovered. - cellLp.addLinkAddress(myIpv4); - mCellNetworkAgent.sendLinkProperties(cellLp); - networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); - assertRoutesAdded(cellNetId, ipv4Subnet); - verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId); - verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any()); - - // Make sure BatteryStats was not told about any v4- interfaces, as none should have - // come online yet. - waitForIdle(); - verify(mDeps, never()) - .reportNetworkInterfaceForTransports(eq(mServiceContext), startsWith("v4-"), any()); - - verifyNoMoreInteractions(mMockNetd); - verifyNoMoreInteractions(mMockDnsResolver); - reset(mMockNetd); - reset(mMockDnsResolver); - when(mMockNetd.interfaceGetCfg(CLAT_PREFIX + MOBILE_IFNAME)) - .thenReturn(getClatInterfaceConfigParcel(myIpv4)); - - // Remove IPv4 address. Expect prefix discovery to be started again. - cellLp.removeLinkAddress(myIpv4); - mCellNetworkAgent.sendLinkProperties(cellLp); - networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); - verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId); - assertRoutesRemoved(cellNetId, ipv4Subnet); - - // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started. - Nat464Xlat clat = getNat464Xlat(mCellNetworkAgent); - assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix()); - mService.mResolverUnsolEventCallback.onNat64PrefixEvent( - makeNat64PrefixEvent(cellNetId, PREFIX_OPERATION_ADDED, kNat64PrefixString, 96)); - LinkProperties lpBeforeClat = networkCallback.expectCallback( - CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent).getLp(); - assertEquals(0, lpBeforeClat.getStackedLinks().size()); - assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix()); - verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString()); - - // Clat iface comes up. Expect stacked link to be added. - clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true); - networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); - List stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork()) - .getStackedLinks(); - assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0)); - assertRoutesAdded(cellNetId, stackedDefault); - verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_PREFIX + MOBILE_IFNAME); - // Change trivial linkproperties and see if stacked link is preserved. - cellLp.addDnsServer(InetAddress.getByName("8.8.8.8")); - mCellNetworkAgent.sendLinkProperties(cellLp); - networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); - - List stackedLpsAfterChange = - mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getStackedLinks(); - assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST); - assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0)); - - verify(mMockDnsResolver, times(1)).setResolverConfiguration( - mResolverParamsParcelCaptor.capture()); - ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue(); - assertEquals(1, resolvrParams.servers.length); - assertTrue(ArrayUtils.contains(resolvrParams.servers, "8.8.8.8")); - - for (final LinkProperties stackedLp : stackedLpsAfterChange) { - verify(mDeps).reportNetworkInterfaceForTransports( - mServiceContext, stackedLp.getInterfaceName(), - new int[] { TRANSPORT_CELLULAR }); - } - reset(mMockNetd); - when(mMockNetd.interfaceGetCfg(CLAT_PREFIX + MOBILE_IFNAME)) - .thenReturn(getClatInterfaceConfigParcel(myIpv4)); - // Change the NAT64 prefix without first removing it. - // Expect clatd to be stopped and started with the new prefix. - mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent( - cellNetId, PREFIX_OPERATION_ADDED, kOtherNat64PrefixString, 96)); - networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, - (lp) -> lp.getStackedLinks().size() == 0); - verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME); - assertRoutesRemoved(cellNetId, stackedDefault); - verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_PREFIX + MOBILE_IFNAME); - - verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kOtherNat64Prefix.toString()); - networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, - (lp) -> lp.getNat64Prefix().equals(kOtherNat64Prefix)); - clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true); - networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, - (lp) -> lp.getStackedLinks().size() == 1); - assertRoutesAdded(cellNetId, stackedDefault); - verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_PREFIX + MOBILE_IFNAME); - reset(mMockNetd); - - // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked - // linkproperties are cleaned up. - cellLp.addLinkAddress(myIpv4); - cellLp.addRoute(ipv4Subnet); - mCellNetworkAgent.sendLinkProperties(cellLp); - networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); - assertRoutesAdded(cellNetId, ipv4Subnet); - verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME); - verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId); - - // As soon as stop is called, the linkproperties lose the stacked interface. - networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); - LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork()); - LinkProperties expected = new LinkProperties(cellLp); - expected.setNat64Prefix(kOtherNat64Prefix); - assertEquals(expected, actualLpAfterIpv4); - assertEquals(0, actualLpAfterIpv4.getStackedLinks().size()); - assertRoutesRemoved(cellNetId, stackedDefault); - - // The interface removed callback happens but has no effect after stop is called. - clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME); - networkCallback.assertNoCallback(); - verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_PREFIX + MOBILE_IFNAME); - verifyNoMoreInteractions(mMockNetd); - verifyNoMoreInteractions(mMockDnsResolver); - reset(mMockNetd); - reset(mMockDnsResolver); - when(mMockNetd.interfaceGetCfg(CLAT_PREFIX + MOBILE_IFNAME)) - .thenReturn(getClatInterfaceConfigParcel(myIpv4)); - - // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone. - mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent( - cellNetId, PREFIX_OPERATION_REMOVED, kOtherNat64PrefixString, 96)); - networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, - (lp) -> lp.getNat64Prefix() == null); - - // Remove IPv4 address and expect prefix discovery and clatd to be started again. - cellLp.removeLinkAddress(myIpv4); - cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME)); - cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8")); - mCellNetworkAgent.sendLinkProperties(cellLp); - networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); - assertRoutesRemoved(cellNetId, ipv4Subnet); // Directly-connected routes auto-added. - verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId); - mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent( - cellNetId, PREFIX_OPERATION_ADDED, kNat64PrefixString, 96)); - networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); - verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString()); - - // Clat iface comes up. Expect stacked link to be added. - clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true); - networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, - (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null); - assertRoutesAdded(cellNetId, stackedDefault); - verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_PREFIX + MOBILE_IFNAME); - - // NAT64 prefix is removed. Expect that clat is stopped. - mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent( - cellNetId, PREFIX_OPERATION_REMOVED, kNat64PrefixString, 96)); - networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, - (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null); - assertRoutesRemoved(cellNetId, ipv4Subnet, stackedDefault); - - // Stop has no effect because clat is already stopped. - verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME); - networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, - (lp) -> lp.getStackedLinks().size() == 0); - verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_PREFIX + MOBILE_IFNAME); - verify(mMockNetd, times(1)).interfaceGetCfg(CLAT_PREFIX + MOBILE_IFNAME); - verifyNoMoreInteractions(mMockNetd); - // Clean up. - mCellNetworkAgent.disconnect(); - networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - networkCallback.assertNoCallback(); - mCm.unregisterNetworkCallback(networkCallback); - } - - private void expectNat64PrefixChange(TestableNetworkCallback callback, - TestNetworkAgentWrapper agent, IpPrefix prefix) { - callback.expectLinkPropertiesThat(agent, x -> Objects.equals(x.getNat64Prefix(), prefix)); - } - - @Test - public void testNat64PrefixMultipleSources() throws Exception { - final String iface = "wlan0"; - final String pref64FromRaStr = "64:ff9b::"; - final String pref64FromDnsStr = "2001:db8:64::"; - final IpPrefix pref64FromRa = new IpPrefix(InetAddress.getByName(pref64FromRaStr), 96); - final IpPrefix pref64FromDns = new IpPrefix(InetAddress.getByName(pref64FromDnsStr), 96); - final IpPrefix newPref64FromRa = new IpPrefix("2001:db8:64:64:64:64::/96"); - - final NetworkRequest request = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_INTERNET) - .build(); - final TestNetworkCallback callback = new TestNetworkCallback(); - mCm.registerNetworkCallback(request, callback); - - final LinkProperties baseLp = new LinkProperties(); - baseLp.setInterfaceName(iface); - baseLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64")); - baseLp.addDnsServer(InetAddress.getByName("2001:4860:4860::6464")); - - reset(mMockNetd, mMockDnsResolver); - InOrder inOrder = inOrder(mMockNetd, mMockDnsResolver); - - // If a network already has a NAT64 prefix on connect, clatd is started immediately and - // prefix discovery is never started. - LinkProperties lp = new LinkProperties(baseLp); - lp.setNat64Prefix(pref64FromRa); - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp); - mWiFiNetworkAgent.connect(false); - final Network network = mWiFiNetworkAgent.getNetwork(); - int netId = network.getNetId(); - callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString()); - inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString()); - inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); - callback.assertNoCallback(); - assertEquals(pref64FromRa, mCm.getLinkProperties(network).getNat64Prefix()); - - // If the RA prefix is withdrawn, clatd is stopped and prefix discovery is started. - lp.setNat64Prefix(null); - mWiFiNetworkAgent.sendLinkProperties(lp); - expectNat64PrefixChange(callback, mWiFiNetworkAgent, null); - inOrder.verify(mMockNetd).clatdStop(iface); - inOrder.verify(mMockDnsResolver).setPrefix64(netId, ""); - inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId); - - // If the RA prefix appears while DNS discovery is in progress, discovery is stopped and - // clatd is started with the prefix from the RA. - lp.setNat64Prefix(pref64FromRa); - mWiFiNetworkAgent.sendLinkProperties(lp); - expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromRa); - inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString()); - inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId); - inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString()); - - // Withdraw the RA prefix so we can test the case where an RA prefix appears after DNS - // discovery has succeeded. - lp.setNat64Prefix(null); - mWiFiNetworkAgent.sendLinkProperties(lp); - expectNat64PrefixChange(callback, mWiFiNetworkAgent, null); - inOrder.verify(mMockNetd).clatdStop(iface); - inOrder.verify(mMockDnsResolver).setPrefix64(netId, ""); - inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId); - - mService.mResolverUnsolEventCallback.onNat64PrefixEvent( - makeNat64PrefixEvent(netId, PREFIX_OPERATION_ADDED, pref64FromDnsStr, 96)); - expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromDns); - inOrder.verify(mMockNetd).clatdStart(iface, pref64FromDns.toString()); - - // If an RA advertises the same prefix that was discovered by DNS, nothing happens: prefix - // discovery is not stopped, and there are no callbacks. - lp.setNat64Prefix(pref64FromDns); - mWiFiNetworkAgent.sendLinkProperties(lp); - callback.assertNoCallback(); - inOrder.verify(mMockNetd, never()).clatdStop(iface); - inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString()); - inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId); - inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); - inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString()); - - // If the RA is later withdrawn, nothing happens again. - lp.setNat64Prefix(null); - mWiFiNetworkAgent.sendLinkProperties(lp); - callback.assertNoCallback(); - inOrder.verify(mMockNetd, never()).clatdStop(iface); - inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString()); - inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId); - inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); - inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString()); - - // If the RA prefix changes, clatd is restarted and prefix discovery is stopped. - lp.setNat64Prefix(pref64FromRa); - mWiFiNetworkAgent.sendLinkProperties(lp); - expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromRa); - inOrder.verify(mMockNetd).clatdStop(iface); - inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId); - - // Stopping prefix discovery results in a prefix removed notification. - mService.mResolverUnsolEventCallback.onNat64PrefixEvent( - makeNat64PrefixEvent(netId, PREFIX_OPERATION_REMOVED, pref64FromDnsStr, 96)); - - inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString()); - inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString()); - inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); - - // If the RA prefix changes, clatd is restarted and prefix discovery is not started. - lp.setNat64Prefix(newPref64FromRa); - mWiFiNetworkAgent.sendLinkProperties(lp); - expectNat64PrefixChange(callback, mWiFiNetworkAgent, newPref64FromRa); - inOrder.verify(mMockNetd).clatdStop(iface); - inOrder.verify(mMockDnsResolver).setPrefix64(netId, ""); - inOrder.verify(mMockNetd).clatdStart(iface, newPref64FromRa.toString()); - inOrder.verify(mMockDnsResolver).setPrefix64(netId, newPref64FromRa.toString()); - inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId); - inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); - - // If the RA prefix changes to the same value, nothing happens. - lp.setNat64Prefix(newPref64FromRa); - mWiFiNetworkAgent.sendLinkProperties(lp); - callback.assertNoCallback(); - assertEquals(newPref64FromRa, mCm.getLinkProperties(network).getNat64Prefix()); - inOrder.verify(mMockNetd, never()).clatdStop(iface); - inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString()); - inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId); - inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); - inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString()); - - // The transition between no prefix and DNS prefix is tested in testStackedLinkProperties. - - // If the same prefix is learned first by DNS and then by RA, and clat is later stopped, - // (e.g., because the network disconnects) setPrefix64(netid, "") is never called. - lp.setNat64Prefix(null); - mWiFiNetworkAgent.sendLinkProperties(lp); - expectNat64PrefixChange(callback, mWiFiNetworkAgent, null); - inOrder.verify(mMockNetd).clatdStop(iface); - inOrder.verify(mMockDnsResolver).setPrefix64(netId, ""); - inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId); - mService.mResolverUnsolEventCallback.onNat64PrefixEvent( - makeNat64PrefixEvent(netId, PREFIX_OPERATION_ADDED, pref64FromDnsStr, 96)); - expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromDns); - inOrder.verify(mMockNetd).clatdStart(iface, pref64FromDns.toString()); - inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), any()); - - lp.setNat64Prefix(pref64FromDns); - mWiFiNetworkAgent.sendLinkProperties(lp); - callback.assertNoCallback(); - inOrder.verify(mMockNetd, never()).clatdStop(iface); - inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString()); - inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId); - inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); - inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString()); - - // When tearing down a network, clat state is only updated after CALLBACK_LOST is fired, but - // before CONNECTIVITY_ACTION is sent. Wait for CONNECTIVITY_ACTION before verifying that - // clat has been stopped, or the test will be flaky. - ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED); - mWiFiNetworkAgent.disconnect(); - callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - b.expectBroadcast(); - - inOrder.verify(mMockNetd).clatdStop(iface); - inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId); - inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString()); - - mCm.unregisterNetworkCallback(callback); - } - - @Test - public void testWith464XlatDisable() throws Exception { - doReturn(false).when(mDeps).getCellular464XlatEnabled(); - - final TestNetworkCallback callback = new TestNetworkCallback(); - final TestNetworkCallback defaultCallback = new TestNetworkCallback(); - final NetworkRequest networkRequest = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_INTERNET) - .build(); - mCm.registerNetworkCallback(networkRequest, callback); - mCm.registerDefaultNetworkCallback(defaultCallback); - - // Bring up validated cell. - final LinkProperties cellLp = new LinkProperties(); - cellLp.setInterfaceName(MOBILE_IFNAME); - cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64")); - cellLp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, MOBILE_IFNAME)); - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - - mCellNetworkAgent.sendLinkProperties(cellLp); - mCellNetworkAgent.connect(true); - callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - final int cellNetId = mCellNetworkAgent.getNetwork().netId; - waitForIdle(); - - verify(mMockDnsResolver, never()).startPrefix64Discovery(cellNetId); - Nat464Xlat clat = getNat464Xlat(mCellNetworkAgent); - assertTrue("Nat464Xlat was not IDLE", !clat.isStarted()); - - // This cannot happen because prefix discovery cannot succeed if it is never started. - mService.mResolverUnsolEventCallback.onNat64PrefixEvent( - makeNat64PrefixEvent(cellNetId, PREFIX_OPERATION_ADDED, "64:ff9b::", 96)); - - // ... but still, check that even if it did, clatd would not be started. - verify(mMockNetd, never()).clatdStart(anyString(), anyString()); - assertTrue("Nat464Xlat was not IDLE", !clat.isStarted()); - } - - @Test - public void testDataActivityTracking() throws Exception { - final TestNetworkCallback networkCallback = new TestNetworkCallback(); - final NetworkRequest networkRequest = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_INTERNET) - .build(); - mCm.registerNetworkCallback(networkRequest, networkCallback); - - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - final LinkProperties cellLp = new LinkProperties(); - cellLp.setInterfaceName(MOBILE_IFNAME); - mCellNetworkAgent.sendLinkProperties(cellLp); - mCellNetworkAgent.connect(true); - networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - verify(mMockNetd, times(1)).idletimerAddInterface(eq(MOBILE_IFNAME), anyInt(), - eq(Integer.toString(TRANSPORT_CELLULAR))); - - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - final LinkProperties wifiLp = new LinkProperties(); - wifiLp.setInterfaceName(WIFI_IFNAME); - mWiFiNetworkAgent.sendLinkProperties(wifiLp); - - // Network switch - mWiFiNetworkAgent.connect(true); - networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); - networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); - verify(mMockNetd, times(1)).idletimerAddInterface(eq(WIFI_IFNAME), anyInt(), - eq(Integer.toString(TRANSPORT_WIFI))); - verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(), - eq(Integer.toString(TRANSPORT_CELLULAR))); - - // Disconnect wifi and switch back to cell - reset(mMockNetd); - mWiFiNetworkAgent.disconnect(); - networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - assertNoCallbacks(networkCallback); - verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(WIFI_IFNAME), anyInt(), - eq(Integer.toString(TRANSPORT_WIFI))); - verify(mMockNetd, times(1)).idletimerAddInterface(eq(MOBILE_IFNAME), anyInt(), - eq(Integer.toString(TRANSPORT_CELLULAR))); - - // reconnect wifi - reset(mMockNetd); - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - wifiLp.setInterfaceName(WIFI_IFNAME); - mWiFiNetworkAgent.sendLinkProperties(wifiLp); - mWiFiNetworkAgent.connect(true); - networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); - networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); - verify(mMockNetd, times(1)).idletimerAddInterface(eq(WIFI_IFNAME), anyInt(), - eq(Integer.toString(TRANSPORT_WIFI))); - verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(), - eq(Integer.toString(TRANSPORT_CELLULAR))); - - // Disconnect cell - reset(mMockNetd); - mCellNetworkAgent.disconnect(); - networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - // LOST callback is triggered earlier than removing idle timer. Broadcast should also be - // sent as network being switched. Ensure rule removal for cell will not be triggered - // unexpectedly before network being removed. - waitForIdle(); - verify(mMockNetd, times(0)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(), - eq(Integer.toString(TRANSPORT_CELLULAR))); - verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId)); - verify(mMockDnsResolver, times(1)) - .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId)); - - // Disconnect wifi - ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED); - mWiFiNetworkAgent.disconnect(); - b.expectBroadcast(); - verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(WIFI_IFNAME), anyInt(), - eq(Integer.toString(TRANSPORT_WIFI))); - - // Clean up - mCm.unregisterNetworkCallback(networkCallback); - } - - private void verifyTcpBufferSizeChange(String tcpBufferSizes) throws Exception { - String[] values = tcpBufferSizes.split(","); - String rmemValues = String.join(" ", values[0], values[1], values[2]); - String wmemValues = String.join(" ", values[3], values[4], values[5]); - verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues); - reset(mMockNetd); - } - - @Test - public void testTcpBufferReset() throws Exception { - final String testTcpBufferSizes = "1,2,3,4,5,6"; - final NetworkRequest networkRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR) - .addCapability(NET_CAPABILITY_INTERNET) - .build(); - final TestNetworkCallback networkCallback = new TestNetworkCallback(); - mCm.registerNetworkCallback(networkRequest, networkCallback); - - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - reset(mMockNetd); - // Switching default network updates TCP buffer sizes. - mCellNetworkAgent.connect(false); - networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); - verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES); - // Change link Properties should have updated tcp buffer size. - LinkProperties lp = new LinkProperties(); - lp.setTcpBufferSizes(testTcpBufferSizes); - mCellNetworkAgent.sendLinkProperties(lp); - networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); - verifyTcpBufferSizeChange(testTcpBufferSizes); - // Clean up. - mCellNetworkAgent.disconnect(); - networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - networkCallback.assertNoCallback(); - mCm.unregisterNetworkCallback(networkCallback); - } - - @Test - public void testGetGlobalProxyForNetwork() throws Exception { - final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888); - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - final Network wifiNetwork = mWiFiNetworkAgent.getNetwork(); - when(mService.mProxyTracker.getGlobalProxy()).thenReturn(testProxyInfo); - assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork)); - } - - @Test - public void testGetProxyForActiveNetwork() throws Exception { - final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888); - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true); - waitForIdle(); - assertNull(mService.getProxyForNetwork(null)); - - final LinkProperties testLinkProperties = new LinkProperties(); - testLinkProperties.setHttpProxy(testProxyInfo); - - mWiFiNetworkAgent.sendLinkProperties(testLinkProperties); - waitForIdle(); - - assertEquals(testProxyInfo, mService.getProxyForNetwork(null)); - } - - @Test - public void testGetProxyForVPN() throws Exception { - final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888); - - // Set up a WiFi network with no proxy - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true); - waitForIdle(); - assertNull(mService.getProxyForNetwork(null)); - - // Connect a VPN network with a proxy. - LinkProperties testLinkProperties = new LinkProperties(); - testLinkProperties.setHttpProxy(testProxyInfo); - mMockVpn.establishForMyUid(testLinkProperties); - assertUidRangesUpdatedForMyUid(true); - - // Test that the VPN network returns a proxy, and the WiFi does not. - assertEquals(testProxyInfo, mService.getProxyForNetwork(mMockVpn.getNetwork())); - assertEquals(testProxyInfo, mService.getProxyForNetwork(null)); - assertNull(mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork())); - - // Test that the VPN network returns no proxy when it is set to null. - testLinkProperties.setHttpProxy(null); - mMockVpn.sendLinkProperties(testLinkProperties); - waitForIdle(); - assertNull(mService.getProxyForNetwork(mMockVpn.getNetwork())); - assertNull(mService.getProxyForNetwork(null)); - - // Set WiFi proxy and check that the vpn proxy is still null. - testLinkProperties.setHttpProxy(testProxyInfo); - mWiFiNetworkAgent.sendLinkProperties(testLinkProperties); - waitForIdle(); - assertNull(mService.getProxyForNetwork(null)); - - // Disconnect from VPN and check that the active network, which is now the WiFi, has the - // correct proxy setting. - mMockVpn.disconnect(); - waitForIdle(); - assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - assertEquals(testProxyInfo, mService.getProxyForNetwork(mWiFiNetworkAgent.getNetwork())); - assertEquals(testProxyInfo, mService.getProxyForNetwork(null)); - } - - @Test - public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception { - LinkProperties lp = new LinkProperties(); - lp.setInterfaceName("tun0"); - lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null)); - lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE)); - // The uid range needs to cover the test app so the network is visible to it. - final Set vpnRange = Collections.singleton(PRIMARY_UIDRANGE); - mMockVpn.establish(lp, VPN_UID, vpnRange); - assertVpnUidRangesUpdated(true, vpnRange, VPN_UID); - - // A connected VPN should have interface rules set up. There are two expected invocations, - // one during the VPN initial connection, one during the VPN LinkProperties update. - ArgumentCaptor uidCaptor = ArgumentCaptor.forClass(int[].class); - verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture()); - assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID); - assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID); - assertTrue(mService.mPermissionMonitor.getVpnUidRanges("tun0").equals(vpnRange)); - - mMockVpn.disconnect(); - waitForIdle(); - - // Disconnected VPN should have interface rules removed - verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture()); - assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID); - assertNull(mService.mPermissionMonitor.getVpnUidRanges("tun0")); - } - - @Test - public void testLegacyVpnDoesNotResultInInterfaceFilteringRule() throws Exception { - LinkProperties lp = new LinkProperties(); - lp.setInterfaceName("tun0"); - lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null)); - lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null)); - // The uid range needs to cover the test app so the network is visible to it. - final Set vpnRange = Collections.singleton(PRIMARY_UIDRANGE); - mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange); - assertVpnUidRangesUpdated(true, vpnRange, Process.SYSTEM_UID); - - // Legacy VPN should not have interface rules set up - verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any()); - } - - @Test - public void testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule() - throws Exception { - LinkProperties lp = new LinkProperties(); - lp.setInterfaceName("tun0"); - lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0")); - lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE)); - // The uid range needs to cover the test app so the network is visible to it. - final Set vpnRange = Collections.singleton(PRIMARY_UIDRANGE); - mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange); - assertVpnUidRangesUpdated(true, vpnRange, Process.SYSTEM_UID); - - // IPv6 unreachable route should not be misinterpreted as a default route - verify(mMockNetd, never()).firewallAddUidInterfaceRules(any(), any()); - } - - @Test - public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception { - LinkProperties lp = new LinkProperties(); - lp.setInterfaceName("tun0"); - lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null)); - lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null)); - // The uid range needs to cover the test app so the network is visible to it. - final Set vpnRange = Collections.singleton(PRIMARY_UIDRANGE); - mMockVpn.establish(lp, VPN_UID, vpnRange); - assertVpnUidRangesUpdated(true, vpnRange, VPN_UID); - - // Connected VPN should have interface rules set up. There are two expected invocations, - // one during VPN uid update, one during VPN LinkProperties update - ArgumentCaptor uidCaptor = ArgumentCaptor.forClass(int[].class); - verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture()); - assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID); - assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID); - - reset(mMockNetd); - InOrder inOrder = inOrder(mMockNetd); - lp.setInterfaceName("tun1"); - mMockVpn.sendLinkProperties(lp); - waitForIdle(); - // VPN handover (switch to a new interface) should result in rules being updated (old rules - // removed first, then new rules added) - inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture()); - assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID); - inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture()); - assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID); - - reset(mMockNetd); - lp = new LinkProperties(); - lp.setInterfaceName("tun1"); - lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun1")); - mMockVpn.sendLinkProperties(lp); - waitForIdle(); - // VPN not routing everything should no longer have interface filtering rules - verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture()); - assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID); - - reset(mMockNetd); - lp = new LinkProperties(); - lp.setInterfaceName("tun1"); - lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE)); - lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null)); - mMockVpn.sendLinkProperties(lp); - waitForIdle(); - // Back to routing all IPv6 traffic should have filtering rules - verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun1"), uidCaptor.capture()); - assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID); - } - - @Test - public void testUidUpdateChangesInterfaceFilteringRule() throws Exception { - LinkProperties lp = new LinkProperties(); - lp.setInterfaceName("tun0"); - lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE)); - lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null)); - // The uid range needs to cover the test app so the network is visible to it. - final UidRange vpnRange = PRIMARY_UIDRANGE; - final Set vpnRanges = Collections.singleton(vpnRange); - mMockVpn.establish(lp, VPN_UID, vpnRanges); - assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID); - - reset(mMockNetd); - InOrder inOrder = inOrder(mMockNetd); - - // Update to new range which is old range minus APP1, i.e. only APP2 - final Set newRanges = new HashSet<>(Arrays.asList( - new UidRange(vpnRange.start, APP1_UID - 1), - new UidRange(APP1_UID + 1, vpnRange.stop))); - mMockVpn.setUids(newRanges); - waitForIdle(); - - ArgumentCaptor uidCaptor = ArgumentCaptor.forClass(int[].class); - // Verify old rules are removed before new rules are added - inOrder.verify(mMockNetd).firewallRemoveUidInterfaceRules(uidCaptor.capture()); - assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID); - inOrder.verify(mMockNetd).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture()); - assertContainsExactly(uidCaptor.getValue(), APP2_UID); - } - - @Test - public void testLinkPropertiesWithWakeOnLanForActiveNetwork() throws Exception { - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - - LinkProperties wifiLp = new LinkProperties(); - wifiLp.setInterfaceName(WIFI_WOL_IFNAME); - wifiLp.setWakeOnLanSupported(false); - - // Default network switch should update ifaces. - mWiFiNetworkAgent.connect(false); - mWiFiNetworkAgent.sendLinkProperties(wifiLp); - waitForIdle(); - - // ConnectivityService should have changed the WakeOnLanSupported to true - wifiLp.setWakeOnLanSupported(true); - assertEquals(wifiLp, mService.getActiveLinkProperties()); - } - - @Test - public void testLegacyExtraInfoSentToNetworkMonitor() throws Exception { - class TestNetworkAgent extends NetworkAgent { - TestNetworkAgent(Context context, Looper looper, NetworkAgentConfig config) { - super(context, looper, "MockAgent", new NetworkCapabilities(), - new LinkProperties(), 40 , config, null /* provider */); - } - } - final NetworkAgent naNoExtraInfo = new TestNetworkAgent( - mServiceContext, mCsHandlerThread.getLooper(), new NetworkAgentConfig()); - naNoExtraInfo.register(); - verify(mNetworkStack).makeNetworkMonitor(any(), isNull(String.class), any()); - naNoExtraInfo.unregister(); - - reset(mNetworkStack); - final NetworkAgentConfig config = - new NetworkAgentConfig.Builder().setLegacyExtraInfo("legacyinfo").build(); - final NetworkAgent naExtraInfo = new TestNetworkAgent( - mServiceContext, mCsHandlerThread.getLooper(), config); - naExtraInfo.register(); - verify(mNetworkStack).makeNetworkMonitor(any(), eq("legacyinfo"), any()); - naExtraInfo.unregister(); - } - - // To avoid granting location permission bypass. - private void denyAllLocationPrivilegedPermissions() { - mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, - PERMISSION_DENIED); - mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED); - mServiceContext.setPermission(Manifest.permission.NETWORK_STACK, - PERMISSION_DENIED); - mServiceContext.setPermission(Manifest.permission.NETWORK_SETUP_WIZARD, - PERMISSION_DENIED); - } - - private void setupLocationPermissions( - int targetSdk, boolean locationToggle, String op, String perm) throws Exception { - denyAllLocationPrivilegedPermissions(); - - final ApplicationInfo applicationInfo = new ApplicationInfo(); - applicationInfo.targetSdkVersion = targetSdk; - when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any())) - .thenReturn(applicationInfo); - when(mPackageManager.getTargetSdkVersion(any())).thenReturn(targetSdk); - - when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(locationToggle); - - if (op != null) { - when(mAppOpsManager.noteOp(eq(op), eq(Process.myUid()), - eq(mContext.getPackageName()), eq(getAttributionTag()), anyString())) - .thenReturn(AppOpsManager.MODE_ALLOWED); - } - - if (perm != null) { - mServiceContext.setPermission(perm, PERMISSION_GRANTED); - } - } - - private int getOwnerUidNetCapsPermission(int ownerUid, int callerUid, - boolean includeLocationSensitiveInfo) { - final NetworkCapabilities netCap = new NetworkCapabilities().setOwnerUid(ownerUid); - - return mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled( - netCap, includeLocationSensitiveInfo, Process.myUid(), callerUid, - mContext.getPackageName(), getAttributionTag()) - .getOwnerUid(); - } - - private void verifyTransportInfoCopyNetCapsPermission( - int callerUid, boolean includeLocationSensitiveInfo, - boolean shouldMakeCopyWithLocationSensitiveFieldsParcelable) { - final TransportInfo transportInfo = mock(TransportInfo.class); - when(transportInfo.getApplicableRedactions()).thenReturn(REDACT_FOR_ACCESS_FINE_LOCATION); - final NetworkCapabilities netCap = - new NetworkCapabilities().setTransportInfo(transportInfo); - - mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled( - netCap, includeLocationSensitiveInfo, Process.myPid(), callerUid, - mContext.getPackageName(), getAttributionTag()); - if (shouldMakeCopyWithLocationSensitiveFieldsParcelable) { - verify(transportInfo).makeCopy(REDACT_NONE); - } else { - verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION); - } - } - - private void verifyOwnerUidAndTransportInfoNetCapsPermission( - boolean shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag, - boolean shouldInclLocationSensitiveOwnerUidWithIncludeFlag, - boolean shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag, - boolean shouldInclLocationSensitiveTransportInfoWithIncludeFlag) { - final int myUid = Process.myUid(); - - final int expectedOwnerUidWithoutIncludeFlag = - shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag - ? myUid : INVALID_UID; - assertEquals(expectedOwnerUidWithoutIncludeFlag, getOwnerUidNetCapsPermission( - myUid, myUid, false /* includeLocationSensitiveInfo */)); - - final int expectedOwnerUidWithIncludeFlag = - shouldInclLocationSensitiveOwnerUidWithIncludeFlag ? myUid : INVALID_UID; - assertEquals(expectedOwnerUidWithIncludeFlag, getOwnerUidNetCapsPermission( - myUid, myUid, true /* includeLocationSensitiveInfo */)); - - verifyTransportInfoCopyNetCapsPermission(myUid, - false, /* includeLocationSensitiveInfo */ - shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag); - - verifyTransportInfoCopyNetCapsPermission(myUid, - true, /* includeLocationSensitiveInfo */ - shouldInclLocationSensitiveTransportInfoWithIncludeFlag); - - } - - private void verifyOwnerUidAndTransportInfoNetCapsPermissionPreS() { - verifyOwnerUidAndTransportInfoNetCapsPermission( - // Ensure that owner uid is included even if the request asks to remove it (which is - // the default) since the app has necessary permissions and targetSdk < S. - true, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ - true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ - // Ensure that location info is removed if the request asks to remove it even if the - // app has necessary permissions. - false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */ - true /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */ - ); - } - - @Test - public void testCreateWithLocationInfoSanitizedWithFineLocationAfterQPreS() - throws Exception { - setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, - Manifest.permission.ACCESS_FINE_LOCATION); - - verifyOwnerUidAndTransportInfoNetCapsPermissionPreS(); - } - - @Test - public void testCreateWithLocationInfoSanitizedWithFineLocationPreSWithAndWithoutCallbackFlag() - throws Exception { - setupLocationPermissions(Build.VERSION_CODES.R, true, AppOpsManager.OPSTR_FINE_LOCATION, - Manifest.permission.ACCESS_FINE_LOCATION); - - verifyOwnerUidAndTransportInfoNetCapsPermissionPreS(); - } - - @Test - public void - testCreateWithLocationInfoSanitizedWithFineLocationAfterSWithAndWithoutCallbackFlag() - throws Exception { - setupLocationPermissions(Build.VERSION_CODES.S, true, AppOpsManager.OPSTR_FINE_LOCATION, - Manifest.permission.ACCESS_FINE_LOCATION); - - verifyOwnerUidAndTransportInfoNetCapsPermission( - // Ensure that the owner UID is removed if the request asks us to remove it even - // if the app has necessary permissions since targetSdk >= S. - false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ - true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ - // Ensure that location info is removed if the request asks to remove it even if the - // app has necessary permissions. - false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */ - true /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */ - ); - } - - @Test - public void testCreateWithLocationInfoSanitizedWithCoarseLocationPreQ() - throws Exception { - setupLocationPermissions(Build.VERSION_CODES.P, true, AppOpsManager.OPSTR_COARSE_LOCATION, - Manifest.permission.ACCESS_COARSE_LOCATION); - - verifyOwnerUidAndTransportInfoNetCapsPermissionPreS(); - } - - private void verifyOwnerUidAndTransportInfoNetCapsNotIncluded() { - verifyOwnerUidAndTransportInfoNetCapsPermission( - false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */ - false, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */ - false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */ - false /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */ - ); - } - - @Test - public void testCreateWithLocationInfoSanitizedLocationOff() throws Exception { - // Test that even with fine location permission, and UIDs matching, the UID is sanitized. - setupLocationPermissions(Build.VERSION_CODES.Q, false, AppOpsManager.OPSTR_FINE_LOCATION, - Manifest.permission.ACCESS_FINE_LOCATION); - - verifyOwnerUidAndTransportInfoNetCapsNotIncluded(); - } - - @Test - public void testCreateWithLocationInfoSanitizedWrongUid() throws Exception { - // Test that even with fine location permission, not being the owner leads to sanitization. - setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, - Manifest.permission.ACCESS_FINE_LOCATION); - - final int myUid = Process.myUid(); - assertEquals(Process.INVALID_UID, - getOwnerUidNetCapsPermission(myUid + 1, myUid, - true /* includeLocationSensitiveInfo */)); - } - - @Test - public void testCreateWithLocationInfoSanitizedWithCoarseLocationAfterQ() - throws Exception { - // Test that not having fine location permission leads to sanitization. - setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_COARSE_LOCATION, - Manifest.permission.ACCESS_COARSE_LOCATION); - - verifyOwnerUidAndTransportInfoNetCapsNotIncluded(); - } - - @Test - public void testCreateWithLocationInfoSanitizedWithCoarseLocationAfterS() - throws Exception { - // Test that not having fine location permission leads to sanitization. - setupLocationPermissions(Build.VERSION_CODES.S, true, AppOpsManager.OPSTR_COARSE_LOCATION, - Manifest.permission.ACCESS_COARSE_LOCATION); - - verifyOwnerUidAndTransportInfoNetCapsNotIncluded(); - } - - @Test - public void testCreateForCallerWithLocalMacAddressSanitizedWithLocalMacAddressPermission() - throws Exception { - mServiceContext.setPermission(Manifest.permission.LOCAL_MAC_ADDRESS, PERMISSION_GRANTED); - - final TransportInfo transportInfo = mock(TransportInfo.class); - when(transportInfo.getApplicableRedactions()) - .thenReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS); - final NetworkCapabilities netCap = - new NetworkCapabilities().setTransportInfo(transportInfo); - - mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled( - netCap, false /* includeLocationSensitiveInfoInTransportInfo */, - Process.myPid(), Process.myUid(), - mContext.getPackageName(), getAttributionTag()); - // don't redact MAC_ADDRESS fields, only location sensitive fields. - verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION); - } - - @Test - public void testCreateForCallerWithLocalMacAddressSanitizedWithoutLocalMacAddressPermission() - throws Exception { - mServiceContext.setPermission(Manifest.permission.LOCAL_MAC_ADDRESS, PERMISSION_DENIED); - - final TransportInfo transportInfo = mock(TransportInfo.class); - when(transportInfo.getApplicableRedactions()) - .thenReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS); - final NetworkCapabilities netCap = - new NetworkCapabilities().setTransportInfo(transportInfo); - - mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled( - netCap, false /* includeLocationSensitiveInfoInTransportInfo */, - Process.myPid(), Process.myUid(), - mContext.getPackageName(), getAttributionTag()); - // redact both MAC_ADDRESS & location sensitive fields. - verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION - | REDACT_FOR_LOCAL_MAC_ADDRESS); - } - - @Test - public void testCreateForCallerWithLocalMacAddressSanitizedWithSettingsPermission() - throws Exception { - mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED); - - final TransportInfo transportInfo = mock(TransportInfo.class); - when(transportInfo.getApplicableRedactions()) - .thenReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS); - final NetworkCapabilities netCap = - new NetworkCapabilities().setTransportInfo(transportInfo); - - mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled( - netCap, false /* includeLocationSensitiveInfoInTransportInfo */, - Process.myPid(), Process.myUid(), - mContext.getPackageName(), getAttributionTag()); - // don't redact NETWORK_SETTINGS fields, only location sensitive fields. - verify(transportInfo).makeCopy(REDACT_FOR_ACCESS_FINE_LOCATION); - } - - @Test - public void testCreateForCallerWithLocalMacAddressSanitizedWithoutSettingsPermission() - throws Exception { - mServiceContext.setPermission(Manifest.permission.LOCAL_MAC_ADDRESS, PERMISSION_DENIED); - - final TransportInfo transportInfo = mock(TransportInfo.class); - when(transportInfo.getApplicableRedactions()) - .thenReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS); - final NetworkCapabilities netCap = - new NetworkCapabilities().setTransportInfo(transportInfo); - - mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled( - netCap, false /* includeLocationSensitiveInfoInTransportInfo */, - Process.myPid(), Process.myUid(), - mContext.getPackageName(), getAttributionTag()); - // redact both NETWORK_SETTINGS & location sensitive fields. - verify(transportInfo).makeCopy( - REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS); - } - - /** - * Test TransportInfo to verify redaction mechanism. - */ - private static class TestTransportInfo implements TransportInfo { - public final boolean locationRedacted; - public final boolean localMacAddressRedacted; - public final boolean settingsRedacted; - - TestTransportInfo() { - locationRedacted = false; - localMacAddressRedacted = false; - settingsRedacted = false; - } - - TestTransportInfo(boolean locationRedacted, boolean localMacAddressRedacted, - boolean settingsRedacted) { - this.locationRedacted = locationRedacted; - this.localMacAddressRedacted = - localMacAddressRedacted; - this.settingsRedacted = settingsRedacted; - } - - @Override - public TransportInfo makeCopy(@NetworkCapabilities.RedactionType long redactions) { - return new TestTransportInfo( - locationRedacted | (redactions & REDACT_FOR_ACCESS_FINE_LOCATION) != 0, - localMacAddressRedacted | (redactions & REDACT_FOR_LOCAL_MAC_ADDRESS) != 0, - settingsRedacted | (redactions & REDACT_FOR_NETWORK_SETTINGS) != 0 - ); - } - - @Override - public @NetworkCapabilities.RedactionType long getApplicableRedactions() { - return REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS - | REDACT_FOR_NETWORK_SETTINGS; - } - - @Override - public boolean equals(Object other) { - if (!(other instanceof TestTransportInfo)) return false; - TestTransportInfo that = (TestTransportInfo) other; - return that.locationRedacted == this.locationRedacted - && that.localMacAddressRedacted == this.localMacAddressRedacted - && that.settingsRedacted == this.settingsRedacted; - } - - @Override - public int hashCode() { - return Objects.hash(locationRedacted, localMacAddressRedacted, settingsRedacted); - } - - @Override - public String toString() { - return String.format( - "TestTransportInfo{locationRedacted=%s macRedacted=%s settingsRedacted=%s}", - locationRedacted, localMacAddressRedacted, settingsRedacted); - } - } - - private TestTransportInfo getTestTransportInfo(NetworkCapabilities nc) { - return (TestTransportInfo) nc.getTransportInfo(); - } - - private TestTransportInfo getTestTransportInfo(TestNetworkAgentWrapper n) { - final NetworkCapabilities nc = mCm.getNetworkCapabilities(n.getNetwork()); - assertNotNull(nc); - return getTestTransportInfo(nc); - } - - - private void verifyNetworkCallbackLocationDataInclusionUsingTransportInfoAndOwnerUidInNetCaps( - @NonNull TestNetworkCallback wifiNetworkCallback, int actualOwnerUid, - @NonNull TransportInfo actualTransportInfo, int expectedOwnerUid, - @NonNull TransportInfo expectedTransportInfo) throws Exception { - when(mPackageManager.getTargetSdkVersion(anyString())).thenReturn(Build.VERSION_CODES.S); - final NetworkCapabilities ncTemplate = - new NetworkCapabilities() - .addTransportType(TRANSPORT_WIFI) - .setOwnerUid(actualOwnerUid); - - final NetworkRequest wifiRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_WIFI).build(); - mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback); - - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(), - ncTemplate); - mWiFiNetworkAgent.connect(false); - - wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - - // Send network capabilities update with TransportInfo to trigger capabilities changed - // callback. - mWiFiNetworkAgent.setNetworkCapabilities( - ncTemplate.setTransportInfo(actualTransportInfo), true); - - wifiNetworkCallback.expectCapabilitiesThat(mWiFiNetworkAgent, - nc -> Objects.equals(expectedOwnerUid, nc.getOwnerUid()) - && Objects.equals(expectedTransportInfo, nc.getTransportInfo())); - } - - @Test - public void testVerifyLocationDataIsNotIncludedWhenInclFlagNotSet() throws Exception { - final TestNetworkCallback wifiNetworkCallack = new TestNetworkCallback(); - final int ownerUid = Process.myUid(); - final TransportInfo transportInfo = new TestTransportInfo(); - // Even though the test uid holds privileged permissions, mask location fields since - // the callback did not explicitly opt-in to get location data. - final TransportInfo sanitizedTransportInfo = new TestTransportInfo( - true, /* locationRedacted */ - true, /* localMacAddressRedacted */ - true /* settingsRedacted */ - ); - // Should not expect location data since the callback does not set the flag for including - // location data. - verifyNetworkCallbackLocationDataInclusionUsingTransportInfoAndOwnerUidInNetCaps( - wifiNetworkCallack, ownerUid, transportInfo, INVALID_UID, sanitizedTransportInfo); - } - - @Test - public void testTransportInfoRedactionInSynchronousCalls() throws Exception { - final NetworkCapabilities ncTemplate = new NetworkCapabilities() - .addTransportType(TRANSPORT_WIFI) - .setTransportInfo(new TestTransportInfo()); - - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(), - ncTemplate); - mWiFiNetworkAgent.connect(true /* validated; waits for callback */); - - // NETWORK_SETTINGS redaction is controlled by the NETWORK_SETTINGS permission - assertTrue(getTestTransportInfo(mWiFiNetworkAgent).settingsRedacted); - withPermission(NETWORK_SETTINGS, () -> { - assertFalse(getTestTransportInfo(mWiFiNetworkAgent).settingsRedacted); - }); - assertTrue(getTestTransportInfo(mWiFiNetworkAgent).settingsRedacted); - - // LOCAL_MAC_ADDRESS redaction is controlled by the LOCAL_MAC_ADDRESS permission - assertTrue(getTestTransportInfo(mWiFiNetworkAgent).localMacAddressRedacted); - withPermission(LOCAL_MAC_ADDRESS, () -> { - assertFalse(getTestTransportInfo(mWiFiNetworkAgent).localMacAddressRedacted); - }); - assertTrue(getTestTransportInfo(mWiFiNetworkAgent).localMacAddressRedacted); - - // Synchronous getNetworkCapabilities calls never return unredacted location-sensitive - // information. - assertTrue(getTestTransportInfo(mWiFiNetworkAgent).locationRedacted); - setupLocationPermissions(Build.VERSION_CODES.S, true, AppOpsManager.OPSTR_FINE_LOCATION, - Manifest.permission.ACCESS_FINE_LOCATION); - assertTrue(getTestTransportInfo(mWiFiNetworkAgent).locationRedacted); - denyAllLocationPrivilegedPermissions(); - assertTrue(getTestTransportInfo(mWiFiNetworkAgent).locationRedacted); - } - - private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType) - throws Exception { - final Set vpnRange = Collections.singleton(PRIMARY_UIDRANGE); - mMockVpn.setVpnType(vpnType); - mMockVpn.establish(new LinkProperties(), vpnOwnerUid, vpnRange); - assertVpnUidRangesUpdated(true, vpnRange, vpnOwnerUid); - - final UnderlyingNetworkInfo underlyingNetworkInfo = - new UnderlyingNetworkInfo(vpnOwnerUid, VPN_IFNAME, new ArrayList()); - mMockVpn.setUnderlyingNetworkInfo(underlyingNetworkInfo); - when(mDeps.getConnectionOwnerUid(anyInt(), any(), any())).thenReturn(42); - } - - private void setupConnectionOwnerUidAsVpnApp(int vpnOwnerUid, @VpnManager.VpnType int vpnType) - throws Exception { - setupConnectionOwnerUid(vpnOwnerUid, vpnType); - - // Test as VPN app - mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED); - mServiceContext.setPermission( - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_DENIED); - } - - private ConnectionInfo getTestConnectionInfo() throws Exception { - return new ConnectionInfo( - IPPROTO_TCP, - new InetSocketAddress(InetAddresses.parseNumericAddress("1.2.3.4"), 1234), - new InetSocketAddress(InetAddresses.parseNumericAddress("2.3.4.5"), 2345)); - } - - @Test - public void testGetConnectionOwnerUidPlatformVpn() throws Exception { - final int myUid = Process.myUid(); - setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_PLATFORM); - - assertEquals(INVALID_UID, mService.getConnectionOwnerUid(getTestConnectionInfo())); - } - - @Test - public void testGetConnectionOwnerUidVpnServiceWrongUser() throws Exception { - final int myUid = Process.myUid(); - setupConnectionOwnerUidAsVpnApp(myUid + 1, VpnManager.TYPE_VPN_SERVICE); - - assertEquals(INVALID_UID, mService.getConnectionOwnerUid(getTestConnectionInfo())); - } - - @Test - public void testGetConnectionOwnerUidVpnServiceDoesNotThrow() throws Exception { - final int myUid = Process.myUid(); - setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_SERVICE); - - assertEquals(42, mService.getConnectionOwnerUid(getTestConnectionInfo())); - } - - @Test - public void testGetConnectionOwnerUidVpnServiceNetworkStackDoesNotThrow() throws Exception { - final int myUid = Process.myUid(); - setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE); - mServiceContext.setPermission( - android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED); - - assertEquals(42, mService.getConnectionOwnerUid(getTestConnectionInfo())); - } - - @Test - public void testGetConnectionOwnerUidVpnServiceMainlineNetworkStackDoesNotThrow() - throws Exception { - final int myUid = Process.myUid(); - setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE); - mServiceContext.setPermission( - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_GRANTED); - - assertEquals(42, mService.getConnectionOwnerUid(getTestConnectionInfo())); - } - - private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid) { - final PackageInfo packageInfo = new PackageInfo(); - if (hasSystemPermission) { - packageInfo.requestedPermissions = new String[] { - CHANGE_NETWORK_STATE, CONNECTIVITY_USE_RESTRICTED_NETWORKS }; - packageInfo.requestedPermissionsFlags = new int[] { - REQUESTED_PERMISSION_GRANTED, REQUESTED_PERMISSION_GRANTED }; - } else { - packageInfo.requestedPermissions = new String[0]; - } - packageInfo.applicationInfo = new ApplicationInfo(); - packageInfo.applicationInfo.privateFlags = 0; - packageInfo.applicationInfo.uid = UserHandle.getUid(UserHandle.USER_SYSTEM, - UserHandle.getAppId(uid)); - return packageInfo; - } - - @Test - public void testRegisterConnectivityDiagnosticsCallbackInvalidRequest() throws Exception { - final NetworkRequest request = - new NetworkRequest( - new NetworkCapabilities(), TYPE_ETHERNET, 0, NetworkRequest.Type.NONE); - try { - mService.registerConnectivityDiagnosticsCallback( - mConnectivityDiagnosticsCallback, request, mContext.getPackageName()); - fail("registerConnectivityDiagnosticsCallback should throw on invalid NetworkRequest"); - } catch (IllegalArgumentException expected) { - } - } - - private void assertRouteInfoParcelMatches(RouteInfo route, RouteInfoParcel parcel) { - assertEquals(route.getDestination().toString(), parcel.destination); - assertEquals(route.getInterface(), parcel.ifName); - assertEquals(route.getMtu(), parcel.mtu); - - switch (route.getType()) { - case RouteInfo.RTN_UNICAST: - if (route.hasGateway()) { - assertEquals(route.getGateway().getHostAddress(), parcel.nextHop); - } else { - assertEquals(INetd.NEXTHOP_NONE, parcel.nextHop); - } - break; - case RouteInfo.RTN_UNREACHABLE: - assertEquals(INetd.NEXTHOP_UNREACHABLE, parcel.nextHop); - break; - case RouteInfo.RTN_THROW: - assertEquals(INetd.NEXTHOP_THROW, parcel.nextHop); - break; - default: - assertEquals(INetd.NEXTHOP_NONE, parcel.nextHop); - break; - } - } - - private void assertRoutesAdded(int netId, RouteInfo... routes) throws Exception { - ArgumentCaptor captor = ArgumentCaptor.forClass(RouteInfoParcel.class); - verify(mMockNetd, times(routes.length)).networkAddRouteParcel(eq(netId), captor.capture()); - for (int i = 0; i < routes.length; i++) { - assertRouteInfoParcelMatches(routes[i], captor.getAllValues().get(i)); - } - } - - private void assertRoutesRemoved(int netId, RouteInfo... routes) throws Exception { - ArgumentCaptor captor = ArgumentCaptor.forClass(RouteInfoParcel.class); - verify(mMockNetd, times(routes.length)).networkRemoveRouteParcel(eq(netId), - captor.capture()); - for (int i = 0; i < routes.length; i++) { - assertRouteInfoParcelMatches(routes[i], captor.getAllValues().get(i)); - } - } - - @Test - public void testRegisterUnregisterConnectivityDiagnosticsCallback() throws Exception { - final NetworkRequest wifiRequest = - new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build(); - when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder); - - mService.registerConnectivityDiagnosticsCallback( - mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName()); - - // Block until all other events are done processing. - HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS); - - verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt()); - verify(mConnectivityDiagnosticsCallback).asBinder(); - assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder)); - - mService.unregisterConnectivityDiagnosticsCallback(mConnectivityDiagnosticsCallback); - verify(mIBinder, timeout(TIMEOUT_MS)) - .unlinkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt()); - assertFalse(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder)); - verify(mConnectivityDiagnosticsCallback, atLeastOnce()).asBinder(); - } - - @Test - public void testRegisterDuplicateConnectivityDiagnosticsCallback() throws Exception { - final NetworkRequest wifiRequest = - new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build(); - when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder); - - mService.registerConnectivityDiagnosticsCallback( - mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName()); - - // Block until all other events are done processing. - HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS); - - verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt()); - verify(mConnectivityDiagnosticsCallback).asBinder(); - assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder)); - - // Register the same callback again - mService.registerConnectivityDiagnosticsCallback( - mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName()); - - // Block until all other events are done processing. - HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS); - - assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder)); - } - - public NetworkAgentInfo fakeMobileNai(NetworkCapabilities nc) { - final NetworkInfo info = new NetworkInfo(TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_LTE, - ConnectivityManager.getNetworkTypeName(TYPE_MOBILE), - TelephonyManager.getNetworkTypeName(TelephonyManager.NETWORK_TYPE_LTE)); - return new NetworkAgentInfo(null, new Network(NET_ID), info, new LinkProperties(), - nc, new NetworkScore.Builder().setLegacyInt(0).build(), - mServiceContext, null, new NetworkAgentConfig(), mService, null, null, 0, - INVALID_UID, TEST_LINGER_DELAY_MS, mQosCallbackTracker, - new ConnectivityService.Dependencies()); - } - - @Test - public void testCheckConnectivityDiagnosticsPermissionsNetworkStack() throws Exception { - final NetworkAgentInfo naiWithoutUid = fakeMobileNai(new NetworkCapabilities()); - - mServiceContext.setPermission( - android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED); - assertTrue( - "NetworkStack permission not applied", - mService.checkConnectivityDiagnosticsPermissions( - Process.myPid(), Process.myUid(), naiWithoutUid, - mContext.getOpPackageName())); - } - - @Test - public void testCheckConnectivityDiagnosticsPermissionsWrongUidPackageName() throws Exception { - final int wrongUid = Process.myUid() + 1; - - final NetworkCapabilities nc = new NetworkCapabilities(); - nc.setAdministratorUids(new int[] {wrongUid}); - final NetworkAgentInfo naiWithUid = fakeMobileNai(nc); - - mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED); - - assertFalse( - "Mismatched uid/package name should not pass the location permission check", - mService.checkConnectivityDiagnosticsPermissions( - Process.myPid() + 1, wrongUid, naiWithUid, mContext.getOpPackageName())); - } - - @Test - public void testCheckConnectivityDiagnosticsPermissionsNoLocationPermission() throws Exception { - final NetworkCapabilities nc = new NetworkCapabilities(); - nc.setAdministratorUids(new int[] {Process.myUid()}); - final NetworkAgentInfo naiWithUid = fakeMobileNai(nc); - - mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED); - - assertFalse( - "ACCESS_FINE_LOCATION permission necessary for Connectivity Diagnostics", - mService.checkConnectivityDiagnosticsPermissions( - Process.myPid(), Process.myUid(), naiWithUid, mContext.getOpPackageName())); - } - - @Test - public void testCheckConnectivityDiagnosticsPermissionsActiveVpn() throws Exception { - final NetworkAgentInfo naiWithoutUid = fakeMobileNai(new NetworkCapabilities()); - - mMockVpn.establishForMyUid(); - assertUidRangesUpdatedForMyUid(true); - - // Wait for networks to connect and broadcasts to be sent before removing permissions. - waitForIdle(); - setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, - Manifest.permission.ACCESS_FINE_LOCATION); - - assertTrue(mMockVpn.setUnderlyingNetworks(new Network[] {naiWithoutUid.network})); - waitForIdle(); - assertTrue( - "Active VPN permission not applied", - mService.checkConnectivityDiagnosticsPermissions( - Process.myPid(), Process.myUid(), naiWithoutUid, - mContext.getOpPackageName())); - - assertTrue(mMockVpn.setUnderlyingNetworks(null)); - waitForIdle(); - assertFalse( - "VPN shouldn't receive callback on non-underlying network", - mService.checkConnectivityDiagnosticsPermissions( - Process.myPid(), Process.myUid(), naiWithoutUid, - mContext.getOpPackageName())); - } - - @Test - public void testCheckConnectivityDiagnosticsPermissionsNetworkAdministrator() throws Exception { - final NetworkCapabilities nc = new NetworkCapabilities(); - nc.setAdministratorUids(new int[] {Process.myUid()}); - final NetworkAgentInfo naiWithUid = fakeMobileNai(nc); - - setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, - Manifest.permission.ACCESS_FINE_LOCATION); - mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED); - - assertTrue( - "NetworkCapabilities administrator uid permission not applied", - mService.checkConnectivityDiagnosticsPermissions( - Process.myPid(), Process.myUid(), naiWithUid, mContext.getOpPackageName())); - } - - @Test - public void testCheckConnectivityDiagnosticsPermissionsFails() throws Exception { - final NetworkCapabilities nc = new NetworkCapabilities(); - nc.setOwnerUid(Process.myUid()); - nc.setAdministratorUids(new int[] {Process.myUid()}); - final NetworkAgentInfo naiWithUid = fakeMobileNai(nc); - - setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, - Manifest.permission.ACCESS_FINE_LOCATION); - mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED); - - // Use wrong pid and uid - assertFalse( - "Permissions allowed when they shouldn't be granted", - mService.checkConnectivityDiagnosticsPermissions( - Process.myPid() + 1, Process.myUid() + 1, naiWithUid, - mContext.getOpPackageName())); - } - - @Test - public void testRegisterConnectivityDiagnosticsCallbackCallsOnConnectivityReport() - throws Exception { - // Set up the Network, which leads to a ConnectivityReport being cached for the network. - final TestNetworkCallback callback = new TestNetworkCallback(); - mCm.registerDefaultNetworkCallback(callback); - final LinkProperties linkProperties = new LinkProperties(); - linkProperties.setInterfaceName(INTERFACE_NAME); - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, linkProperties); - mCellNetworkAgent.connect(true); - callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - callback.assertNoCallback(); - - final NetworkRequest request = new NetworkRequest.Builder().build(); - when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder); - - mServiceContext.setPermission( - android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED); - - mService.registerConnectivityDiagnosticsCallback( - mConnectivityDiagnosticsCallback, request, mContext.getPackageName()); - - // Block until all other events are done processing. - HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS); - - verify(mConnectivityDiagnosticsCallback) - .onConnectivityReportAvailable(argThat(report -> { - return INTERFACE_NAME.equals(report.getLinkProperties().getInterfaceName()) - && report.getNetworkCapabilities().hasTransport(TRANSPORT_CELLULAR); - })); - } - - private void setUpConnectivityDiagnosticsCallback() throws Exception { - final NetworkRequest request = new NetworkRequest.Builder().build(); - when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder); - - mServiceContext.setPermission( - android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED); - - mService.registerConnectivityDiagnosticsCallback( - mConnectivityDiagnosticsCallback, request, mContext.getPackageName()); - - // Block until all other events are done processing. - HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS); - - // Connect the cell agent verify that it notifies TestNetworkCallback that it is available - final TestNetworkCallback callback = new TestNetworkCallback(); - mCm.registerDefaultNetworkCallback(callback); - - final NetworkCapabilities ncTemplate = new NetworkCapabilities() - .addTransportType(TRANSPORT_CELLULAR) - .setTransportInfo(new TestTransportInfo()); - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(), - ncTemplate); - mCellNetworkAgent.connect(true); - callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - callback.assertNoCallback(); - } - - private boolean areConnDiagCapsRedacted(NetworkCapabilities nc) { - TestTransportInfo ti = (TestTransportInfo) nc.getTransportInfo(); - return nc.getUids() == null - && nc.getAdministratorUids().length == 0 - && nc.getOwnerUid() == Process.INVALID_UID - && getTestTransportInfo(nc).locationRedacted - && getTestTransportInfo(nc).localMacAddressRedacted - && getTestTransportInfo(nc).settingsRedacted; - } - - @Test - public void testConnectivityDiagnosticsCallbackOnConnectivityReportAvailable() - throws Exception { - setUpConnectivityDiagnosticsCallback(); - - // Block until all other events are done processing. - HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS); - - // Verify onConnectivityReport fired - verify(mConnectivityDiagnosticsCallback).onConnectivityReportAvailable( - argThat(report -> areConnDiagCapsRedacted(report.getNetworkCapabilities()))); - } - - @Test - public void testConnectivityDiagnosticsCallbackOnDataStallSuspected() throws Exception { - setUpConnectivityDiagnosticsCallback(); - - // Trigger notifyDataStallSuspected() on the INetworkMonitorCallbacks instance in the - // cellular network agent - mCellNetworkAgent.notifyDataStallSuspected(); - - // Block until all other events are done processing. - HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS); - - // Verify onDataStallSuspected fired - verify(mConnectivityDiagnosticsCallback).onDataStallSuspected( - argThat(report -> areConnDiagCapsRedacted(report.getNetworkCapabilities()))); - } - - @Test - public void testConnectivityDiagnosticsCallbackOnConnectivityReported() throws Exception { - setUpConnectivityDiagnosticsCallback(); - - final Network n = mCellNetworkAgent.getNetwork(); - final boolean hasConnectivity = true; - mService.reportNetworkConnectivity(n, hasConnectivity); - - // Block until all other events are done processing. - HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS); - - // Verify onNetworkConnectivityReported fired - verify(mConnectivityDiagnosticsCallback) - .onNetworkConnectivityReported(eq(n), eq(hasConnectivity)); - - final boolean noConnectivity = false; - mService.reportNetworkConnectivity(n, noConnectivity); - - // Block until all other events are done processing. - HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS); - - // Wait for onNetworkConnectivityReported to fire - verify(mConnectivityDiagnosticsCallback) - .onNetworkConnectivityReported(eq(n), eq(noConnectivity)); - } - - @Test - public void testRouteAddDeleteUpdate() throws Exception { - final NetworkRequest request = new NetworkRequest.Builder().build(); - final TestNetworkCallback networkCallback = new TestNetworkCallback(); - mCm.registerNetworkCallback(request, networkCallback); - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - reset(mMockNetd); - mCellNetworkAgent.connect(false); - networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); - final int netId = mCellNetworkAgent.getNetwork().netId; - - final String iface = "rmnet_data0"; - final InetAddress gateway = InetAddress.getByName("fe80::5678"); - RouteInfo direct = RouteInfo.makeHostRoute(gateway, iface); - RouteInfo rio1 = new RouteInfo(new IpPrefix("2001:db8:1::/48"), gateway, iface); - RouteInfo rio2 = new RouteInfo(new IpPrefix("2001:db8:2::/48"), gateway, iface); - RouteInfo defaultRoute = new RouteInfo((IpPrefix) null, gateway, iface); - RouteInfo defaultWithMtu = new RouteInfo(null, gateway, iface, RouteInfo.RTN_UNICAST, - 1280 /* mtu */); - - // Send LinkProperties and check that we ask netd to add routes. - LinkProperties lp = new LinkProperties(); - lp.setInterfaceName(iface); - lp.addRoute(direct); - lp.addRoute(rio1); - lp.addRoute(defaultRoute); - mCellNetworkAgent.sendLinkProperties(lp); - networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, x -> x.getRoutes().size() == 3); - - assertRoutesAdded(netId, direct, rio1, defaultRoute); - reset(mMockNetd); - - // Send updated LinkProperties and check that we ask netd to add, remove, update routes. - assertTrue(lp.getRoutes().contains(defaultRoute)); - lp.removeRoute(rio1); - lp.addRoute(rio2); - lp.addRoute(defaultWithMtu); - // Ensure adding the same route with a different MTU replaces the previous route. - assertFalse(lp.getRoutes().contains(defaultRoute)); - assertTrue(lp.getRoutes().contains(defaultWithMtu)); - - mCellNetworkAgent.sendLinkProperties(lp); - networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, - x -> x.getRoutes().contains(rio2)); - - assertRoutesRemoved(netId, rio1); - assertRoutesAdded(netId, rio2); - - ArgumentCaptor captor = ArgumentCaptor.forClass(RouteInfoParcel.class); - verify(mMockNetd).networkUpdateRouteParcel(eq(netId), captor.capture()); - assertRouteInfoParcelMatches(defaultWithMtu, captor.getValue()); - - - mCm.unregisterNetworkCallback(networkCallback); - } - - @Test - public void testDumpDoesNotCrash() { - mServiceContext.setPermission(DUMP, PERMISSION_GRANTED); - // Filing a couple requests prior to testing the dump. - final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback(); - final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback(); - final NetworkRequest genericRequest = new NetworkRequest.Builder() - .clearCapabilities().build(); - final NetworkRequest wifiRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_WIFI).build(); - mCm.registerNetworkCallback(genericRequest, genericNetworkCallback); - mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback); - final StringWriter stringWriter = new StringWriter(); - - mService.dump(new FileDescriptor(), new PrintWriter(stringWriter), new String[0]); - - assertFalse(stringWriter.toString().isEmpty()); - } - - @Test - public void testRequestsSortedByIdSortsCorrectly() { - final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback(); - final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback(); - final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); - final NetworkRequest genericRequest = new NetworkRequest.Builder() - .clearCapabilities().build(); - final NetworkRequest wifiRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_WIFI).build(); - final NetworkRequest cellRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR).build(); - mCm.registerNetworkCallback(genericRequest, genericNetworkCallback); - mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback); - mCm.registerNetworkCallback(cellRequest, cellNetworkCallback); - waitForIdle(); - - final ConnectivityService.NetworkRequestInfo[] nriOutput = mService.requestsSortedById(); - - assertTrue(nriOutput.length > 1); - for (int i = 0; i < nriOutput.length - 1; i++) { - final boolean isRequestIdInOrder = - nriOutput[i].mRequests.get(0).requestId - < nriOutput[i + 1].mRequests.get(0).requestId; - assertTrue(isRequestIdInOrder); - } - } - - private void assertUidRangesUpdatedForMyUid(boolean add) throws Exception { - final int uid = Process.myUid(); - assertVpnUidRangesUpdated(add, uidRangesForUids(uid), uid); - } - - private void assertVpnUidRangesUpdated(boolean add, Set vpnRanges, int exemptUid) - throws Exception { - InOrder inOrder = inOrder(mMockNetd); - ArgumentCaptor exemptUidCaptor = ArgumentCaptor.forClass(int[].class); - - inOrder.verify(mMockNetd, times(1)).socketDestroy(eq(toUidRangeStableParcels(vpnRanges)), - exemptUidCaptor.capture()); - assertContainsExactly(exemptUidCaptor.getValue(), Process.VPN_UID, exemptUid); - - if (add) { - inOrder.verify(mMockNetd, times(1)) - .networkAddUidRanges(eq(mMockVpn.getNetwork().getNetId()), - eq(toUidRangeStableParcels(vpnRanges))); - } else { - inOrder.verify(mMockNetd, times(1)) - .networkRemoveUidRanges(eq(mMockVpn.getNetwork().getNetId()), - eq(toUidRangeStableParcels(vpnRanges))); - } - - inOrder.verify(mMockNetd, times(1)).socketDestroy(eq(toUidRangeStableParcels(vpnRanges)), - exemptUidCaptor.capture()); - assertContainsExactly(exemptUidCaptor.getValue(), Process.VPN_UID, exemptUid); - } - - @Test - public void testVpnUidRangesUpdate() throws Exception { - LinkProperties lp = new LinkProperties(); - lp.setInterfaceName("tun0"); - lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null)); - lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null)); - final UidRange vpnRange = PRIMARY_UIDRANGE; - Set vpnRanges = Collections.singleton(vpnRange); - mMockVpn.establish(lp, VPN_UID, vpnRanges); - assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID); - - reset(mMockNetd); - // Update to new range which is old range minus APP1, i.e. only APP2 - final Set newRanges = new HashSet<>(Arrays.asList( - new UidRange(vpnRange.start, APP1_UID - 1), - new UidRange(APP1_UID + 1, vpnRange.stop))); - mMockVpn.setUids(newRanges); - waitForIdle(); - - assertVpnUidRangesUpdated(true, newRanges, VPN_UID); - assertVpnUidRangesUpdated(false, vpnRanges, VPN_UID); - } - - @Test - public void testInvalidRequestTypes() { - final int[] invalidReqTypeInts = new int[]{-1, NetworkRequest.Type.NONE.ordinal(), - NetworkRequest.Type.LISTEN.ordinal(), NetworkRequest.Type.values().length}; - final NetworkCapabilities nc = new NetworkCapabilities().addTransportType(TRANSPORT_WIFI); - - for (int reqTypeInt : invalidReqTypeInts) { - assertThrows("Expect throws for invalid request type " + reqTypeInt, - IllegalArgumentException.class, - () -> mService.requestNetwork(Process.INVALID_UID, nc, reqTypeInt, null, 0, - null, ConnectivityManager.TYPE_NONE, NetworkCallback.FLAG_NONE, - mContext.getPackageName(), getAttributionTag()) - ); - } - } - - @Test - public void testKeepConnected() throws Exception { - setAlwaysOnNetworks(false); - registerDefaultNetworkCallbacks(); - final TestNetworkCallback allNetworksCb = new TestNetworkCallback(); - final NetworkRequest allNetworksRequest = new NetworkRequest.Builder().clearCapabilities() - .build(); - mCm.registerNetworkCallback(allNetworksRequest, allNetworksCb); - - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true /* validated */); - - mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - allNetworksCb.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true /* validated */); - - mDefaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); - // While the default callback doesn't see the network before it's validated, the listen - // sees the network come up and validate later - allNetworksCb.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - allNetworksCb.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); - allNetworksCb.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); - allNetworksCb.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, - TEST_LINGER_DELAY_MS * 2); - - // The cell network has disconnected (see LOST above) because it was outscored and - // had no requests (see setAlwaysOnNetworks(false) above) - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - final NetworkScore score = new NetworkScore.Builder().setLegacyInt(30).build(); - mCellNetworkAgent.setScore(score); - mCellNetworkAgent.connect(false /* validated */); - - // The cell network gets torn down right away. - allNetworksCb.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); - allNetworksCb.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, - TEST_NASCENT_DELAY_MS * 2); - allNetworksCb.assertNoCallback(); - - // Now create a cell network with KEEP_CONNECTED_FOR_HANDOVER and make sure it's - // not disconnected immediately when outscored. - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - final NetworkScore scoreKeepup = new NetworkScore.Builder().setLegacyInt(30) - .setKeepConnectedReason(KEEP_CONNECTED_FOR_HANDOVER).build(); - mCellNetworkAgent.setScore(scoreKeepup); - mCellNetworkAgent.connect(true /* validated */); - - allNetworksCb.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - mDefaultNetworkCallback.assertNoCallback(); - - mWiFiNetworkAgent.disconnect(); - - allNetworksCb.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - mDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); - - // Reconnect a WiFi network and make sure the cell network is still not torn down. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true /* validated */); - - allNetworksCb.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent); - mDefaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); - - // Now remove the reason to keep connected and make sure the network lingers and is - // torn down. - mCellNetworkAgent.setScore(new NetworkScore.Builder().setLegacyInt(30).build()); - allNetworksCb.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent, - TEST_NASCENT_DELAY_MS * 2); - allNetworksCb.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, - TEST_LINGER_DELAY_MS * 2); - mDefaultNetworkCallback.assertNoCallback(); - - mCm.unregisterNetworkCallback(allNetworksCb); - // mDefaultNetworkCallback will be unregistered by tearDown() - } - - private class QosCallbackMockHelper { - @NonNull public final QosFilter mFilter; - @NonNull public final IQosCallback mCallback; - @NonNull public final TestNetworkAgentWrapper mAgentWrapper; - @NonNull private final List mCallbacks = new ArrayList(); - - QosCallbackMockHelper() throws Exception { - Log.d(TAG, "QosCallbackMockHelper: "); - mFilter = mock(QosFilter.class); - - // Ensure the network is disconnected before anything else occurs - assertNull(mCellNetworkAgent); - - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - - verifyActiveNetwork(TRANSPORT_CELLULAR); - waitForIdle(); - final Network network = mCellNetworkAgent.getNetwork(); - - final Pair pair = createQosCallback(); - mCallback = pair.first; - - when(mFilter.getNetwork()).thenReturn(network); - when(mFilter.validate()).thenReturn(QosCallbackException.EX_TYPE_FILTER_NONE); - mAgentWrapper = mCellNetworkAgent; - } - - void registerQosCallback(@NonNull final QosFilter filter, - @NonNull final IQosCallback callback) { - mCallbacks.add(callback); - final NetworkAgentInfo nai = - mService.getNetworkAgentInfoForNetwork(filter.getNetwork()); - mService.registerQosCallbackInternal(filter, callback, nai); - } - - void tearDown() { - for (int i = 0; i < mCallbacks.size(); i++) { - mService.unregisterQosCallback(mCallbacks.get(i)); - } - } - } - - private Pair createQosCallback() { - final IQosCallback callback = mock(IQosCallback.class); - final IBinder binder = mock(Binder.class); - when(callback.asBinder()).thenReturn(binder); - when(binder.isBinderAlive()).thenReturn(true); - return new Pair<>(callback, binder); - } - - - @Test - public void testQosCallbackRegistration() throws Exception { - mQosCallbackMockHelper = new QosCallbackMockHelper(); - final NetworkAgentWrapper wrapper = mQosCallbackMockHelper.mAgentWrapper; - - when(mQosCallbackMockHelper.mFilter.validate()) - .thenReturn(QosCallbackException.EX_TYPE_FILTER_NONE); - mQosCallbackMockHelper.registerQosCallback( - mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback); - - final NetworkAgentWrapper.CallbackType.OnQosCallbackRegister cbRegister1 = - (NetworkAgentWrapper.CallbackType.OnQosCallbackRegister) - wrapper.getCallbackHistory().poll(1000, x -> true); - assertNotNull(cbRegister1); - - final int registerCallbackId = cbRegister1.mQosCallbackId; - mService.unregisterQosCallback(mQosCallbackMockHelper.mCallback); - final NetworkAgentWrapper.CallbackType.OnQosCallbackUnregister cbUnregister; - cbUnregister = (NetworkAgentWrapper.CallbackType.OnQosCallbackUnregister) - wrapper.getCallbackHistory().poll(1000, x -> true); - assertNotNull(cbUnregister); - assertEquals(registerCallbackId, cbUnregister.mQosCallbackId); - assertNull(wrapper.getCallbackHistory().poll(200, x -> true)); - } - - @Test - public void testQosCallbackNoRegistrationOnValidationError() throws Exception { - mQosCallbackMockHelper = new QosCallbackMockHelper(); - - when(mQosCallbackMockHelper.mFilter.validate()) - .thenReturn(QosCallbackException.EX_TYPE_FILTER_NETWORK_RELEASED); - mQosCallbackMockHelper.registerQosCallback( - mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback); - waitForIdle(); - verify(mQosCallbackMockHelper.mCallback) - .onError(eq(QosCallbackException.EX_TYPE_FILTER_NETWORK_RELEASED)); - } - - @Test - public void testQosCallbackAvailableAndLost() throws Exception { - mQosCallbackMockHelper = new QosCallbackMockHelper(); - final int sessionId = 10; - final int qosCallbackId = 1; - - when(mQosCallbackMockHelper.mFilter.validate()) - .thenReturn(QosCallbackException.EX_TYPE_FILTER_NONE); - mQosCallbackMockHelper.registerQosCallback( - mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback); - waitForIdle(); - - final EpsBearerQosSessionAttributes attributes = new EpsBearerQosSessionAttributes( - 1, 2, 3, 4, 5, new ArrayList<>()); - mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent() - .sendQosSessionAvailable(qosCallbackId, sessionId, attributes); - waitForIdle(); - - verify(mQosCallbackMockHelper.mCallback).onQosEpsBearerSessionAvailable(argThat(session -> - session.getSessionId() == sessionId - && session.getSessionType() == QosSession.TYPE_EPS_BEARER), eq(attributes)); - - mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent() - .sendQosSessionLost(qosCallbackId, sessionId, QosSession.TYPE_EPS_BEARER); - waitForIdle(); - verify(mQosCallbackMockHelper.mCallback).onQosSessionLost(argThat(session -> - session.getSessionId() == sessionId - && session.getSessionType() == QosSession.TYPE_EPS_BEARER)); - } - - @Test - public void testNrQosCallbackAvailableAndLost() throws Exception { - mQosCallbackMockHelper = new QosCallbackMockHelper(); - final int sessionId = 10; - final int qosCallbackId = 1; - - when(mQosCallbackMockHelper.mFilter.validate()) - .thenReturn(QosCallbackException.EX_TYPE_FILTER_NONE); - mQosCallbackMockHelper.registerQosCallback( - mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback); - waitForIdle(); - - final NrQosSessionAttributes attributes = new NrQosSessionAttributes( - 1, 2, 3, 4, 5, 6, 7, new ArrayList<>()); - mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent() - .sendQosSessionAvailable(qosCallbackId, sessionId, attributes); - waitForIdle(); - - verify(mQosCallbackMockHelper.mCallback).onNrQosSessionAvailable(argThat(session -> - session.getSessionId() == sessionId - && session.getSessionType() == QosSession.TYPE_NR_BEARER), eq(attributes)); - - mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent() - .sendQosSessionLost(qosCallbackId, sessionId, QosSession.TYPE_NR_BEARER); - waitForIdle(); - verify(mQosCallbackMockHelper.mCallback).onQosSessionLost(argThat(session -> - session.getSessionId() == sessionId - && session.getSessionType() == QosSession.TYPE_NR_BEARER)); - } - - @Test - public void testQosCallbackTooManyRequests() throws Exception { - mQosCallbackMockHelper = new QosCallbackMockHelper(); - - when(mQosCallbackMockHelper.mFilter.validate()) - .thenReturn(QosCallbackException.EX_TYPE_FILTER_NONE); - for (int i = 0; i < 100; i++) { - final Pair pair = createQosCallback(); - - try { - mQosCallbackMockHelper.registerQosCallback( - mQosCallbackMockHelper.mFilter, pair.first); - } catch (ServiceSpecificException e) { - assertEquals(e.errorCode, ConnectivityManager.Errors.TOO_MANY_REQUESTS); - if (i < 50) { - fail("TOO_MANY_REQUESTS thrown too early, the count is " + i); - } - - // As long as there is at least 50 requests, it is safe to assume it works. - // Note: The count isn't being tested precisely against 100 because the counter - // is shared with request network. - return; - } - } - fail("TOO_MANY_REQUESTS never thrown"); - } - - private UidRange createUidRange(int userId) { - return UidRange.createForUser(UserHandle.of(userId)); - } - - private void mockGetApplicationInfo(@NonNull final String packageName, @NonNull final int uid) { - final ApplicationInfo applicationInfo = new ApplicationInfo(); - applicationInfo.uid = uid; - try { - when(mPackageManager.getApplicationInfo(eq(packageName), anyInt())) - .thenReturn(applicationInfo); - } catch (Exception e) { - fail(e.getMessage()); - } - } - - private void mockGetApplicationInfoThrowsNameNotFound(@NonNull final String packageName) - throws Exception { - when(mPackageManager.getApplicationInfo(eq(packageName), anyInt())) - .thenThrow(new PackageManager.NameNotFoundException(packageName)); - } - - private void mockHasSystemFeature(@NonNull final String featureName, - @NonNull final boolean hasFeature) { - when(mPackageManager.hasSystemFeature(eq(featureName))) - .thenReturn(hasFeature); - } - - private Range getNriFirstUidRange( - @NonNull final ConnectivityService.NetworkRequestInfo nri) { - return nri.mRequests.get(0).networkCapabilities.getUids().iterator().next(); - } - - private OemNetworkPreferences createDefaultOemNetworkPreferences( - @OemNetworkPreferences.OemNetworkPreference final int preference) { - // Arrange PackageManager mocks - mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID); - - // Build OemNetworkPreferences object - return new OemNetworkPreferences.Builder() - .addNetworkPreference(TEST_PACKAGE_NAME, preference) - .build(); - } - - @Test - public void testOemNetworkRequestFactoryPreferenceUninitializedThrowsError() - throws PackageManager.NameNotFoundException { - @OemNetworkPreferences.OemNetworkPreference final int prefToTest = - OEM_NETWORK_PREFERENCE_UNINITIALIZED; - - // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences() - assertThrows(IllegalArgumentException.class, - () -> mService.new OemNetworkRequestFactory() - .createNrisFromOemNetworkPreferences( - createDefaultOemNetworkPreferences(prefToTest))); - } - - @Test - public void testOemNetworkRequestFactoryPreferenceOemPaid() - throws Exception { - // Expectations - final int expectedNumOfNris = 1; - final int expectedNumOfRequests = 3; - - @OemNetworkPreferences.OemNetworkPreference final int prefToTest = - OEM_NETWORK_PREFERENCE_OEM_PAID; - - // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences() - final ArraySet nris = - mService.new OemNetworkRequestFactory() - .createNrisFromOemNetworkPreferences( - createDefaultOemNetworkPreferences(prefToTest)); - - final List mRequests = nris.iterator().next().mRequests; - assertEquals(expectedNumOfNris, nris.size()); - assertEquals(expectedNumOfRequests, mRequests.size()); - assertTrue(mRequests.get(0).isListen()); - assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_NOT_METERED)); - assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_VALIDATED)); - assertTrue(mRequests.get(1).isRequest()); - assertTrue(mRequests.get(1).hasCapability(NET_CAPABILITY_OEM_PAID)); - assertEquals(NetworkRequest.Type.TRACK_DEFAULT, mRequests.get(2).type); - assertTrue(mService.getDefaultRequest().networkCapabilities.equalsNetCapabilities( - mRequests.get(2).networkCapabilities)); - } - - @Test - public void testOemNetworkRequestFactoryPreferenceOemPaidNoFallback() - throws Exception { - // Expectations - final int expectedNumOfNris = 1; - final int expectedNumOfRequests = 2; - - @OemNetworkPreferences.OemNetworkPreference final int prefToTest = - OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK; - - // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences() - final ArraySet nris = - mService.new OemNetworkRequestFactory() - .createNrisFromOemNetworkPreferences( - createDefaultOemNetworkPreferences(prefToTest)); - - final List mRequests = nris.iterator().next().mRequests; - assertEquals(expectedNumOfNris, nris.size()); - assertEquals(expectedNumOfRequests, mRequests.size()); - assertTrue(mRequests.get(0).isListen()); - assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_NOT_METERED)); - assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_VALIDATED)); - assertTrue(mRequests.get(1).isRequest()); - assertTrue(mRequests.get(1).hasCapability(NET_CAPABILITY_OEM_PAID)); - } - - @Test - public void testOemNetworkRequestFactoryPreferenceOemPaidOnly() - throws Exception { - // Expectations - final int expectedNumOfNris = 1; - final int expectedNumOfRequests = 1; - - @OemNetworkPreferences.OemNetworkPreference final int prefToTest = - OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; - - // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences() - final ArraySet nris = - mService.new OemNetworkRequestFactory() - .createNrisFromOemNetworkPreferences( - createDefaultOemNetworkPreferences(prefToTest)); - - final List mRequests = nris.iterator().next().mRequests; - assertEquals(expectedNumOfNris, nris.size()); - assertEquals(expectedNumOfRequests, mRequests.size()); - assertTrue(mRequests.get(0).isRequest()); - assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_OEM_PAID)); - } - - @Test - public void testOemNetworkRequestFactoryPreferenceOemPrivateOnly() - throws Exception { - // Expectations - final int expectedNumOfNris = 1; - final int expectedNumOfRequests = 1; - - @OemNetworkPreferences.OemNetworkPreference final int prefToTest = - OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY; - - // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences() - final ArraySet nris = - mService.new OemNetworkRequestFactory() - .createNrisFromOemNetworkPreferences( - createDefaultOemNetworkPreferences(prefToTest)); - - final List mRequests = nris.iterator().next().mRequests; - assertEquals(expectedNumOfNris, nris.size()); - assertEquals(expectedNumOfRequests, mRequests.size()); - assertTrue(mRequests.get(0).isRequest()); - assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_OEM_PRIVATE)); - assertFalse(mRequests.get(0).hasCapability(NET_CAPABILITY_OEM_PAID)); - } - - @Test - public void testOemNetworkRequestFactoryCreatesCorrectNumOfNris() - throws Exception { - // Expectations - final int expectedNumOfNris = 2; - - // Arrange PackageManager mocks - final String testPackageName2 = "com.google.apps.dialer"; - mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID); - mockGetApplicationInfo(testPackageName2, TEST_PACKAGE_UID); - - // Build OemNetworkPreferences object - final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID; - final int testOemPref2 = OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK; - final OemNetworkPreferences pref = new OemNetworkPreferences.Builder() - .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref) - .addNetworkPreference(testPackageName2, testOemPref2) - .build(); - - // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences() - final ArraySet nris = - mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(pref); - - assertNotNull(nris); - assertEquals(expectedNumOfNris, nris.size()); - } - - @Test - public void testOemNetworkRequestFactoryMultiplePrefsCorrectlySetsUids() - throws Exception { - // Arrange PackageManager mocks - final String testPackageName2 = "com.google.apps.dialer"; - final int testPackageNameUid2 = 456; - mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID); - mockGetApplicationInfo(testPackageName2, testPackageNameUid2); - - // Build OemNetworkPreferences object - final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID; - final int testOemPref2 = OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK; - final OemNetworkPreferences pref = new OemNetworkPreferences.Builder() - .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref) - .addNetworkPreference(testPackageName2, testOemPref2) - .build(); - - // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences() - final List nris = - new ArrayList<>( - mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences( - pref)); - - // Sort by uid to access nris by index - nris.sort(Comparator.comparingInt(nri -> getNriFirstUidRange(nri).getLower())); - assertEquals(TEST_PACKAGE_UID, (int) getNriFirstUidRange(nris.get(0)).getLower()); - assertEquals(TEST_PACKAGE_UID, (int) getNriFirstUidRange(nris.get(0)).getUpper()); - assertEquals(testPackageNameUid2, (int) getNriFirstUidRange(nris.get(1)).getLower()); - assertEquals(testPackageNameUid2, (int) getNriFirstUidRange(nris.get(1)).getUpper()); - } - - @Test - public void testOemNetworkRequestFactoryMultipleUsersCorrectlySetsUids() - throws Exception { - // Arrange users - final int secondUser = 10; - final UserHandle secondUserHandle = new UserHandle(secondUser); - when(mUserManager.getUserHandles(anyBoolean())).thenReturn( - Arrays.asList(PRIMARY_USER_HANDLE, secondUserHandle)); - - // Arrange PackageManager mocks - mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID); - - // Build OemNetworkPreferences object - final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID; - final OemNetworkPreferences pref = new OemNetworkPreferences.Builder() - .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref) - .build(); - - // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences() - final List nris = - new ArrayList<>( - mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences( - pref)); - - // UIDs for all users and all managed packages should be present. - // Two users each with two packages. - final int expectedUidSize = 2; - final List> uids = - new ArrayList<>(nris.get(0).mRequests.get(0).networkCapabilities.getUids()); - assertEquals(expectedUidSize, uids.size()); - - // Sort by uid to access nris by index - uids.sort(Comparator.comparingInt(uid -> uid.getLower())); - final int secondUserTestPackageUid = UserHandle.getUid(secondUser, TEST_PACKAGE_UID); - assertEquals(TEST_PACKAGE_UID, (int) uids.get(0).getLower()); - assertEquals(TEST_PACKAGE_UID, (int) uids.get(0).getUpper()); - assertEquals(secondUserTestPackageUid, (int) uids.get(1).getLower()); - assertEquals(secondUserTestPackageUid, (int) uids.get(1).getUpper()); - } - - @Test - public void testOemNetworkRequestFactoryAddsPackagesToCorrectPreference() - throws Exception { - // Expectations - final int expectedNumOfNris = 1; - final int expectedNumOfAppUids = 2; - - // Arrange PackageManager mocks - final String testPackageName2 = "com.google.apps.dialer"; - final int testPackageNameUid2 = 456; - mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID); - mockGetApplicationInfo(testPackageName2, testPackageNameUid2); - - // Build OemNetworkPreferences object - final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID; - final OemNetworkPreferences pref = new OemNetworkPreferences.Builder() - .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref) - .addNetworkPreference(testPackageName2, testOemPref) - .build(); - - // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences() - final ArraySet nris = - mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(pref); - - assertEquals(expectedNumOfNris, nris.size()); - assertEquals(expectedNumOfAppUids, - nris.iterator().next().mRequests.get(0).networkCapabilities.getUids().size()); - } - - @Test - public void testSetOemNetworkPreferenceNullListenerAndPrefParamThrowsNpe() { - mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true); - - // Act on ConnectivityService.setOemNetworkPreference() - assertThrows(NullPointerException.class, - () -> mService.setOemNetworkPreference( - null, - null)); - } - - @Test - public void testSetOemNetworkPreferenceFailsForNonAutomotive() - throws Exception { - mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, false); - @OemNetworkPreferences.OemNetworkPreference final int networkPref = - OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY; - - // Act on ConnectivityService.setOemNetworkPreference() - assertThrows(UnsupportedOperationException.class, - () -> mService.setOemNetworkPreference( - createDefaultOemNetworkPreferences(networkPref), - new TestOemListenerCallback())); - } - - private void setOemNetworkPreferenceAgentConnected(final int transportType, - final boolean connectAgent) throws Exception { - switch(transportType) { - // Corresponds to a metered cellular network. Will be used for the default network. - case TRANSPORT_CELLULAR: - if (!connectAgent) { - mCellNetworkAgent.disconnect(); - break; - } - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED); - mCellNetworkAgent.connect(true); - break; - // Corresponds to a restricted ethernet network with OEM_PAID/OEM_PRIVATE. - case TRANSPORT_ETHERNET: - if (!connectAgent) { - stopOemManagedNetwork(); - break; - } - startOemManagedNetwork(true); - break; - // Corresponds to unmetered Wi-Fi. - case TRANSPORT_WIFI: - if (!connectAgent) { - mWiFiNetworkAgent.disconnect(); - break; - } - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); - mWiFiNetworkAgent.connect(true); - break; - default: - throw new AssertionError("Unsupported transport type passed in."); - - } - waitForIdle(); - } - - private void startOemManagedNetwork(final boolean isOemPaid) throws Exception { - mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET); - mEthernetNetworkAgent.addCapability( - isOemPaid ? NET_CAPABILITY_OEM_PAID : NET_CAPABILITY_OEM_PRIVATE); - mEthernetNetworkAgent.removeCapability(NET_CAPABILITY_NOT_RESTRICTED); - mEthernetNetworkAgent.connect(true); - } - - private void stopOemManagedNetwork() { - mEthernetNetworkAgent.disconnect(); - waitForIdle(); - } - - private void verifyMultipleDefaultNetworksTracksCorrectly( - final int expectedOemRequestsSize, - @NonNull final Network expectedDefaultNetwork, - @NonNull final Network expectedPerAppNetwork) { - // The current test setup assumes two tracked default network requests; one for the default - // network and the other for the OEM network preference being tested. This will be validated - // each time to confirm it doesn't change under test. - final int expectedDefaultNetworkRequestsSize = 2; - assertEquals(expectedDefaultNetworkRequestsSize, mService.mDefaultNetworkRequests.size()); - for (final ConnectivityService.NetworkRequestInfo defaultRequest - : mService.mDefaultNetworkRequests) { - final Network defaultNetwork = defaultRequest.getSatisfier() == null - ? null : defaultRequest.getSatisfier().network(); - // If this is the default request. - if (defaultRequest == mService.mDefaultRequest) { - assertEquals( - expectedDefaultNetwork, - defaultNetwork); - // Make sure this value doesn't change. - assertEquals(1, defaultRequest.mRequests.size()); - continue; - } - assertEquals(expectedPerAppNetwork, defaultNetwork); - assertEquals(expectedOemRequestsSize, defaultRequest.mRequests.size()); - } - verifyMultipleDefaultCallbacks(expectedDefaultNetwork, expectedPerAppNetwork); - } - - /** - * Verify default callbacks for 'available' fire as expected. This will only run if - * registerDefaultNetworkCallbacks() was executed prior and will only be different if the - * setOemNetworkPreference() per-app API was used for the current process. - * @param expectedSystemDefault the expected network for the system default. - * @param expectedPerAppDefault the expected network for the current process's default. - */ - private void verifyMultipleDefaultCallbacks( - @NonNull final Network expectedSystemDefault, - @NonNull final Network expectedPerAppDefault) { - if (null != mSystemDefaultNetworkCallback && null != expectedSystemDefault - && mService.mNoServiceNetwork.network() != expectedSystemDefault) { - // getLastAvailableNetwork() is used as this method can be called successively with - // the same network to validate therefore expectAvailableThenValidatedCallbacks - // can't be used. - assertEquals(mSystemDefaultNetworkCallback.getLastAvailableNetwork(), - expectedSystemDefault); - } - if (null != mDefaultNetworkCallback && null != expectedPerAppDefault - && mService.mNoServiceNetwork.network() != expectedPerAppDefault) { - assertEquals(mDefaultNetworkCallback.getLastAvailableNetwork(), - expectedPerAppDefault); - } - } - - private void registerDefaultNetworkCallbacks() { - // Using Manifest.permission.NETWORK_SETTINGS for registerSystemDefaultNetworkCallback() - mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED); - mSystemDefaultNetworkCallback = new TestNetworkCallback(); - mDefaultNetworkCallback = new TestNetworkCallback(); - mProfileDefaultNetworkCallback = new TestNetworkCallback(); - mCm.registerSystemDefaultNetworkCallback(mSystemDefaultNetworkCallback, - new Handler(ConnectivityThread.getInstanceLooper())); - mCm.registerDefaultNetworkCallback(mDefaultNetworkCallback); - registerDefaultNetworkCallbackAsUid(mProfileDefaultNetworkCallback, - TEST_WORK_PROFILE_APP_UID); - // TODO: test using ConnectivityManager#registerDefaultNetworkCallbackAsUid as well. - mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED); - } - - private void unregisterDefaultNetworkCallbacks() { - if (null != mDefaultNetworkCallback) { - mCm.unregisterNetworkCallback(mDefaultNetworkCallback); - } - if (null != mSystemDefaultNetworkCallback) { - mCm.unregisterNetworkCallback(mSystemDefaultNetworkCallback); - } - if (null != mProfileDefaultNetworkCallback) { - mCm.unregisterNetworkCallback(mProfileDefaultNetworkCallback); - } - } - - private void setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest( - @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup) - throws Exception { - final int testPackageNameUid = TEST_PACKAGE_UID; - final String testPackageName = "per.app.defaults.package"; - setupMultipleDefaultNetworksForOemNetworkPreferenceTest( - networkPrefToSetup, testPackageNameUid, testPackageName); - } - - private void setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest( - @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup) - throws Exception { - final int testPackageNameUid = Process.myUid(); - final String testPackageName = "per.app.defaults.package"; - setupMultipleDefaultNetworksForOemNetworkPreferenceTest( - networkPrefToSetup, testPackageNameUid, testPackageName); - } - - private void setupMultipleDefaultNetworksForOemNetworkPreferenceTest( - @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup, - final int testPackageUid, @NonNull final String testPackageName) throws Exception { - // Only the default request should be included at start. - assertEquals(1, mService.mDefaultNetworkRequests.size()); - - final UidRangeParcel[] uidRanges = - toUidRangeStableParcels(uidRangesForUids(testPackageUid)); - setupSetOemNetworkPreferenceForPreferenceTest( - networkPrefToSetup, uidRanges, testPackageName); - } - - private void setupSetOemNetworkPreferenceForPreferenceTest( - @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup, - @NonNull final UidRangeParcel[] uidRanges, - @NonNull final String testPackageName) - throws Exception { - // These tests work off a single UID therefore using 'start' is valid. - mockGetApplicationInfo(testPackageName, uidRanges[0].start); - - setOemNetworkPreference(networkPrefToSetup, testPackageName); - } - - private void setOemNetworkPreference(final int networkPrefToSetup, - @NonNull final String... testPackageNames) - throws Exception { - mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true); - - // Build OemNetworkPreferences object - final OemNetworkPreferences.Builder builder = new OemNetworkPreferences.Builder(); - for (final String packageName : testPackageNames) { - builder.addNetworkPreference(packageName, networkPrefToSetup); - } - final OemNetworkPreferences pref = builder.build(); - - // Act on ConnectivityService.setOemNetworkPreference() - final TestOemListenerCallback oemPrefListener = new TestOemListenerCallback(); - mService.setOemNetworkPreference(pref, oemPrefListener); - - // Verify call returned successfully - oemPrefListener.expectOnComplete(); - } - - private static class TestOemListenerCallback implements IOnCompleteListener { - final CompletableFuture mDone = new CompletableFuture<>(); - - @Override - public void onComplete() { - mDone.complete(new Object()); - } - - void expectOnComplete() { - try { - mDone.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); - } catch (TimeoutException e) { - fail("Expected onComplete() not received after " + TIMEOUT_MS + " ms"); - } catch (Exception e) { - fail(e.getMessage()); - } - } - - @Override - public IBinder asBinder() { - return null; - } - } - - @Test - public void testMultiDefaultGetActiveNetworkIsCorrect() throws Exception { - @OemNetworkPreferences.OemNetworkPreference final int networkPref = - OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; - final int expectedOemPrefRequestSize = 1; - registerDefaultNetworkCallbacks(); - - // Setup the test process to use networkPref for their default network. - setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref); - - // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID. - // The active network for the default should be null at this point as this is a retricted - // network. - setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - null, - mEthernetNetworkAgent.getNetwork()); - - // Verify that the active network is correct - verifyActiveNetwork(TRANSPORT_ETHERNET); - // default NCs will be unregistered in tearDown - } - - @Test - public void testMultiDefaultIsActiveNetworkMeteredIsCorrect() throws Exception { - @OemNetworkPreferences.OemNetworkPreference final int networkPref = - OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; - final int expectedOemPrefRequestSize = 1; - registerDefaultNetworkCallbacks(); - - // Setup the test process to use networkPref for their default network. - setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref); - - // Returns true by default when no network is available. - assertTrue(mCm.isActiveNetworkMetered()); - - // Connect to an unmetered restricted network that will only be available to the OEM pref. - mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET); - mEthernetNetworkAgent.addCapability(NET_CAPABILITY_OEM_PAID); - mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); - mEthernetNetworkAgent.removeCapability(NET_CAPABILITY_NOT_RESTRICTED); - mEthernetNetworkAgent.connect(true); - waitForIdle(); - - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - null, - mEthernetNetworkAgent.getNetwork()); - - assertFalse(mCm.isActiveNetworkMetered()); - // default NCs will be unregistered in tearDown - } - - @Test - public void testPerAppDefaultRegisterDefaultNetworkCallback() throws Exception { - @OemNetworkPreferences.OemNetworkPreference final int networkPref = - OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; - final int expectedOemPrefRequestSize = 1; - final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback(); - - // Register the default network callback before the pref is already set. This means that - // the policy will be applied to the callback on setOemNetworkPreference(). - mCm.registerDefaultNetworkCallback(defaultNetworkCallback); - defaultNetworkCallback.assertNoCallback(); - - final TestNetworkCallback otherUidDefaultCallback = new TestNetworkCallback(); - withPermission(NETWORK_SETTINGS, () -> - mCm.registerDefaultNetworkCallbackForUid(TEST_PACKAGE_UID, otherUidDefaultCallback, - new Handler(ConnectivityThread.getInstanceLooper()))); - - // Setup the test process to use networkPref for their default network. - setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref); - - // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID. - // The active nai for the default is null at this point as this is a restricted network. - setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - null, - mEthernetNetworkAgent.getNetwork()); - - // At this point with a restricted network used, the available callback should trigger. - defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent); - assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), - mEthernetNetworkAgent.getNetwork()); - otherUidDefaultCallback.assertNoCallback(); - - // Now bring down the default network which should trigger a LOST callback. - setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false); - - // At this point, with no network is available, the lost callback should trigger - defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent); - otherUidDefaultCallback.assertNoCallback(); - - // Confirm we can unregister without issues. - mCm.unregisterNetworkCallback(defaultNetworkCallback); - mCm.unregisterNetworkCallback(otherUidDefaultCallback); - } - - @Test - public void testPerAppDefaultRegisterDefaultNetworkCallbackAfterPrefSet() throws Exception { - @OemNetworkPreferences.OemNetworkPreference final int networkPref = - OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; - final int expectedOemPrefRequestSize = 1; - final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback(); - - // Setup the test process to use networkPref for their default network. - setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref); - - // Register the default network callback after the pref is already set. This means that - // the policy will be applied to the callback on requestNetwork(). - mCm.registerDefaultNetworkCallback(defaultNetworkCallback); - defaultNetworkCallback.assertNoCallback(); - - final TestNetworkCallback otherUidDefaultCallback = new TestNetworkCallback(); - withPermission(NETWORK_SETTINGS, () -> - mCm.registerDefaultNetworkCallbackForUid(TEST_PACKAGE_UID, otherUidDefaultCallback, - new Handler(ConnectivityThread.getInstanceLooper()))); - - // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID. - // The active nai for the default is null at this point as this is a restricted network. - setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - null, - mEthernetNetworkAgent.getNetwork()); - - // At this point with a restricted network used, the available callback should trigger - defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent); - assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), - mEthernetNetworkAgent.getNetwork()); - otherUidDefaultCallback.assertNoCallback(); - - // Now bring down the default network which should trigger a LOST callback. - setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false); - otherUidDefaultCallback.assertNoCallback(); - - // At this point, with no network is available, the lost callback should trigger - defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent); - otherUidDefaultCallback.assertNoCallback(); - - // Confirm we can unregister without issues. - mCm.unregisterNetworkCallback(defaultNetworkCallback); - mCm.unregisterNetworkCallback(otherUidDefaultCallback); - } - - @Test - public void testPerAppDefaultRegisterDefaultNetworkCallbackDoesNotFire() throws Exception { - @OemNetworkPreferences.OemNetworkPreference final int networkPref = - OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; - final int expectedOemPrefRequestSize = 1; - final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback(); - final int userId = UserHandle.getUserId(Process.myUid()); - - mCm.registerDefaultNetworkCallback(defaultNetworkCallback); - defaultNetworkCallback.assertNoCallback(); - - final TestNetworkCallback otherUidDefaultCallback = new TestNetworkCallback(); - withPermission(NETWORK_SETTINGS, () -> - mCm.registerDefaultNetworkCallbackForUid(TEST_PACKAGE_UID, otherUidDefaultCallback, - new Handler(ConnectivityThread.getInstanceLooper()))); - - // Setup a process different than the test process to use the default network. This means - // that the defaultNetworkCallback won't be tracked by the per-app policy. - setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(networkPref); - - // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID. - // The active nai for the default is null at this point as this is a restricted network. - setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - null, - mEthernetNetworkAgent.getNetwork()); - - // As this callback does not have access to the OEM_PAID network, it will not fire. - defaultNetworkCallback.assertNoCallback(); - assertDefaultNetworkCapabilities(userId /* no networks */); - - // The other UID does have access, and gets a callback. - otherUidDefaultCallback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent); - - // Bring up unrestricted cellular. This should now satisfy the default network. - setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - mCellNetworkAgent.getNetwork(), - mEthernetNetworkAgent.getNetwork()); - - // At this point with an unrestricted network used, the available callback should trigger - // The other UID is unaffected and remains on the paid network. - defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), - mCellNetworkAgent.getNetwork()); - assertDefaultNetworkCapabilities(userId, mCellNetworkAgent); - otherUidDefaultCallback.assertNoCallback(); - - // Now bring down the per-app network. - setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false); - - // Since the callback didn't use the per-app network, only the other UID gets a callback. - // Because the preference specifies no fallback, it does not switch to cellular. - defaultNetworkCallback.assertNoCallback(); - otherUidDefaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent); - - // Now bring down the default network. - setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false); - - // As this callback was tracking the default, this should now trigger. - defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - otherUidDefaultCallback.assertNoCallback(); - - // Confirm we can unregister without issues. - mCm.unregisterNetworkCallback(defaultNetworkCallback); - mCm.unregisterNetworkCallback(otherUidDefaultCallback); - } - - /** - * This method assumes that the same uidRanges input will be used to verify that dependencies - * are called as expected. - */ - private void verifySetOemNetworkPreferenceForPreference( - @NonNull final UidRangeParcel[] uidRanges, - final int addUidRangesNetId, - final int addUidRangesTimes, - final int removeUidRangesNetId, - final int removeUidRangesTimes, - final boolean shouldDestroyNetwork) throws RemoteException { - verifySetOemNetworkPreferenceForPreference(uidRanges, uidRanges, - addUidRangesNetId, addUidRangesTimes, removeUidRangesNetId, removeUidRangesTimes, - shouldDestroyNetwork); - } - - private void verifySetOemNetworkPreferenceForPreference( - @NonNull final UidRangeParcel[] addedUidRanges, - @NonNull final UidRangeParcel[] removedUidRanges, - final int addUidRangesNetId, - final int addUidRangesTimes, - final int removeUidRangesNetId, - final int removeUidRangesTimes, - final boolean shouldDestroyNetwork) throws RemoteException { - final boolean useAnyIdForAdd = OEM_PREF_ANY_NET_ID == addUidRangesNetId; - final boolean useAnyIdForRemove = OEM_PREF_ANY_NET_ID == removeUidRangesNetId; - - // Validate netd. - verify(mMockNetd, times(addUidRangesTimes)) - .networkAddUidRanges( - (useAnyIdForAdd ? anyInt() : eq(addUidRangesNetId)), eq(addedUidRanges)); - verify(mMockNetd, times(removeUidRangesTimes)) - .networkRemoveUidRanges( - (useAnyIdForRemove ? anyInt() : eq(removeUidRangesNetId)), - eq(removedUidRanges)); - if (shouldDestroyNetwork) { - verify(mMockNetd, times(1)) - .networkDestroy((useAnyIdForRemove ? anyInt() : eq(removeUidRangesNetId))); - } - reset(mMockNetd); - } - - /** - * Test the tracked default requests clear previous OEM requests on setOemNetworkPreference(). - */ - @Test - public void testSetOemNetworkPreferenceClearPreviousOemValues() throws Exception { - @OemNetworkPreferences.OemNetworkPreference int networkPref = - OEM_NETWORK_PREFERENCE_OEM_PAID; - final int testPackageUid = 123; - final String testPackageName = "com.google.apps.contacts"; - final UidRangeParcel[] uidRanges = - toUidRangeStableParcels(uidRangesForUids(testPackageUid)); - - // Validate the starting requests only includes the fallback request. - assertEquals(1, mService.mDefaultNetworkRequests.size()); - - // Add an OEM default network request to track. - setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, testPackageName); - - // Two requests should exist, one for the fallback and one for the pref. - assertEquals(2, mService.mDefaultNetworkRequests.size()); - - networkPref = OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY; - setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, testPackageName); - - // Two requests should still exist validating the previous per-app request was replaced. - assertEquals(2, mService.mDefaultNetworkRequests.size()); - } - - /** - * Test network priority for preference OEM_NETWORK_PREFERENCE_OEM_PAID in the following order: - * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID -> fallback - */ - @Test - public void testMultilayerForPreferenceOemPaidEvaluatesCorrectly() - throws Exception { - @OemNetworkPreferences.OemNetworkPreference final int networkPref = - OEM_NETWORK_PREFERENCE_OEM_PAID; - - // Arrange PackageManager mocks - final UidRangeParcel[] uidRanges = - toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID)); - setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME); - - // Verify the starting state. No networks should be connected. - verifySetOemNetworkPreferenceForPreference(uidRanges, - OEM_PREF_ANY_NET_ID, 0 /* times */, - OEM_PREF_ANY_NET_ID, 0 /* times */, - false /* shouldDestroyNetwork */); - - // Test lowest to highest priority requests. - // Bring up metered cellular. This will satisfy the fallback network. - setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); - verifySetOemNetworkPreferenceForPreference(uidRanges, - mCellNetworkAgent.getNetwork().netId, 1 /* times */, - OEM_PREF_ANY_NET_ID, 0 /* times */, - false /* shouldDestroyNetwork */); - - // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID. - setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true); - verifySetOemNetworkPreferenceForPreference(uidRanges, - mEthernetNetworkAgent.getNetwork().netId, 1 /* times */, - mCellNetworkAgent.getNetwork().netId, 1 /* times */, - false /* shouldDestroyNetwork */); - - // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED. - setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true); - verifySetOemNetworkPreferenceForPreference(uidRanges, - mWiFiNetworkAgent.getNetwork().netId, 1 /* times */, - mEthernetNetworkAgent.getNetwork().netId, 1 /* times */, - false /* shouldDestroyNetwork */); - - // Disconnecting OEM_PAID should have no effect as it is lower in priority then unmetered. - setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false); - // netd should not be called as default networks haven't changed. - verifySetOemNetworkPreferenceForPreference(uidRanges, - OEM_PREF_ANY_NET_ID, 0 /* times */, - OEM_PREF_ANY_NET_ID, 0 /* times */, - false /* shouldDestroyNetwork */); - - // Disconnecting unmetered should put PANS on lowest priority fallback request. - setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false); - verifySetOemNetworkPreferenceForPreference(uidRanges, - mCellNetworkAgent.getNetwork().netId, 1 /* times */, - mWiFiNetworkAgent.getNetwork().netId, 0 /* times */, - true /* shouldDestroyNetwork */); - - // Disconnecting the fallback network should result in no connectivity. - setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false); - verifySetOemNetworkPreferenceForPreference(uidRanges, - OEM_PREF_ANY_NET_ID, 0 /* times */, - mCellNetworkAgent.getNetwork().netId, 0 /* times */, - true /* shouldDestroyNetwork */); - } - - /** - * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK in the following order: - * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID - */ - @Test - public void testMultilayerForPreferenceOemPaidNoFallbackEvaluatesCorrectly() - throws Exception { - @OemNetworkPreferences.OemNetworkPreference final int networkPref = - OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK; - - // Arrange PackageManager mocks - final UidRangeParcel[] uidRanges = - toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID)); - setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME); - - // Verify the starting state. This preference doesn't support using the fallback network - // therefore should be on the disconnected network as it has no networks to connect to. - verifySetOemNetworkPreferenceForPreference(uidRanges, - mService.mNoServiceNetwork.network.getNetId(), 1 /* times */, - OEM_PREF_ANY_NET_ID, 0 /* times */, - false /* shouldDestroyNetwork */); - - // Test lowest to highest priority requests. - // Bring up metered cellular. This will satisfy the fallback network. - // This preference should not use this network as it doesn't support fallback usage. - setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); - verifySetOemNetworkPreferenceForPreference(uidRanges, - OEM_PREF_ANY_NET_ID, 0 /* times */, - OEM_PREF_ANY_NET_ID, 0 /* times */, - false /* shouldDestroyNetwork */); - - // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID. - setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true); - verifySetOemNetworkPreferenceForPreference(uidRanges, - mEthernetNetworkAgent.getNetwork().netId, 1 /* times */, - mService.mNoServiceNetwork.network.getNetId(), 1 /* times */, - false /* shouldDestroyNetwork */); - - // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED. - setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true); - verifySetOemNetworkPreferenceForPreference(uidRanges, - mWiFiNetworkAgent.getNetwork().netId, 1 /* times */, - mEthernetNetworkAgent.getNetwork().netId, 1 /* times */, - false /* shouldDestroyNetwork */); - - // Disconnecting unmetered should put PANS on OEM_PAID. - setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false); - verifySetOemNetworkPreferenceForPreference(uidRanges, - mEthernetNetworkAgent.getNetwork().netId, 1 /* times */, - mWiFiNetworkAgent.getNetwork().netId, 0 /* times */, - true /* shouldDestroyNetwork */); - - // Disconnecting OEM_PAID should result in no connectivity. - // OEM_PAID_NO_FALLBACK not supporting a fallback now uses the disconnected network. - setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false); - verifySetOemNetworkPreferenceForPreference(uidRanges, - mService.mNoServiceNetwork.network.getNetId(), 1 /* times */, - mEthernetNetworkAgent.getNetwork().netId, 0 /* times */, - true /* shouldDestroyNetwork */); - } - - /** - * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY in the following order: - * NET_CAPABILITY_OEM_PAID - * This preference should only apply to OEM_PAID networks. - */ - @Test - public void testMultilayerForPreferenceOemPaidOnlyEvaluatesCorrectly() - throws Exception { - @OemNetworkPreferences.OemNetworkPreference final int networkPref = - OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; - - // Arrange PackageManager mocks - final UidRangeParcel[] uidRanges = - toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID)); - setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME); - - // Verify the starting state. This preference doesn't support using the fallback network - // therefore should be on the disconnected network as it has no networks to connect to. - verifySetOemNetworkPreferenceForPreference(uidRanges, - mService.mNoServiceNetwork.network.getNetId(), 1 /* times */, - OEM_PREF_ANY_NET_ID, 0 /* times */, - false /* shouldDestroyNetwork */); - - // Bring up metered cellular. This should not apply to this preference. - setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); - verifySetOemNetworkPreferenceForPreference(uidRanges, - OEM_PREF_ANY_NET_ID, 0 /* times */, - OEM_PREF_ANY_NET_ID, 0 /* times */, - false /* shouldDestroyNetwork */); - - // Bring up unmetered Wi-Fi. This should not apply to this preference. - setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true); - verifySetOemNetworkPreferenceForPreference(uidRanges, - OEM_PREF_ANY_NET_ID, 0 /* times */, - OEM_PREF_ANY_NET_ID, 0 /* times */, - false /* shouldDestroyNetwork */); - - // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID. - setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true); - verifySetOemNetworkPreferenceForPreference(uidRanges, - mEthernetNetworkAgent.getNetwork().netId, 1 /* times */, - mService.mNoServiceNetwork.network.getNetId(), 1 /* times */, - false /* shouldDestroyNetwork */); - - // Disconnecting OEM_PAID should result in no connectivity. - setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false); - verifySetOemNetworkPreferenceForPreference(uidRanges, - mService.mNoServiceNetwork.network.getNetId(), 1 /* times */, - mEthernetNetworkAgent.getNetwork().netId, 0 /* times */, - true /* shouldDestroyNetwork */); - } - - /** - * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY in the following order: - * NET_CAPABILITY_OEM_PRIVATE - * This preference should only apply to OEM_PRIVATE networks. - */ - @Test - public void testMultilayerForPreferenceOemPrivateOnlyEvaluatesCorrectly() - throws Exception { - @OemNetworkPreferences.OemNetworkPreference final int networkPref = - OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY; - - // Arrange PackageManager mocks - final UidRangeParcel[] uidRanges = - toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID)); - setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME); - - // Verify the starting state. This preference doesn't support using the fallback network - // therefore should be on the disconnected network as it has no networks to connect to. - verifySetOemNetworkPreferenceForPreference(uidRanges, - mService.mNoServiceNetwork.network.getNetId(), 1 /* times */, - OEM_PREF_ANY_NET_ID, 0 /* times */, - false /* shouldDestroyNetwork */); - - // Bring up metered cellular. This should not apply to this preference. - setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); - verifySetOemNetworkPreferenceForPreference(uidRanges, - OEM_PREF_ANY_NET_ID, 0 /* times */, - OEM_PREF_ANY_NET_ID, 0 /* times */, - false /* shouldDestroyNetwork */); - - // Bring up unmetered Wi-Fi. This should not apply to this preference. - setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true); - verifySetOemNetworkPreferenceForPreference(uidRanges, - OEM_PREF_ANY_NET_ID, 0 /* times */, - OEM_PREF_ANY_NET_ID, 0 /* times */, - false /* shouldDestroyNetwork */); - - // Bring up ethernet with OEM_PRIVATE. This will satisfy NET_CAPABILITY_OEM_PRIVATE. - startOemManagedNetwork(false); - verifySetOemNetworkPreferenceForPreference(uidRanges, - mEthernetNetworkAgent.getNetwork().netId, 1 /* times */, - mService.mNoServiceNetwork.network.getNetId(), 1 /* times */, - false /* shouldDestroyNetwork */); - - // Disconnecting OEM_PRIVATE should result in no connectivity. - stopOemManagedNetwork(); - verifySetOemNetworkPreferenceForPreference(uidRanges, - mService.mNoServiceNetwork.network.getNetId(), 1 /* times */, - mEthernetNetworkAgent.getNetwork().netId, 0 /* times */, - true /* shouldDestroyNetwork */); - } - - @Test - public void testMultilayerForMultipleUsersEvaluatesCorrectly() - throws Exception { - @OemNetworkPreferences.OemNetworkPreference final int networkPref = - OEM_NETWORK_PREFERENCE_OEM_PAID; - - // Arrange users - final int secondUser = 10; - final UserHandle secondUserHandle = new UserHandle(secondUser); - when(mUserManager.getUserHandles(anyBoolean())).thenReturn( - Arrays.asList(PRIMARY_USER_HANDLE, secondUserHandle)); - - // Arrange PackageManager mocks - final int secondUserTestPackageUid = UserHandle.getUid(secondUser, TEST_PACKAGE_UID); - final UidRangeParcel[] uidRanges = - toUidRangeStableParcels( - uidRangesForUids(TEST_PACKAGE_UID, secondUserTestPackageUid)); - setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME); - - // Verify the starting state. No networks should be connected. - verifySetOemNetworkPreferenceForPreference(uidRanges, - OEM_PREF_ANY_NET_ID, 0 /* times */, - OEM_PREF_ANY_NET_ID, 0 /* times */, - false /* shouldDestroyNetwork */); - - // Test that we correctly add the expected values for multiple users. - setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); - verifySetOemNetworkPreferenceForPreference(uidRanges, - mCellNetworkAgent.getNetwork().netId, 1 /* times */, - OEM_PREF_ANY_NET_ID, 0 /* times */, - false /* shouldDestroyNetwork */); - - // Test that we correctly remove the expected values for multiple users. - setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false); - verifySetOemNetworkPreferenceForPreference(uidRanges, - OEM_PREF_ANY_NET_ID, 0 /* times */, - mCellNetworkAgent.getNetwork().netId, 0 /* times */, - true /* shouldDestroyNetwork */); - } - - @Test - public void testMultilayerForBroadcastedUsersEvaluatesCorrectly() - throws Exception { - @OemNetworkPreferences.OemNetworkPreference final int networkPref = - OEM_NETWORK_PREFERENCE_OEM_PAID; - - // Arrange users - final int secondUser = 10; - final UserHandle secondUserHandle = new UserHandle(secondUser); - when(mUserManager.getUserHandles(anyBoolean())).thenReturn( - Arrays.asList(PRIMARY_USER_HANDLE)); - - // Arrange PackageManager mocks - final int secondUserTestPackageUid = UserHandle.getUid(secondUser, TEST_PACKAGE_UID); - final UidRangeParcel[] uidRangesSingleUser = - toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID)); - final UidRangeParcel[] uidRangesBothUsers = - toUidRangeStableParcels( - uidRangesForUids(TEST_PACKAGE_UID, secondUserTestPackageUid)); - setupSetOemNetworkPreferenceForPreferenceTest( - networkPref, uidRangesSingleUser, TEST_PACKAGE_NAME); - - // Verify the starting state. No networks should be connected. - verifySetOemNetworkPreferenceForPreference(uidRangesSingleUser, - OEM_PREF_ANY_NET_ID, 0 /* times */, - OEM_PREF_ANY_NET_ID, 0 /* times */, - false /* shouldDestroyNetwork */); - - // Test that we correctly add the expected values for multiple users. - setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); - verifySetOemNetworkPreferenceForPreference(uidRangesSingleUser, - mCellNetworkAgent.getNetwork().netId, 1 /* times */, - OEM_PREF_ANY_NET_ID, 0 /* times */, - false /* shouldDestroyNetwork */); - - // Send a broadcast indicating a user was added. - when(mUserManager.getUserHandles(anyBoolean())).thenReturn( - Arrays.asList(PRIMARY_USER_HANDLE, secondUserHandle)); - final Intent addedIntent = new Intent(ACTION_USER_ADDED); - addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(secondUser)); - processBroadcast(addedIntent); - - // Test that we correctly add values for all users and remove for the single user. - verifySetOemNetworkPreferenceForPreference(uidRangesBothUsers, uidRangesSingleUser, - mCellNetworkAgent.getNetwork().netId, 1 /* times */, - mCellNetworkAgent.getNetwork().netId, 1 /* times */, - false /* shouldDestroyNetwork */); - - // Send a broadcast indicating a user was removed. - when(mUserManager.getUserHandles(anyBoolean())).thenReturn( - Arrays.asList(PRIMARY_USER_HANDLE)); - final Intent removedIntent = new Intent(ACTION_USER_REMOVED); - removedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(secondUser)); - processBroadcast(removedIntent); - - // Test that we correctly add values for the single user and remove for the all users. - verifySetOemNetworkPreferenceForPreference(uidRangesSingleUser, uidRangesBothUsers, - mCellNetworkAgent.getNetwork().netId, 1 /* times */, - mCellNetworkAgent.getNetwork().netId, 1 /* times */, - false /* shouldDestroyNetwork */); - } - - @Test - public void testMultilayerForPackageChangesEvaluatesCorrectly() - throws Exception { - @OemNetworkPreferences.OemNetworkPreference final int networkPref = - OEM_NETWORK_PREFERENCE_OEM_PAID; - final String packageScheme = "package:"; - - // Arrange PackageManager mocks - final String packageToInstall = "package.to.install"; - final int packageToInstallUid = 81387; - final UidRangeParcel[] uidRangesSinglePackage = - toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID)); - mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID); - mockGetApplicationInfoThrowsNameNotFound(packageToInstall); - setOemNetworkPreference(networkPref, TEST_PACKAGE_NAME, packageToInstall); - grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid(), packageToInstall); - - // Verify the starting state. No networks should be connected. - verifySetOemNetworkPreferenceForPreference(uidRangesSinglePackage, - OEM_PREF_ANY_NET_ID, 0 /* times */, - OEM_PREF_ANY_NET_ID, 0 /* times */, - false /* shouldDestroyNetwork */); - - // Test that we correctly add the expected values for installed packages. - setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); - verifySetOemNetworkPreferenceForPreference(uidRangesSinglePackage, - mCellNetworkAgent.getNetwork().netId, 1 /* times */, - OEM_PREF_ANY_NET_ID, 0 /* times */, - false /* shouldDestroyNetwork */); - - // Set the system to recognize the package to be installed - mockGetApplicationInfo(packageToInstall, packageToInstallUid); - final UidRangeParcel[] uidRangesAllPackages = - toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID, packageToInstallUid)); - - // Send a broadcast indicating a package was installed. - final Intent addedIntent = new Intent(ACTION_PACKAGE_ADDED); - addedIntent.setData(Uri.parse(packageScheme + packageToInstall)); - processBroadcast(addedIntent); - - // Test the single package is removed and the combined packages are added. - verifySetOemNetworkPreferenceForPreference(uidRangesAllPackages, uidRangesSinglePackage, - mCellNetworkAgent.getNetwork().netId, 1 /* times */, - mCellNetworkAgent.getNetwork().netId, 1 /* times */, - false /* shouldDestroyNetwork */); - - // Set the system to no longer recognize the package to be installed - mockGetApplicationInfoThrowsNameNotFound(packageToInstall); - - // Send a broadcast indicating a package was removed. - final Intent removedIntent = new Intent(ACTION_PACKAGE_REMOVED); - removedIntent.setData(Uri.parse(packageScheme + packageToInstall)); - processBroadcast(removedIntent); - - // Test the combined packages are removed and the single package is added. - verifySetOemNetworkPreferenceForPreference(uidRangesSinglePackage, uidRangesAllPackages, - mCellNetworkAgent.getNetwork().netId, 1 /* times */, - mCellNetworkAgent.getNetwork().netId, 1 /* times */, - false /* shouldDestroyNetwork */); - - // Set the system to change the installed package's uid - final int replacedTestPackageUid = TEST_PACKAGE_UID + 1; - mockGetApplicationInfo(TEST_PACKAGE_NAME, replacedTestPackageUid); - final UidRangeParcel[] uidRangesReplacedPackage = - toUidRangeStableParcels(uidRangesForUids(replacedTestPackageUid)); - - // Send a broadcast indicating a package was replaced. - final Intent replacedIntent = new Intent(ACTION_PACKAGE_REPLACED); - replacedIntent.setData(Uri.parse(packageScheme + TEST_PACKAGE_NAME)); - processBroadcast(replacedIntent); - - // Test the original uid is removed and is replaced with the new uid. - verifySetOemNetworkPreferenceForPreference(uidRangesReplacedPackage, uidRangesSinglePackage, - mCellNetworkAgent.getNetwork().netId, 1 /* times */, - mCellNetworkAgent.getNetwork().netId, 1 /* times */, - false /* shouldDestroyNetwork */); - } - - /** - * Test network priority for preference OEM_NETWORK_PREFERENCE_OEM_PAID in the following order: - * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID -> fallback - */ - @Test - public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPaidCorrectly() - throws Exception { - @OemNetworkPreferences.OemNetworkPreference final int networkPref = - OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID; - setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref); - final int expectedDefaultRequestSize = 2; - final int expectedOemPrefRequestSize = 3; - registerDefaultNetworkCallbacks(); - - // The fallback as well as the OEM preference should now be tracked. - assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size()); - - // Test lowest to highest priority requests. - // Bring up metered cellular. This will satisfy the fallback network. - setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - mCellNetworkAgent.getNetwork(), - mCellNetworkAgent.getNetwork()); - - // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID. - setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - mCellNetworkAgent.getNetwork(), - mEthernetNetworkAgent.getNetwork()); - - // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED. - setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - mWiFiNetworkAgent.getNetwork(), - mWiFiNetworkAgent.getNetwork()); - - // Disconnecting unmetered Wi-Fi will put the pref on OEM_PAID and fallback on cellular. - setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - mCellNetworkAgent.getNetwork(), - mEthernetNetworkAgent.getNetwork()); - - // Disconnecting cellular should keep OEM network on OEM_PAID and fallback will be null. - setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - null, - mEthernetNetworkAgent.getNetwork()); - - // Disconnecting OEM_PAID will put both on null as it is the last network. - setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - null, - null); - - // default callbacks will be unregistered in tearDown - } - - @Test - public void testNetworkFactoryRequestsWithMultilayerRequest() - throws Exception { - // First use OEM_PAID preference to create a multi-layer request : 1. listen for - // unmetered, 2. request network with cap OEM_PAID, 3, request the default network for - // fallback. - @OemNetworkPreferences.OemNetworkPreference final int networkPref = - OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID; - setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref); - - final HandlerThread handlerThread = new HandlerThread("MockFactory"); - handlerThread.start(); - NetworkCapabilities internetFilter = new NetworkCapabilities() - .addCapability(NET_CAPABILITY_INTERNET) - .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); - final MockNetworkFactory internetFactory = new MockNetworkFactory(handlerThread.getLooper(), - mServiceContext, "internetFactory", internetFilter, mCsHandlerThread); - internetFactory.setScoreFilter(40); - internetFactory.register(); - // Default internet request only. The unmetered request is never sent to factories (it's a - // LISTEN, not requestable). The 3rd (fallback) request in OEM_PAID NRI is TRACK_DEFAULT - // which is also not sent to factories. Finally, the OEM_PAID request doesn't match the - // internetFactory filter. - internetFactory.expectRequestAdds(1); - internetFactory.assertRequestCountEquals(1); - - NetworkCapabilities oemPaidFilter = new NetworkCapabilities() - .addCapability(NET_CAPABILITY_INTERNET) - .addCapability(NET_CAPABILITY_OEM_PAID) - .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) - .removeCapability(NET_CAPABILITY_NOT_RESTRICTED); - final MockNetworkFactory oemPaidFactory = new MockNetworkFactory(handlerThread.getLooper(), - mServiceContext, "oemPaidFactory", oemPaidFilter, mCsHandlerThread); - oemPaidFactory.setScoreFilter(40); - oemPaidFactory.register(); - oemPaidFactory.expectRequestAdd(); // Because nobody satisfies the request - - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - - // A network connected that satisfies the default internet request. For the OEM_PAID - // preference, this is not as good as an OEM_PAID network, so even if the score of - // the network is better than the factory announced, it still should try to bring up - // the network. - expectNoRequestChanged(oemPaidFactory); - oemPaidFactory.assertRequestCountEquals(1); - // The internet factory however is outscored, and should lose its requests. - internetFactory.expectRequestRemove(); - internetFactory.assertRequestCountEquals(0); - - final NetworkCapabilities oemPaidNc = new NetworkCapabilities(); - oemPaidNc.addCapability(NET_CAPABILITY_OEM_PAID); - oemPaidNc.removeCapability(NET_CAPABILITY_NOT_RESTRICTED); - final TestNetworkAgentWrapper oemPaidAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, - new LinkProperties(), oemPaidNc); - oemPaidAgent.connect(true); - - // The oemPaidAgent has score 50/cell transport, so it beats what the oemPaidFactory can - // provide, therefore it loses the request. - oemPaidFactory.expectRequestRemove(); - oemPaidFactory.assertRequestCountEquals(0); - expectNoRequestChanged(internetFactory); - internetFactory.assertRequestCountEquals(0); - - oemPaidAgent.setScore(new NetworkScore.Builder().setLegacyInt(20).setExiting(true).build()); - // Now the that the agent is weak, the oemPaidFactory can beat the existing network for the - // OEM_PAID request. The internet factory however can't beat a network that has OEM_PAID - // for the preference request, so it doesn't see the request. - oemPaidFactory.expectRequestAdd(); - oemPaidFactory.assertRequestCountEquals(1); - expectNoRequestChanged(internetFactory); - internetFactory.assertRequestCountEquals(0); - - mCellNetworkAgent.disconnect(); - // The network satisfying the default internet request has disconnected, so the - // internetFactory sees the default request again. However there is a network with OEM_PAID - // connected, so the 2nd OEM_PAID req is already satisfied, so the oemPaidFactory doesn't - // care about networks that don't have OEM_PAID. - expectNoRequestChanged(oemPaidFactory); - oemPaidFactory.assertRequestCountEquals(1); - internetFactory.expectRequestAdd(); - internetFactory.assertRequestCountEquals(1); - - // Cell connects again, still with score 50. Back to the previous state. - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - expectNoRequestChanged(oemPaidFactory); - oemPaidFactory.assertRequestCountEquals(1); - internetFactory.expectRequestRemove(); - internetFactory.assertRequestCountEquals(0); - - // Create a request that holds the upcoming wifi network. - final TestNetworkCallback wifiCallback = new TestNetworkCallback(); - mCm.requestNetwork(new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build(), - wifiCallback); - - // Now WiFi connects and it's unmetered, but it's weaker than cell. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); - mWiFiNetworkAgent.setScore(new NetworkScore.Builder().setLegacyInt(30).setExiting(true) - .build()); // Not the best Internet network, but unmetered - mWiFiNetworkAgent.connect(true); - - // The OEM_PAID preference prefers an unmetered network to an OEM_PAID network, so - // the oemPaidFactory can't beat wifi no matter how high its score. - oemPaidFactory.expectRequestRemove(); - expectNoRequestChanged(internetFactory); - - mCellNetworkAgent.disconnect(); - // Now that the best internet network (cell, with its 50 score compared to 30 for WiFi - // at this point), the default internet request is satisfied by a network worse than - // the internetFactory announced, so it gets the request. However, there is still an - // unmetered network, so the oemPaidNetworkFactory still can't beat this. - expectNoRequestChanged(oemPaidFactory); - internetFactory.expectRequestAdd(); - mCm.unregisterNetworkCallback(wifiCallback); - } - - /** - * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK in the following order: - * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID - */ - @Test - public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPaidNoFallbackCorrectly() - throws Exception { - @OemNetworkPreferences.OemNetworkPreference final int networkPref = - OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK; - setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref); - final int expectedDefaultRequestSize = 2; - final int expectedOemPrefRequestSize = 2; - registerDefaultNetworkCallbacks(); - - // The fallback as well as the OEM preference should now be tracked. - assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size()); - - // Test lowest to highest priority requests. - // Bring up metered cellular. This will satisfy the fallback network but not the pref. - setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - mCellNetworkAgent.getNetwork(), - mService.mNoServiceNetwork.network()); - - // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID. - setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - mCellNetworkAgent.getNetwork(), - mEthernetNetworkAgent.getNetwork()); - - // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED. - setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - mWiFiNetworkAgent.getNetwork(), - mWiFiNetworkAgent.getNetwork()); - - // Disconnecting unmetered Wi-Fi will put the OEM pref on OEM_PAID and fallback on cellular. - setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - mCellNetworkAgent.getNetwork(), - mEthernetNetworkAgent.getNetwork()); - - // Disconnecting cellular should keep OEM network on OEM_PAID and fallback will be null. - setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - null, - mEthernetNetworkAgent.getNetwork()); - - // Disconnecting OEM_PAID puts the fallback on null and the pref on the disconnected net. - setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - null, - mService.mNoServiceNetwork.network()); - - // default callbacks will be unregistered in tearDown - } - - /** - * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY in the following order: - * NET_CAPABILITY_OEM_PAID - * This preference should only apply to OEM_PAID networks. - */ - @Test - public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPaidOnlyCorrectly() - throws Exception { - @OemNetworkPreferences.OemNetworkPreference final int networkPref = - OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; - setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref); - final int expectedDefaultRequestSize = 2; - final int expectedOemPrefRequestSize = 1; - registerDefaultNetworkCallbacks(); - - // The fallback as well as the OEM preference should now be tracked. - assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size()); - - // Test lowest to highest priority requests. - // Bring up metered cellular. This will satisfy the fallback network. - setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - mCellNetworkAgent.getNetwork(), - mService.mNoServiceNetwork.network()); - - // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID. - setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - mCellNetworkAgent.getNetwork(), - mEthernetNetworkAgent.getNetwork()); - - // Bring up unmetered Wi-Fi. The OEM network shouldn't change, the fallback will take Wi-Fi. - setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - mWiFiNetworkAgent.getNetwork(), - mEthernetNetworkAgent.getNetwork()); - - // Disconnecting unmetered Wi-Fi shouldn't change the OEM network with fallback on cellular. - setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - mCellNetworkAgent.getNetwork(), - mEthernetNetworkAgent.getNetwork()); - - // Disconnecting OEM_PAID will keep the fallback on cellular and nothing for OEM_PAID. - // OEM_PAID_ONLY not supporting a fallback now uses the disconnected network. - setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - mCellNetworkAgent.getNetwork(), - mService.mNoServiceNetwork.network()); - - // Disconnecting cellular will put the fallback on null and the pref on disconnected. - setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - null, - mService.mNoServiceNetwork.network()); - - // default callbacks will be unregistered in tearDown - } - - /** - * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY in the following order: - * NET_CAPABILITY_OEM_PRIVATE - * This preference should only apply to OEM_PRIVATE networks. - */ - @Test - public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPrivateOnlyCorrectly() - throws Exception { - @OemNetworkPreferences.OemNetworkPreference final int networkPref = - OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY; - setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref); - final int expectedDefaultRequestSize = 2; - final int expectedOemPrefRequestSize = 1; - registerDefaultNetworkCallbacks(); - - // The fallback as well as the OEM preference should now be tracked. - assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size()); - - // Test lowest to highest priority requests. - // Bring up metered cellular. This will satisfy the fallback network. - setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - mCellNetworkAgent.getNetwork(), - mService.mNoServiceNetwork.network()); - - // Bring up ethernet with OEM_PRIVATE. This will satisfy NET_CAPABILITY_OEM_PRIVATE. - startOemManagedNetwork(false); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - mCellNetworkAgent.getNetwork(), - mEthernetNetworkAgent.getNetwork()); - - // Bring up unmetered Wi-Fi. The OEM network shouldn't change, the fallback will take Wi-Fi. - setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - mWiFiNetworkAgent.getNetwork(), - mEthernetNetworkAgent.getNetwork()); - - // Disconnecting unmetered Wi-Fi shouldn't change the OEM network with fallback on cellular. - setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - mCellNetworkAgent.getNetwork(), - mEthernetNetworkAgent.getNetwork()); - - // Disconnecting OEM_PRIVATE will keep the fallback on cellular. - // OEM_PRIVATE_ONLY not supporting a fallback now uses to the disconnected network. - stopOemManagedNetwork(); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - mCellNetworkAgent.getNetwork(), - mService.mNoServiceNetwork.network()); - - // Disconnecting cellular will put the fallback on null and pref on disconnected. - setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false); - verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, - null, - mService.mNoServiceNetwork.network()); - - // default callbacks will be unregistered in tearDown - } - - @Test - public void testCapabilityWithOemNetworkPreference() throws Exception { - @OemNetworkPreferences.OemNetworkPreference final int networkPref = - OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY; - setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(networkPref); - registerDefaultNetworkCallbacks(); - - setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); - - mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - - mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED); - mSystemDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc -> - nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); - mDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc -> - nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); - - // default callbacks will be unregistered in tearDown - } - - @Test - public void testSetOemNetworkPreferenceLogsRequest() throws Exception { - mServiceContext.setPermission(DUMP, PERMISSION_GRANTED); - @OemNetworkPreferences.OemNetworkPreference final int networkPref = - OEM_NETWORK_PREFERENCE_OEM_PAID; - final StringWriter stringWriter = new StringWriter(); - final String logIdentifier = "UPDATE INITIATED: OemNetworkPreferences"; - final Pattern pattern = Pattern.compile(logIdentifier); - - final int expectedNumLogs = 2; - final UidRangeParcel[] uidRanges = - toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID)); - - // Call twice to generate two logs. - setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME); - setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME); - mService.dump(new FileDescriptor(), new PrintWriter(stringWriter), new String[0]); - - final String dumpOutput = stringWriter.toString(); - final Matcher matcher = pattern.matcher(dumpOutput); - int count = 0; - while (matcher.find()) { - count++; - } - assertEquals(expectedNumLogs, count); - } - - @Test - public void testGetAllNetworkStateSnapshots() throws Exception { - verifyNoNetwork(); - - // Setup test cellular network with specified LinkProperties and NetworkCapabilities, - // verify the content of the snapshot matches. - final LinkProperties cellLp = new LinkProperties(); - final LinkAddress myIpv4Addr = new LinkAddress(InetAddress.getByName("192.0.2.129"), 25); - final LinkAddress myIpv6Addr = new LinkAddress(InetAddress.getByName("2001:db8::1"), 64); - cellLp.setInterfaceName("test01"); - cellLp.addLinkAddress(myIpv4Addr); - cellLp.addLinkAddress(myIpv6Addr); - cellLp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234"))); - cellLp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254"))); - cellLp.addRoute(new RouteInfo(myIpv4Addr, null)); - cellLp.addRoute(new RouteInfo(myIpv6Addr, null)); - final NetworkCapabilities cellNcTemplate = new NetworkCapabilities.Builder() - .addTransportType(TRANSPORT_CELLULAR).addCapability(NET_CAPABILITY_MMS).build(); - - final TestNetworkCallback cellCb = new TestNetworkCallback(); - mCm.requestNetwork(new NetworkRequest.Builder().addCapability(NET_CAPABILITY_MMS).build(), - cellCb); - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp, cellNcTemplate); - mCellNetworkAgent.connect(true); - cellCb.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); - List snapshots = mCm.getAllNetworkStateSnapshots(); - assertLength(1, snapshots); - - // Compose the expected cellular snapshot for verification. - final NetworkCapabilities cellNc = - mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()); - final NetworkStateSnapshot cellSnapshot = new NetworkStateSnapshot( - mCellNetworkAgent.getNetwork(), cellNc, cellLp, - null, ConnectivityManager.TYPE_MOBILE); - assertEquals(cellSnapshot, snapshots.get(0)); - - // Connect wifi and verify the snapshots. - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true); - waitForIdle(); - // Compose the expected wifi snapshot for verification. - final NetworkCapabilities wifiNc = - mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()); - final NetworkStateSnapshot wifiSnapshot = new NetworkStateSnapshot( - mWiFiNetworkAgent.getNetwork(), wifiNc, new LinkProperties(), null, - ConnectivityManager.TYPE_WIFI); - - snapshots = mCm.getAllNetworkStateSnapshots(); - assertLength(2, snapshots); - assertContainsAll(snapshots, cellSnapshot, wifiSnapshot); - - // Set cellular as suspended, verify the snapshots will not contain suspended networks. - // TODO: Consider include SUSPENDED networks, which should be considered as - // temporary shortage of connectivity of a connected network. - mCellNetworkAgent.suspend(); - waitForIdle(); - snapshots = mCm.getAllNetworkStateSnapshots(); - assertLength(1, snapshots); - assertEquals(wifiSnapshot, snapshots.get(0)); - - // Disconnect wifi, verify the snapshots contain nothing. - mWiFiNetworkAgent.disconnect(); - waitForIdle(); - snapshots = mCm.getAllNetworkStateSnapshots(); - assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); - assertLength(0, snapshots); - - mCellNetworkAgent.resume(); - waitForIdle(); - snapshots = mCm.getAllNetworkStateSnapshots(); - assertLength(1, snapshots); - assertEquals(cellSnapshot, snapshots.get(0)); - - mCellNetworkAgent.disconnect(); - waitForIdle(); - verifyNoNetwork(); - mCm.unregisterNetworkCallback(cellCb); - } - - // Cannot be part of MockNetworkFactory since it requires method of the test. - private void expectNoRequestChanged(@NonNull MockNetworkFactory factory) { - waitForIdle(); - factory.assertNoRequestChanged(); - } - - @Test - public void testRegisterBestMatchingNetworkCallback_noIssueToFactory() throws Exception { - // Prepare mock mms factory. - final HandlerThread handlerThread = new HandlerThread("MockCellularFactory"); - handlerThread.start(); - NetworkCapabilities filter = new NetworkCapabilities() - .addTransportType(TRANSPORT_CELLULAR) - .addCapability(NET_CAPABILITY_MMS); - final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), - mServiceContext, "testFactory", filter, mCsHandlerThread); - testFactory.setScoreFilter(40); - - try { - // Register the factory. It doesn't see the default request because its filter does - // not include INTERNET. - testFactory.register(); - expectNoRequestChanged(testFactory); - testFactory.assertRequestCountEquals(0); - // The factory won't try to start the network since the default request doesn't - // match the filter (no INTERNET capability). - assertFalse(testFactory.getMyStartRequested()); - - // Register callback for listening best matching network. Verify that the request won't - // be sent to factory. - final TestNetworkCallback bestMatchingCb = new TestNetworkCallback(); - mCm.registerBestMatchingNetworkCallback( - new NetworkRequest.Builder().addCapability(NET_CAPABILITY_MMS).build(), - bestMatchingCb, mCsHandlerThread.getThreadHandler()); - bestMatchingCb.assertNoCallback(); - expectNoRequestChanged(testFactory); - testFactory.assertRequestCountEquals(0); - assertFalse(testFactory.getMyStartRequested()); - - // Fire a normal mms request, verify the factory will only see the request. - final TestNetworkCallback mmsNetworkCallback = new TestNetworkCallback(); - final NetworkRequest mmsRequest = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_MMS).build(); - mCm.requestNetwork(mmsRequest, mmsNetworkCallback); - testFactory.expectRequestAdd(); - testFactory.assertRequestCountEquals(1); - assertTrue(testFactory.getMyStartRequested()); - - // Unregister best matching callback, verify factory see no change. - mCm.unregisterNetworkCallback(bestMatchingCb); - expectNoRequestChanged(testFactory); - testFactory.assertRequestCountEquals(1); - assertTrue(testFactory.getMyStartRequested()); - } finally { - testFactory.terminate(); - } - } - - @Test - public void testRegisterBestMatchingNetworkCallback_trackBestNetwork() throws Exception { - final TestNetworkCallback bestMatchingCb = new TestNetworkCallback(); - mCm.registerBestMatchingNetworkCallback( - new NetworkRequest.Builder().addCapability(NET_CAPABILITY_TRUSTED).build(), - bestMatchingCb, mCsHandlerThread.getThreadHandler()); - - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - bestMatchingCb.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - - mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true); - bestMatchingCb.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); - - // Change something on cellular to trigger capabilities changed, since the callback - // only cares about the best network, verify it received nothing from cellular. - mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED); - bestMatchingCb.assertNoCallback(); - - // Make cellular the best network again, verify the callback now tracks cellular. - mWiFiNetworkAgent.adjustScore(-50); - bestMatchingCb.expectAvailableCallbacksValidated(mCellNetworkAgent); - - // Make cellular temporary non-trusted, which will not satisfying the request. - // Verify the callback switch from/to the other network accordingly. - mCellNetworkAgent.removeCapability(NET_CAPABILITY_TRUSTED); - bestMatchingCb.expectAvailableCallbacksValidated(mWiFiNetworkAgent); - mCellNetworkAgent.addCapability(NET_CAPABILITY_TRUSTED); - bestMatchingCb.expectAvailableDoubleValidatedCallbacks(mCellNetworkAgent); - - // Verify the callback doesn't care about wifi disconnect. - mWiFiNetworkAgent.disconnect(); - bestMatchingCb.assertNoCallback(); - mCellNetworkAgent.disconnect(); - bestMatchingCb.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - } - - private UidRangeParcel[] uidRangeFor(final UserHandle handle) { - UidRange range = UidRange.createForUser(handle); - return new UidRangeParcel[] { new UidRangeParcel(range.start, range.stop) }; - } - - private static class TestOnCompleteListener implements Runnable { - final class OnComplete {} - final ArrayTrackRecord.ReadHead mHistory = - new ArrayTrackRecord().newReadHead(); - - @Override - public void run() { - mHistory.add(new OnComplete()); - } - - public void expectOnComplete() { - assertNotNull(mHistory.poll(TIMEOUT_MS, it -> true)); - } - } - - private TestNetworkAgentWrapper makeEnterpriseNetworkAgent() throws Exception { - final NetworkCapabilities workNc = new NetworkCapabilities(); - workNc.addCapability(NET_CAPABILITY_ENTERPRISE); - workNc.removeCapability(NET_CAPABILITY_NOT_RESTRICTED); - return new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(), workNc); - } - - private TestNetworkCallback mEnterpriseCallback; - private UserHandle setupEnterpriseNetwork() { - final UserHandle userHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID); - mServiceContext.setWorkProfile(userHandle, true); - - // File a request to avoid the enterprise network being disconnected as soon as the default - // request goes away – it would make impossible to test that networkRemoveUidRanges - // is called, as the network would disconnect first for lack of a request. - mEnterpriseCallback = new TestNetworkCallback(); - final NetworkRequest keepUpRequest = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_ENTERPRISE) - .build(); - mCm.requestNetwork(keepUpRequest, mEnterpriseCallback); - return userHandle; - } - - private void maybeTearDownEnterpriseNetwork() { - if (null != mEnterpriseCallback) { - mCm.unregisterNetworkCallback(mEnterpriseCallback); - } - } - - /** - * Make sure per-profile networking preference behaves as expected when the enterprise network - * goes up and down while the preference is active. Make sure they behave as expected whether - * there is a general default network or not. - */ - @Test - public void testPreferenceForUserNetworkUpDown() throws Exception { - final InOrder inOrder = inOrder(mMockNetd); - final UserHandle testHandle = setupEnterpriseNetwork(); - registerDefaultNetworkCallbacks(); - - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - - mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical( - mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE)); - - - final TestOnCompleteListener listener = new TestOnCompleteListener(); - mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE, - r -> r.run(), listener); - listener.expectOnComplete(); - - // Setting a network preference for this user will create a new set of routing rules for - // the UID range that corresponds to this user, so as to define the default network - // for these apps separately. This is true because the multi-layer request relevant to - // this UID range contains a TRACK_DEFAULT, so the range will be moved through UID-specific - // rules to the correct network – in this case the system default network. The case where - // the default network for the profile happens to be the same as the system default - // is not handled specially, the rules are always active as long as a preference is set. - inOrder.verify(mMockNetd).networkAddUidRanges(mCellNetworkAgent.getNetwork().netId, - uidRangeFor(testHandle)); - - // The enterprise network is not ready yet. - assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback, - mProfileDefaultNetworkCallback); - - final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent(); - workAgent.connect(false); - - mProfileDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(workAgent); - mSystemDefaultNetworkCallback.assertNoCallback(); - mDefaultNetworkCallback.assertNoCallback(); - inOrder.verify(mMockNetd).networkCreate( - nativeNetworkConfigPhysical(workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM)); - inOrder.verify(mMockNetd).networkAddUidRanges(workAgent.getNetwork().netId, - uidRangeFor(testHandle)); - inOrder.verify(mMockNetd).networkRemoveUidRanges(mCellNetworkAgent.getNetwork().netId, - uidRangeFor(testHandle)); - - // Make sure changes to the work agent send callbacks to the app in the work profile, but - // not to the other apps. - workAgent.setNetworkValid(true /* isStrictMode */); - workAgent.mNetworkMonitor.forceReevaluation(Process.myUid()); - mProfileDefaultNetworkCallback.expectCapabilitiesThat(workAgent, - nc -> nc.hasCapability(NET_CAPABILITY_VALIDATED) - && nc.hasCapability(NET_CAPABILITY_ENTERPRISE)); - assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback); - - workAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED); - mProfileDefaultNetworkCallback.expectCapabilitiesThat(workAgent, nc -> - nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); - assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback); - - // Conversely, change a capability on the system-wide default network and make sure - // that only the apps outside of the work profile receive the callbacks. - mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED); - mSystemDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc -> - nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); - mDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc -> - nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); - mProfileDefaultNetworkCallback.assertNoCallback(); - - // Disconnect and reconnect the system-wide default network and make sure that the - // apps on this network see the appropriate callbacks, and the app on the work profile - // doesn't because it continues to use the enterprise network. - mCellNetworkAgent.disconnect(); - mSystemDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - mDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - mProfileDefaultNetworkCallback.assertNoCallback(); - inOrder.verify(mMockNetd).networkDestroy(mCellNetworkAgent.getNetwork().netId); - - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - mProfileDefaultNetworkCallback.assertNoCallback(); - inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical( - mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE)); - - // When the agent disconnects, test that the app on the work profile falls back to the - // default network. - workAgent.disconnect(); - mProfileDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, workAgent); - mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); - assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback); - inOrder.verify(mMockNetd).networkAddUidRanges(mCellNetworkAgent.getNetwork().netId, - uidRangeFor(testHandle)); - inOrder.verify(mMockNetd).networkDestroy(workAgent.getNetwork().netId); - - mCellNetworkAgent.disconnect(); - mSystemDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - mDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - mProfileDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); - - // Waiting for the handler to be idle before checking for networkDestroy is necessary - // here because ConnectivityService calls onLost before the network is fully torn down. - waitForIdle(); - inOrder.verify(mMockNetd).networkDestroy(mCellNetworkAgent.getNetwork().netId); - - // If the control comes here, callbacks seem to behave correctly in the presence of - // a default network when the enterprise network goes up and down. Now, make sure they - // also behave correctly in the absence of a system-wide default network. - final TestNetworkAgentWrapper workAgent2 = makeEnterpriseNetworkAgent(); - workAgent2.connect(false); - - mProfileDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(workAgent2); - assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback); - inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical( - workAgent2.getNetwork().netId, INetd.PERMISSION_SYSTEM)); - inOrder.verify(mMockNetd).networkAddUidRanges(workAgent2.getNetwork().netId, - uidRangeFor(testHandle)); - - workAgent2.setNetworkValid(true /* isStrictMode */); - workAgent2.mNetworkMonitor.forceReevaluation(Process.myUid()); - mProfileDefaultNetworkCallback.expectCapabilitiesThat(workAgent2, - nc -> nc.hasCapability(NET_CAPABILITY_ENTERPRISE) - && !nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); - assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback); - inOrder.verify(mMockNetd, never()).networkAddUidRanges(anyInt(), any()); - - // When the agent disconnects, test that the app on the work profile falls back to the - // default network. - workAgent2.disconnect(); - mProfileDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, workAgent2); - assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback); - inOrder.verify(mMockNetd).networkDestroy(workAgent2.getNetwork().netId); - - assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback, - mProfileDefaultNetworkCallback); - - // Callbacks will be unregistered by tearDown() - } - - /** - * Test that, in a given networking context, calling setPreferenceForUser to set per-profile - * defaults on then off works as expected. - */ - @Test - public void testSetPreferenceForUserOnOff() throws Exception { - final InOrder inOrder = inOrder(mMockNetd); - final UserHandle testHandle = setupEnterpriseNetwork(); - - // Connect both a regular cell agent and an enterprise network first. - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - - final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent(); - workAgent.connect(true); - - final TestOnCompleteListener listener = new TestOnCompleteListener(); - mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE, - r -> r.run(), listener); - listener.expectOnComplete(); - inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical( - mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE)); - inOrder.verify(mMockNetd).networkAddUidRanges(workAgent.getNetwork().netId, - uidRangeFor(testHandle)); - - registerDefaultNetworkCallbacks(); - - mSystemDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); - mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); - mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent); - - mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_DEFAULT, - r -> r.run(), listener); - listener.expectOnComplete(); - - mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); - assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback); - inOrder.verify(mMockNetd).networkRemoveUidRanges(workAgent.getNetwork().netId, - uidRangeFor(testHandle)); - - workAgent.disconnect(); - mCellNetworkAgent.disconnect(); - - // Callbacks will be unregistered by tearDown() - } - - /** - * Test per-profile default networks for two different profiles concurrently. - */ - @Test - public void testSetPreferenceForTwoProfiles() throws Exception { - final InOrder inOrder = inOrder(mMockNetd); - final UserHandle testHandle2 = setupEnterpriseNetwork(); - final UserHandle testHandle4 = UserHandle.of(TEST_WORK_PROFILE_USER_ID + 2); - mServiceContext.setWorkProfile(testHandle4, true); - registerDefaultNetworkCallbacks(); - - final TestNetworkCallback app4Cb = new TestNetworkCallback(); - final int testWorkProfileAppUid4 = - UserHandle.getUid(testHandle4.getIdentifier(), TEST_APP_ID); - registerDefaultNetworkCallbackAsUid(app4Cb, testWorkProfileAppUid4); - - // Connect both a regular cell agent and an enterprise network first. - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - - final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent(); - workAgent.connect(true); - - mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - app4Cb.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical( - mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE)); - inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical( - workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM)); - - final TestOnCompleteListener listener = new TestOnCompleteListener(); - mCm.setProfileNetworkPreference(testHandle2, PROFILE_NETWORK_PREFERENCE_ENTERPRISE, - r -> r.run(), listener); - listener.expectOnComplete(); - inOrder.verify(mMockNetd).networkAddUidRanges(workAgent.getNetwork().netId, - uidRangeFor(testHandle2)); - - mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent); - assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback, - app4Cb); - - mCm.setProfileNetworkPreference(testHandle4, PROFILE_NETWORK_PREFERENCE_ENTERPRISE, - r -> r.run(), listener); - listener.expectOnComplete(); - inOrder.verify(mMockNetd).networkAddUidRanges(workAgent.getNetwork().netId, - uidRangeFor(testHandle4)); - - app4Cb.expectAvailableCallbacksValidated(workAgent); - assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback, - mProfileDefaultNetworkCallback); - - mCm.setProfileNetworkPreference(testHandle2, PROFILE_NETWORK_PREFERENCE_DEFAULT, - r -> r.run(), listener); - listener.expectOnComplete(); - inOrder.verify(mMockNetd).networkRemoveUidRanges(workAgent.getNetwork().netId, - uidRangeFor(testHandle2)); - - mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent); - assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback, - app4Cb); - - workAgent.disconnect(); - mCellNetworkAgent.disconnect(); - - mCm.unregisterNetworkCallback(app4Cb); - // Other callbacks will be unregistered by tearDown() - } - - @Test - public void testProfilePreferenceRemovedUponUserRemoved() throws Exception { - final InOrder inOrder = inOrder(mMockNetd); - final UserHandle testHandle = setupEnterpriseNetwork(); - - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - - final TestOnCompleteListener listener = new TestOnCompleteListener(); - mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE, - r -> r.run(), listener); - listener.expectOnComplete(); - inOrder.verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical( - mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE)); - inOrder.verify(mMockNetd).networkAddUidRanges(mCellNetworkAgent.getNetwork().netId, - uidRangeFor(testHandle)); - - final Intent removedIntent = new Intent(ACTION_USER_REMOVED); - removedIntent.putExtra(Intent.EXTRA_USER, testHandle); - processBroadcast(removedIntent); - - inOrder.verify(mMockNetd).networkRemoveUidRanges(mCellNetworkAgent.getNetwork().netId, - uidRangeFor(testHandle)); - } - - /** - * Make sure that OEM preference and per-profile preference can't be used at the same - * time and throw ISE if tried - */ - @Test - public void testOemPreferenceAndProfilePreferenceExclusive() throws Exception { - final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID); - mServiceContext.setWorkProfile(testHandle, true); - final TestOnCompleteListener listener = new TestOnCompleteListener(); - - setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest( - OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY); - assertThrows("Should not be able to set per-profile pref while OEM prefs present", - IllegalStateException.class, () -> - mCm.setProfileNetworkPreference(testHandle, - PROFILE_NETWORK_PREFERENCE_ENTERPRISE, - r -> r.run(), listener)); - - // Empty the OEM prefs - final TestOemListenerCallback oemPrefListener = new TestOemListenerCallback(); - final OemNetworkPreferences emptyOemPref = new OemNetworkPreferences.Builder().build(); - mService.setOemNetworkPreference(emptyOemPref, oemPrefListener); - oemPrefListener.expectOnComplete(); - - mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE, - r -> r.run(), listener); - listener.expectOnComplete(); - assertThrows("Should not be able to set OEM prefs while per-profile pref is on", - IllegalStateException.class , () -> - mService.setOemNetworkPreference(emptyOemPref, oemPrefListener)); - } - - /** - * Make sure wrong preferences for per-profile default networking are rejected. - */ - @Test - public void testProfileNetworkPrefWrongPreference() throws Exception { - final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID); - mServiceContext.setWorkProfile(testHandle, true); - assertThrows("Should not be able to set an illegal preference", - IllegalArgumentException.class, - () -> mCm.setProfileNetworkPreference(testHandle, - PROFILE_NETWORK_PREFERENCE_ENTERPRISE + 1, null, null)); - } - - /** - * Make sure requests for per-profile default networking for a non-work profile are - * rejected - */ - @Test - public void testProfileNetworkPrefWrongProfile() throws Exception { - final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID); - mServiceContext.setWorkProfile(testHandle, false); - assertThrows("Should not be able to set a user pref for a non-work profile", - IllegalArgumentException.class , () -> - mCm.setProfileNetworkPreference(testHandle, - PROFILE_NETWORK_PREFERENCE_ENTERPRISE, null, null)); - } - - @Test - public void testSubIdsClearedWithoutNetworkFactoryPermission() throws Exception { - mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_DENIED); - final NetworkCapabilities nc = new NetworkCapabilities(); - nc.setSubscriptionIds(Collections.singleton(Process.myUid())); - - final NetworkCapabilities result = - mService.networkCapabilitiesRestrictedForCallerPermissions( - nc, Process.myPid(), Process.myUid()); - assertTrue(result.getSubscriptionIds().isEmpty()); - } - - @Test - public void testSubIdsExistWithNetworkFactoryPermission() throws Exception { - mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED); - - final Set subIds = Collections.singleton(Process.myUid()); - final NetworkCapabilities nc = new NetworkCapabilities(); - nc.setSubscriptionIds(subIds); - - final NetworkCapabilities result = - mService.networkCapabilitiesRestrictedForCallerPermissions( - nc, Process.myPid(), Process.myUid()); - assertEquals(subIds, result.getSubscriptionIds()); - } - - private NetworkRequest getRequestWithSubIds() { - return new NetworkRequest.Builder() - .setSubscriptionIds(Collections.singleton(Process.myUid())) - .build(); - } - - @Test - public void testNetworkRequestWithSubIdsWithNetworkFactoryPermission() throws Exception { - mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED); - final PendingIntent pendingIntent = PendingIntent.getBroadcast( - mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE); - final NetworkCallback networkCallback1 = new NetworkCallback(); - final NetworkCallback networkCallback2 = new NetworkCallback(); - - mCm.requestNetwork(getRequestWithSubIds(), networkCallback1); - mCm.requestNetwork(getRequestWithSubIds(), pendingIntent); - mCm.registerNetworkCallback(getRequestWithSubIds(), networkCallback2); - - mCm.unregisterNetworkCallback(networkCallback1); - mCm.releaseNetworkRequest(pendingIntent); - mCm.unregisterNetworkCallback(networkCallback2); - } - - @Test - public void testNetworkRequestWithSubIdsWithoutNetworkFactoryPermission() throws Exception { - mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_DENIED); - final PendingIntent pendingIntent = PendingIntent.getBroadcast( - mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE); - - final Class expected = SecurityException.class; - assertThrows( - expected, () -> mCm.requestNetwork(getRequestWithSubIds(), new NetworkCallback())); - assertThrows(expected, () -> mCm.requestNetwork(getRequestWithSubIds(), pendingIntent)); - assertThrows( - expected, - () -> mCm.registerNetworkCallback(getRequestWithSubIds(), new NetworkCallback())); - } - - /** - * Validate request counts are counted accurately on setProfileNetworkPreference on set/replace. - */ - @Test - public void testProfileNetworkPrefCountsRequestsCorrectlyOnSet() throws Exception { - final UserHandle testHandle = setupEnterpriseNetwork(); - testRequestCountLimits(() -> { - // Set initially to test the limit prior to having existing requests. - final TestOnCompleteListener listener = new TestOnCompleteListener(); - mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE, - Runnable::run, listener); - listener.expectOnComplete(); - - // re-set so as to test the limit as part of replacing existing requests. - mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE, - Runnable::run, listener); - listener.expectOnComplete(); - }); - } - - /** - * Validate request counts are counted accurately on setOemNetworkPreference on set/replace. - */ - @Test - public void testSetOemNetworkPreferenceCountsRequestsCorrectlyOnSet() throws Exception { - mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true); - @OemNetworkPreferences.OemNetworkPreference final int networkPref = - OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY; - testRequestCountLimits(() -> { - // Set initially to test the limit prior to having existing requests. - final TestOemListenerCallback listener = new TestOemListenerCallback(); - mService.setOemNetworkPreference( - createDefaultOemNetworkPreferences(networkPref), listener); - listener.expectOnComplete(); - - // re-set so as to test the limit as part of replacing existing requests. - mService.setOemNetworkPreference( - createDefaultOemNetworkPreferences(networkPref), listener); - listener.expectOnComplete(); - }); - } - - private void testRequestCountLimits(@NonNull final Runnable r) throws Exception { - final ArraySet callbacks = new ArraySet<>(); - try { - final int requestCount = mService.mSystemNetworkRequestCounter - .mUidToNetworkRequestCount.get(Process.myUid()); - // The limit is hit when total requests <= limit. - final int maxCount = - ConnectivityService.MAX_NETWORK_REQUESTS_PER_SYSTEM_UID - requestCount; - // Need permission so registerDefaultNetworkCallback uses mSystemNetworkRequestCounter - withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, () -> { - for (int i = 1; i < maxCount - 1; i++) { - final TestNetworkCallback cb = new TestNetworkCallback(); - mCm.registerDefaultNetworkCallback(cb); - callbacks.add(cb); - } - - // Code to run to check if it triggers a max request count limit error. - r.run(); - }); - } finally { - for (final TestNetworkCallback cb : callbacks) { - mCm.unregisterNetworkCallback(cb); - } - } - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/IpSecServiceParameterizedTest.java b/packages/Connectivity/tests/unit/java/com/android/server/IpSecServiceParameterizedTest.java deleted file mode 100644 index cf2c9c783ac7f..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/IpSecServiceParameterizedTest.java +++ /dev/null @@ -1,1004 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server; - -import static android.content.pm.PackageManager.PERMISSION_DENIED; -import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static android.net.INetd.IF_STATE_DOWN; -import static android.net.INetd.IF_STATE_UP; -import static android.net.IpSecManager.DIRECTION_FWD; -import static android.net.IpSecManager.DIRECTION_IN; -import static android.net.IpSecManager.DIRECTION_OUT; -import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; -import static android.system.OsConstants.AF_INET; -import static android.system.OsConstants.AF_INET6; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.app.AppOpsManager; -import android.content.Context; -import android.content.pm.PackageManager; -import android.net.ConnectivityManager; -import android.net.INetd; -import android.net.InetAddresses; -import android.net.InterfaceConfigurationParcel; -import android.net.IpSecAlgorithm; -import android.net.IpSecConfig; -import android.net.IpSecManager; -import android.net.IpSecSpiResponse; -import android.net.IpSecTransform; -import android.net.IpSecTransformResponse; -import android.net.IpSecTunnelInterfaceResponse; -import android.net.IpSecUdpEncapResponse; -import android.net.LinkAddress; -import android.net.LinkProperties; -import android.net.Network; -import android.os.Binder; -import android.os.ParcelFileDescriptor; -import android.system.Os; -import android.test.mock.MockContext; -import android.util.ArraySet; - -import androidx.test.filters.SmallTest; - -import com.android.server.IpSecService.TunnelInterfaceRecord; - -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import java.net.Inet4Address; -import java.net.Socket; -import java.util.Arrays; -import java.util.Collection; -import java.util.Set; - -/** Unit tests for {@link IpSecService}. */ -@SmallTest -@RunWith(Parameterized.class) -public class IpSecServiceParameterizedTest { - - private static final int TEST_SPI = 0xD1201D; - - private final String mSourceAddr; - private final String mDestinationAddr; - private final LinkAddress mLocalInnerAddress; - private final int mFamily; - - private static final int[] ADDRESS_FAMILIES = - new int[] {AF_INET, AF_INET6}; - - @Parameterized.Parameters - public static Collection ipSecConfigs() { - return Arrays.asList( - new Object[][] { - {"1.2.3.4", "8.8.4.4", "10.0.1.1/24", AF_INET}, - {"2601::2", "2601::10", "2001:db8::1/64", AF_INET6} - }); - } - - private static final byte[] AEAD_KEY = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, - 0x73, 0x61, 0x6C, 0x74 - }; - private static final byte[] CRYPT_KEY = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F - }; - private static final byte[] AUTH_KEY = { - 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, - 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F - }; - - AppOpsManager mMockAppOps = mock(AppOpsManager.class); - ConnectivityManager mMockConnectivityMgr = mock(ConnectivityManager.class); - - TestContext mTestContext = new TestContext(); - - private class TestContext extends MockContext { - private Set mAllowedPermissions = new ArraySet<>(Arrays.asList( - android.Manifest.permission.MANAGE_IPSEC_TUNNELS, - android.Manifest.permission.NETWORK_STACK, - PERMISSION_MAINLINE_NETWORK_STACK)); - - private void setAllowedPermissions(String... permissions) { - mAllowedPermissions = new ArraySet<>(permissions); - } - - @Override - public Object getSystemService(String name) { - switch(name) { - case Context.APP_OPS_SERVICE: - return mMockAppOps; - case Context.CONNECTIVITY_SERVICE: - return mMockConnectivityMgr; - default: - return null; - } - } - - @Override - public String getSystemServiceName(Class serviceClass) { - if (ConnectivityManager.class == serviceClass) { - return Context.CONNECTIVITY_SERVICE; - } - return null; - } - - @Override - public PackageManager getPackageManager() { - return mMockPkgMgr; - } - - @Override - public void enforceCallingOrSelfPermission(String permission, String message) { - if (mAllowedPermissions.contains(permission)) { - return; - } else { - throw new SecurityException("Unavailable permission requested"); - } - } - - @Override - public int checkCallingOrSelfPermission(String permission) { - if (mAllowedPermissions.contains(permission)) { - return PERMISSION_GRANTED; - } else { - return PERMISSION_DENIED; - } - } - } - - INetd mMockNetd; - PackageManager mMockPkgMgr; - IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig; - IpSecService mIpSecService; - Network fakeNetwork = new Network(0xAB); - int mUid = Os.getuid(); - - private static final IpSecAlgorithm AUTH_ALGO = - new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 4); - private static final IpSecAlgorithm CRYPT_ALGO = - new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - private static final IpSecAlgorithm AEAD_ALGO = - new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128); - private static final int REMOTE_ENCAP_PORT = 4500; - - private static final String BLESSED_PACKAGE = "blessedPackage"; - private static final String SYSTEM_PACKAGE = "systemPackage"; - private static final String BAD_PACKAGE = "badPackage"; - - public IpSecServiceParameterizedTest( - String sourceAddr, String destAddr, String localInnerAddr, int family) { - mSourceAddr = sourceAddr; - mDestinationAddr = destAddr; - mLocalInnerAddress = new LinkAddress(localInnerAddr); - mFamily = family; - } - - @Before - public void setUp() throws Exception { - mMockNetd = mock(INetd.class); - mMockPkgMgr = mock(PackageManager.class); - mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class); - mIpSecService = new IpSecService(mTestContext, mMockIpSecSrvConfig); - - // Injecting mock netd - when(mMockIpSecSrvConfig.getNetdInstance()).thenReturn(mMockNetd); - - // PackageManager should always return true (feature flag tests in IpSecServiceTest) - when(mMockPkgMgr.hasSystemFeature(anyString())).thenReturn(true); - - // A package granted the AppOp for MANAGE_IPSEC_TUNNELS will be MODE_ALLOWED. - when(mMockAppOps.noteOp(anyInt(), anyInt(), eq(BLESSED_PACKAGE))) - .thenReturn(AppOpsManager.MODE_ALLOWED); - // A system package will not be granted the app op, so this should fall back to - // a permissions check, which should pass. - when(mMockAppOps.noteOp(anyInt(), anyInt(), eq(SYSTEM_PACKAGE))) - .thenReturn(AppOpsManager.MODE_DEFAULT); - // A mismatch between the package name and the UID will return MODE_IGNORED. - when(mMockAppOps.noteOp(anyInt(), anyInt(), eq(BAD_PACKAGE))) - .thenReturn(AppOpsManager.MODE_IGNORED); - } - - //TODO: Add a test to verify SPI. - - @Test - public void testIpSecServiceReserveSpi() throws Exception { - when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI))) - .thenReturn(TEST_SPI); - - IpSecSpiResponse spiResp = - mIpSecService.allocateSecurityParameterIndex( - mDestinationAddr, TEST_SPI, new Binder()); - assertEquals(IpSecManager.Status.OK, spiResp.status); - assertEquals(TEST_SPI, spiResp.spi); - } - - @Test - public void testReleaseSecurityParameterIndex() throws Exception { - when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI))) - .thenReturn(TEST_SPI); - - IpSecSpiResponse spiResp = - mIpSecService.allocateSecurityParameterIndex( - mDestinationAddr, TEST_SPI, new Binder()); - - mIpSecService.releaseSecurityParameterIndex(spiResp.resourceId); - - verify(mMockNetd) - .ipSecDeleteSecurityAssociation( - eq(mUid), - anyString(), - anyString(), - eq(TEST_SPI), - anyInt(), - anyInt(), - anyInt()); - - // Verify quota and RefcountedResource objects cleaned up - IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); - assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent); - try { - userRecord.mSpiRecords.getRefcountedResourceOrThrow(spiResp.resourceId); - fail("Expected IllegalArgumentException on attempt to access deleted resource"); - } catch (IllegalArgumentException expected) { - - } - } - - @Test - public void testSecurityParameterIndexBinderDeath() throws Exception { - when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI))) - .thenReturn(TEST_SPI); - - IpSecSpiResponse spiResp = - mIpSecService.allocateSecurityParameterIndex( - mDestinationAddr, TEST_SPI, new Binder()); - - IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); - IpSecService.RefcountedResource refcountedRecord = - userRecord.mSpiRecords.getRefcountedResourceOrThrow(spiResp.resourceId); - - refcountedRecord.binderDied(); - - verify(mMockNetd) - .ipSecDeleteSecurityAssociation( - eq(mUid), - anyString(), - anyString(), - eq(TEST_SPI), - anyInt(), - anyInt(), - anyInt()); - - // Verify quota and RefcountedResource objects cleaned up - assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent); - try { - userRecord.mSpiRecords.getRefcountedResourceOrThrow(spiResp.resourceId); - fail("Expected IllegalArgumentException on attempt to access deleted resource"); - } catch (IllegalArgumentException expected) { - - } - } - - private int getNewSpiResourceId(String remoteAddress, int returnSpi) throws Exception { - when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), anyString(), anyInt())) - .thenReturn(returnSpi); - - IpSecSpiResponse spi = - mIpSecService.allocateSecurityParameterIndex( - InetAddresses.parseNumericAddress(remoteAddress).getHostAddress(), - IpSecManager.INVALID_SECURITY_PARAMETER_INDEX, - new Binder()); - return spi.resourceId; - } - - private void addDefaultSpisAndRemoteAddrToIpSecConfig(IpSecConfig config) throws Exception { - config.setSpiResourceId(getNewSpiResourceId(mDestinationAddr, TEST_SPI)); - config.setSourceAddress(mSourceAddr); - config.setDestinationAddress(mDestinationAddr); - } - - private void addAuthAndCryptToIpSecConfig(IpSecConfig config) throws Exception { - config.setEncryption(CRYPT_ALGO); - config.setAuthentication(AUTH_ALGO); - } - - private void addEncapSocketToIpSecConfig(int resourceId, IpSecConfig config) throws Exception { - config.setEncapType(IpSecTransform.ENCAP_ESPINUDP); - config.setEncapSocketResourceId(resourceId); - config.setEncapRemotePort(REMOTE_ENCAP_PORT); - } - - private void verifyTransformNetdCalledForCreatingSA( - IpSecConfig config, IpSecTransformResponse resp) throws Exception { - verifyTransformNetdCalledForCreatingSA(config, resp, 0); - } - - private void verifyTransformNetdCalledForCreatingSA( - IpSecConfig config, IpSecTransformResponse resp, int encapSocketPort) throws Exception { - IpSecAlgorithm auth = config.getAuthentication(); - IpSecAlgorithm crypt = config.getEncryption(); - IpSecAlgorithm authCrypt = config.getAuthenticatedEncryption(); - - verify(mMockNetd, times(1)) - .ipSecAddSecurityAssociation( - eq(mUid), - eq(config.getMode()), - eq(config.getSourceAddress()), - eq(config.getDestinationAddress()), - eq((config.getNetwork() != null) ? config.getNetwork().netId : 0), - eq(TEST_SPI), - eq(0), - eq(0), - eq((auth != null) ? auth.getName() : ""), - eq((auth != null) ? auth.getKey() : new byte[] {}), - eq((auth != null) ? auth.getTruncationLengthBits() : 0), - eq((crypt != null) ? crypt.getName() : ""), - eq((crypt != null) ? crypt.getKey() : new byte[] {}), - eq((crypt != null) ? crypt.getTruncationLengthBits() : 0), - eq((authCrypt != null) ? authCrypt.getName() : ""), - eq((authCrypt != null) ? authCrypt.getKey() : new byte[] {}), - eq((authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0), - eq(config.getEncapType()), - eq(encapSocketPort), - eq(config.getEncapRemotePort()), - eq(config.getXfrmInterfaceId())); - } - - @Test - public void testCreateTransform() throws Exception { - IpSecConfig ipSecConfig = new IpSecConfig(); - addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); - addAuthAndCryptToIpSecConfig(ipSecConfig); - - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - assertEquals(IpSecManager.Status.OK, createTransformResp.status); - - verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp); - } - - @Test - public void testCreateTransformAead() throws Exception { - IpSecConfig ipSecConfig = new IpSecConfig(); - addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); - - ipSecConfig.setAuthenticatedEncryption(AEAD_ALGO); - - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - assertEquals(IpSecManager.Status.OK, createTransformResp.status); - - verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp); - } - - @Test - public void testCreateTransportModeTransformWithEncap() throws Exception { - IpSecUdpEncapResponse udpSock = mIpSecService.openUdpEncapsulationSocket(0, new Binder()); - - IpSecConfig ipSecConfig = new IpSecConfig(); - ipSecConfig.setMode(IpSecTransform.MODE_TRANSPORT); - addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); - addAuthAndCryptToIpSecConfig(ipSecConfig); - addEncapSocketToIpSecConfig(udpSock.resourceId, ipSecConfig); - - if (mFamily == AF_INET) { - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - assertEquals(IpSecManager.Status.OK, createTransformResp.status); - - verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp, udpSock.port); - } else { - try { - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - fail("Expected IllegalArgumentException on attempt to use UDP Encap in IPv6"); - } catch (IllegalArgumentException expected) { - } - } - } - - @Test - public void testCreateTunnelModeTransformWithEncap() throws Exception { - IpSecUdpEncapResponse udpSock = mIpSecService.openUdpEncapsulationSocket(0, new Binder()); - - IpSecConfig ipSecConfig = new IpSecConfig(); - ipSecConfig.setMode(IpSecTransform.MODE_TUNNEL); - addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); - addAuthAndCryptToIpSecConfig(ipSecConfig); - addEncapSocketToIpSecConfig(udpSock.resourceId, ipSecConfig); - - if (mFamily == AF_INET) { - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - assertEquals(IpSecManager.Status.OK, createTransformResp.status); - - verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp, udpSock.port); - } else { - try { - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - fail("Expected IllegalArgumentException on attempt to use UDP Encap in IPv6"); - } catch (IllegalArgumentException expected) { - } - } - } - - @Test - public void testCreateTwoTransformsWithSameSpis() throws Exception { - IpSecConfig ipSecConfig = new IpSecConfig(); - addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); - addAuthAndCryptToIpSecConfig(ipSecConfig); - - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - assertEquals(IpSecManager.Status.OK, createTransformResp.status); - - // Attempting to create transform a second time with the same SPIs should throw an error... - try { - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - fail("IpSecService should have thrown an error for reuse of SPI"); - } catch (IllegalStateException expected) { - } - - // ... even if the transform is deleted - mIpSecService.deleteTransform(createTransformResp.resourceId); - try { - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - fail("IpSecService should have thrown an error for reuse of SPI"); - } catch (IllegalStateException expected) { - } - } - - @Test - public void testReleaseOwnedSpi() throws Exception { - IpSecConfig ipSecConfig = new IpSecConfig(); - addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); - addAuthAndCryptToIpSecConfig(ipSecConfig); - - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); - assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent); - mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId()); - verify(mMockNetd, times(0)) - .ipSecDeleteSecurityAssociation( - eq(mUid), - anyString(), - anyString(), - eq(TEST_SPI), - anyInt(), - anyInt(), - anyInt()); - // quota is not released until the SPI is released by the Transform - assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent); - } - - @Test - public void testDeleteTransform() throws Exception { - IpSecConfig ipSecConfig = new IpSecConfig(); - addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); - addAuthAndCryptToIpSecConfig(ipSecConfig); - - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - mIpSecService.deleteTransform(createTransformResp.resourceId); - - verify(mMockNetd, times(1)) - .ipSecDeleteSecurityAssociation( - eq(mUid), - anyString(), - anyString(), - eq(TEST_SPI), - anyInt(), - anyInt(), - anyInt()); - - // Verify quota and RefcountedResource objects cleaned up - IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); - assertEquals(0, userRecord.mTransformQuotaTracker.mCurrent); - assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent); - - mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId()); - // Verify that ipSecDeleteSa was not called when the SPI was released because the - // ownedByTransform property should prevent it; (note, the called count is cumulative). - verify(mMockNetd, times(1)) - .ipSecDeleteSecurityAssociation( - anyInt(), - anyString(), - anyString(), - anyInt(), - anyInt(), - anyInt(), - anyInt()); - assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent); - - try { - userRecord.mTransformRecords.getRefcountedResourceOrThrow( - createTransformResp.resourceId); - fail("Expected IllegalArgumentException on attempt to access deleted resource"); - } catch (IllegalArgumentException expected) { - - } - } - - @Test - public void testTransportModeTransformBinderDeath() throws Exception { - IpSecConfig ipSecConfig = new IpSecConfig(); - addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); - addAuthAndCryptToIpSecConfig(ipSecConfig); - - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - - IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); - IpSecService.RefcountedResource refcountedRecord = - userRecord.mTransformRecords.getRefcountedResourceOrThrow( - createTransformResp.resourceId); - - refcountedRecord.binderDied(); - - verify(mMockNetd) - .ipSecDeleteSecurityAssociation( - eq(mUid), - anyString(), - anyString(), - eq(TEST_SPI), - anyInt(), - anyInt(), - anyInt()); - - // Verify quota and RefcountedResource objects cleaned up - assertEquals(0, userRecord.mTransformQuotaTracker.mCurrent); - try { - userRecord.mTransformRecords.getRefcountedResourceOrThrow( - createTransformResp.resourceId); - fail("Expected IllegalArgumentException on attempt to access deleted resource"); - } catch (IllegalArgumentException expected) { - - } - } - - @Test - public void testApplyTransportModeTransform() throws Exception { - verifyApplyTransportModeTransformCommon(false); - } - - @Test - public void testApplyTransportModeTransformReleasedSpi() throws Exception { - verifyApplyTransportModeTransformCommon(true); - } - - public void verifyApplyTransportModeTransformCommon( - boolean closeSpiBeforeApply) throws Exception { - IpSecConfig ipSecConfig = new IpSecConfig(); - addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); - addAuthAndCryptToIpSecConfig(ipSecConfig); - - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - - if (closeSpiBeforeApply) { - mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId()); - } - - Socket socket = new Socket(); - socket.bind(null); - ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket); - - int resourceId = createTransformResp.resourceId; - mIpSecService.applyTransportModeTransform(pfd, IpSecManager.DIRECTION_OUT, resourceId); - - verify(mMockNetd) - .ipSecApplyTransportModeTransform( - eq(pfd), - eq(mUid), - eq(IpSecManager.DIRECTION_OUT), - anyString(), - anyString(), - eq(TEST_SPI)); - } - - @Test - public void testApplyTransportModeTransformWithClosedSpi() throws Exception { - IpSecConfig ipSecConfig = new IpSecConfig(); - addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); - addAuthAndCryptToIpSecConfig(ipSecConfig); - - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - - // Close SPI record - mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId()); - - Socket socket = new Socket(); - socket.bind(null); - ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket); - - int resourceId = createTransformResp.resourceId; - mIpSecService.applyTransportModeTransform(pfd, IpSecManager.DIRECTION_OUT, resourceId); - - verify(mMockNetd) - .ipSecApplyTransportModeTransform( - eq(pfd), - eq(mUid), - eq(IpSecManager.DIRECTION_OUT), - anyString(), - anyString(), - eq(TEST_SPI)); - } - - @Test - public void testRemoveTransportModeTransform() throws Exception { - Socket socket = new Socket(); - socket.bind(null); - ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket); - mIpSecService.removeTransportModeTransforms(pfd); - - verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd); - } - - private IpSecTunnelInterfaceResponse createAndValidateTunnel( - String localAddr, String remoteAddr, String pkgName) throws Exception { - final InterfaceConfigurationParcel config = new InterfaceConfigurationParcel(); - config.flags = new String[] {IF_STATE_DOWN}; - when(mMockNetd.interfaceGetCfg(anyString())).thenReturn(config); - IpSecTunnelInterfaceResponse createTunnelResp = - mIpSecService.createTunnelInterface( - mSourceAddr, mDestinationAddr, fakeNetwork, new Binder(), pkgName); - - assertNotNull(createTunnelResp); - assertEquals(IpSecManager.Status.OK, createTunnelResp.status); - for (int direction : new int[] {DIRECTION_IN, DIRECTION_OUT, DIRECTION_FWD}) { - for (int selAddrFamily : ADDRESS_FAMILIES) { - verify(mMockNetd).ipSecAddSecurityPolicy( - eq(mUid), - eq(selAddrFamily), - eq(direction), - anyString(), - anyString(), - eq(0), - anyInt(), // iKey/oKey - anyInt(), // mask - eq(createTunnelResp.resourceId)); - } - } - - return createTunnelResp; - } - - @Test - public void testCreateTunnelInterface() throws Exception { - IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); - - // Check that we have stored the tracking object, and retrieve it - IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); - IpSecService.RefcountedResource refcountedRecord = - userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow( - createTunnelResp.resourceId); - - assertEquals(1, userRecord.mTunnelQuotaTracker.mCurrent); - verify(mMockNetd) - .ipSecAddTunnelInterface( - eq(createTunnelResp.interfaceName), - eq(mSourceAddr), - eq(mDestinationAddr), - anyInt(), - anyInt(), - anyInt()); - verify(mMockNetd).interfaceSetCfg(argThat( - config -> Arrays.asList(config.flags).contains(IF_STATE_UP))); - } - - @Test - public void testDeleteTunnelInterface() throws Exception { - IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); - - IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); - - mIpSecService.deleteTunnelInterface(createTunnelResp.resourceId, BLESSED_PACKAGE); - - // Verify quota and RefcountedResource objects cleaned up - assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent); - verify(mMockNetd).ipSecRemoveTunnelInterface(eq(createTunnelResp.interfaceName)); - try { - userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow( - createTunnelResp.resourceId); - fail("Expected IllegalArgumentException on attempt to access deleted resource"); - } catch (IllegalArgumentException expected) { - } - } - - private Network createFakeUnderlyingNetwork(String interfaceName) { - final Network fakeNetwork = new Network(1000); - final LinkProperties fakeLp = new LinkProperties(); - fakeLp.setInterfaceName(interfaceName); - when(mMockConnectivityMgr.getLinkProperties(eq(fakeNetwork))).thenReturn(fakeLp); - return fakeNetwork; - } - - @Test - public void testSetNetworkForTunnelInterface() throws Exception { - final IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); - final Network newFakeNetwork = createFakeUnderlyingNetwork("newFakeNetworkInterface"); - final int tunnelIfaceResourceId = createTunnelResp.resourceId; - mIpSecService.setNetworkForTunnelInterface( - tunnelIfaceResourceId, newFakeNetwork, BLESSED_PACKAGE); - - final IpSecService.UserRecord userRecord = - mIpSecService.mUserResourceTracker.getUserRecord(mUid); - assertEquals(1, userRecord.mTunnelQuotaTracker.mCurrent); - - final TunnelInterfaceRecord tunnelInterfaceInfo = - userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelIfaceResourceId); - assertEquals(newFakeNetwork, tunnelInterfaceInfo.getUnderlyingNetwork()); - } - - @Test - public void testSetNetworkForTunnelInterfaceFailsForInvalidResourceId() throws Exception { - final IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); - final Network newFakeNetwork = new Network(1000); - - try { - mIpSecService.setNetworkForTunnelInterface( - IpSecManager.INVALID_RESOURCE_ID, newFakeNetwork, BLESSED_PACKAGE); - fail("Expected an IllegalArgumentException for invalid resource ID."); - } catch (IllegalArgumentException expected) { - } - } - - @Test - public void testSetNetworkForTunnelInterfaceFailsWhenSettingTunnelNetwork() throws Exception { - final IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); - final int tunnelIfaceResourceId = createTunnelResp.resourceId; - final IpSecService.UserRecord userRecord = - mIpSecService.mUserResourceTracker.getUserRecord(mUid); - final TunnelInterfaceRecord tunnelInterfaceInfo = - userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelIfaceResourceId); - - final Network newFakeNetwork = - createFakeUnderlyingNetwork(tunnelInterfaceInfo.getInterfaceName()); - - try { - mIpSecService.setNetworkForTunnelInterface( - tunnelIfaceResourceId, newFakeNetwork, BLESSED_PACKAGE); - fail( - "Expected an IllegalArgumentException because the underlying network is the" - + " network being exposed by this tunnel."); - } catch (IllegalArgumentException expected) { - } - } - - @Test - public void testTunnelInterfaceBinderDeath() throws Exception { - IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); - - IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); - IpSecService.RefcountedResource refcountedRecord = - userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow( - createTunnelResp.resourceId); - - refcountedRecord.binderDied(); - - // Verify quota and RefcountedResource objects cleaned up - assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent); - verify(mMockNetd).ipSecRemoveTunnelInterface(eq(createTunnelResp.interfaceName)); - try { - userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow( - createTunnelResp.resourceId); - fail("Expected IllegalArgumentException on attempt to access deleted resource"); - } catch (IllegalArgumentException expected) { - } - } - - @Test - public void testApplyTunnelModeTransformOutbound() throws Exception { - verifyApplyTunnelModeTransformCommon(false /* closeSpiBeforeApply */, DIRECTION_OUT); - } - - @Test - public void testApplyTunnelModeTransformOutboundNonNetworkStack() throws Exception { - mTestContext.setAllowedPermissions(android.Manifest.permission.MANAGE_IPSEC_TUNNELS); - verifyApplyTunnelModeTransformCommon(false /* closeSpiBeforeApply */, DIRECTION_OUT); - } - - @Test - public void testApplyTunnelModeTransformOutboundReleasedSpi() throws Exception { - verifyApplyTunnelModeTransformCommon(true /* closeSpiBeforeApply */, DIRECTION_OUT); - } - - @Test - public void testApplyTunnelModeTransformInbound() throws Exception { - verifyApplyTunnelModeTransformCommon(true /* closeSpiBeforeApply */, DIRECTION_IN); - } - - @Test - public void testApplyTunnelModeTransformInboundNonNetworkStack() throws Exception { - mTestContext.setAllowedPermissions(android.Manifest.permission.MANAGE_IPSEC_TUNNELS); - verifyApplyTunnelModeTransformCommon(true /* closeSpiBeforeApply */, DIRECTION_IN); - } - - @Test - public void testApplyTunnelModeTransformForward() throws Exception { - verifyApplyTunnelModeTransformCommon(true /* closeSpiBeforeApply */, DIRECTION_FWD); - } - - @Test - public void testApplyTunnelModeTransformForwardNonNetworkStack() throws Exception { - mTestContext.setAllowedPermissions(android.Manifest.permission.MANAGE_IPSEC_TUNNELS); - - try { - verifyApplyTunnelModeTransformCommon(true /* closeSpiBeforeApply */, DIRECTION_FWD); - fail("Expected security exception due to use of forward policies without NETWORK_STACK" - + " or MAINLINE_NETWORK_STACK permission"); - } catch (SecurityException expected) { - } - } - - public void verifyApplyTunnelModeTransformCommon(boolean closeSpiBeforeApply, int direction) - throws Exception { - IpSecConfig ipSecConfig = new IpSecConfig(); - ipSecConfig.setMode(IpSecTransform.MODE_TUNNEL); - addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); - addAuthAndCryptToIpSecConfig(ipSecConfig); - - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); - - if (closeSpiBeforeApply) { - mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId()); - } - - int transformResourceId = createTransformResp.resourceId; - int tunnelResourceId = createTunnelResp.resourceId; - mIpSecService.applyTunnelModeTransform( - tunnelResourceId, direction, transformResourceId, BLESSED_PACKAGE); - - for (int selAddrFamily : ADDRESS_FAMILIES) { - verify(mMockNetd) - .ipSecUpdateSecurityPolicy( - eq(mUid), - eq(selAddrFamily), - eq(direction), - anyString(), - anyString(), - eq(direction == DIRECTION_OUT ? TEST_SPI : 0), - anyInt(), // iKey/oKey - anyInt(), // mask - eq(tunnelResourceId)); - } - - ipSecConfig.setXfrmInterfaceId(tunnelResourceId); - verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp); - } - - - @Test - public void testApplyTunnelModeTransformWithClosedSpi() throws Exception { - IpSecConfig ipSecConfig = new IpSecConfig(); - ipSecConfig.setMode(IpSecTransform.MODE_TUNNEL); - addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); - addAuthAndCryptToIpSecConfig(ipSecConfig); - - IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE); - IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE); - - // Close SPI record - mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId()); - - int transformResourceId = createTransformResp.resourceId; - int tunnelResourceId = createTunnelResp.resourceId; - mIpSecService.applyTunnelModeTransform( - tunnelResourceId, IpSecManager.DIRECTION_OUT, transformResourceId, BLESSED_PACKAGE); - - for (int selAddrFamily : ADDRESS_FAMILIES) { - verify(mMockNetd) - .ipSecUpdateSecurityPolicy( - eq(mUid), - eq(selAddrFamily), - eq(IpSecManager.DIRECTION_OUT), - anyString(), - anyString(), - eq(TEST_SPI), - anyInt(), // iKey/oKey - anyInt(), // mask - eq(tunnelResourceId)); - } - - ipSecConfig.setXfrmInterfaceId(tunnelResourceId); - verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp); - } - - @Test - public void testAddRemoveAddressFromTunnelInterface() throws Exception { - for (String pkgName : new String[] {BLESSED_PACKAGE, SYSTEM_PACKAGE}) { - IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr, pkgName); - mIpSecService.addAddressToTunnelInterface( - createTunnelResp.resourceId, mLocalInnerAddress, pkgName); - verify(mMockNetd, times(1)) - .interfaceAddAddress( - eq(createTunnelResp.interfaceName), - eq(mLocalInnerAddress.getAddress().getHostAddress()), - eq(mLocalInnerAddress.getPrefixLength())); - mIpSecService.removeAddressFromTunnelInterface( - createTunnelResp.resourceId, mLocalInnerAddress, pkgName); - verify(mMockNetd, times(1)) - .interfaceDelAddress( - eq(createTunnelResp.interfaceName), - eq(mLocalInnerAddress.getAddress().getHostAddress()), - eq(mLocalInnerAddress.getPrefixLength())); - mIpSecService.deleteTunnelInterface(createTunnelResp.resourceId, pkgName); - } - } - - @Ignore - @Test - public void testAddTunnelFailsForBadPackageName() throws Exception { - try { - IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr, BAD_PACKAGE); - fail("Expected a SecurityException for badPackage."); - } catch (SecurityException expected) { - } - } - - @Test - public void testFeatureFlagVerification() throws Exception { - when(mMockPkgMgr.hasSystemFeature(eq(PackageManager.FEATURE_IPSEC_TUNNELS))) - .thenReturn(false); - - try { - String addr = Inet4Address.getLoopbackAddress().getHostAddress(); - mIpSecService.createTunnelInterface( - addr, addr, new Network(0), new Binder(), BLESSED_PACKAGE); - fail("Expected UnsupportedOperationException for disabled feature"); - } catch (UnsupportedOperationException expected) { - } - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/IpSecServiceRefcountedResourceTest.java b/packages/Connectivity/tests/unit/java/com/android/server/IpSecServiceRefcountedResourceTest.java deleted file mode 100644 index 22a2c94fc194e..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/IpSecServiceRefcountedResourceTest.java +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.fail; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyObject; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import android.content.Context; -import android.os.Binder; -import android.os.IBinder; -import android.os.RemoteException; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.server.IpSecService.IResource; -import com.android.server.IpSecService.RefcountedResource; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.ThreadLocalRandom; - -/** Unit tests for {@link IpSecService.RefcountedResource}. */ -@SmallTest -@RunWith(AndroidJUnit4.class) -public class IpSecServiceRefcountedResourceTest { - Context mMockContext; - IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig; - IpSecService mIpSecService; - - @Before - public void setUp() throws Exception { - mMockContext = mock(Context.class); - mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class); - mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig); - } - - private void assertResourceState( - RefcountedResource resource, - int refCount, - int userReleaseCallCount, - int releaseReferenceCallCount, - int invalidateCallCount, - int freeUnderlyingResourcesCallCount) - throws RemoteException { - // Check refcount on RefcountedResource - assertEquals(refCount, resource.mRefCount); - - // Check call count of RefcountedResource - verify(resource, times(userReleaseCallCount)).userRelease(); - verify(resource, times(releaseReferenceCallCount)).releaseReference(); - - // Check call count of IResource - verify(resource.getResource(), times(invalidateCallCount)).invalidate(); - verify(resource.getResource(), times(freeUnderlyingResourcesCallCount)) - .freeUnderlyingResources(); - } - - /** Adds mockito instrumentation */ - private RefcountedResource getTestRefcountedResource( - RefcountedResource... children) { - return getTestRefcountedResource(new Binder(), children); - } - - /** Adds mockito instrumentation with provided binder */ - private RefcountedResource getTestRefcountedResource( - IBinder binder, RefcountedResource... children) { - return spy( - mIpSecService - .new RefcountedResource(mock(IResource.class), binder, children)); - } - - @Test - public void testConstructor() throws RemoteException { - IBinder binderMock = mock(IBinder.class); - RefcountedResource resource = getTestRefcountedResource(binderMock); - - // Verify resource's refcount starts at 1 (for user-reference) - assertResourceState(resource, 1, 0, 0, 0, 0); - - // Verify linking to binder death - verify(binderMock).linkToDeath(anyObject(), anyInt()); - } - - @Test - public void testConstructorWithChildren() throws RemoteException { - IBinder binderMockChild = mock(IBinder.class); - IBinder binderMockParent = mock(IBinder.class); - RefcountedResource childResource = getTestRefcountedResource(binderMockChild); - RefcountedResource parentResource = - getTestRefcountedResource(binderMockParent, childResource); - - // Verify parent's refcount starts at 1 (for user-reference) - assertResourceState(parentResource, 1, 0, 0, 0, 0); - - // Verify child's refcounts were incremented - assertResourceState(childResource, 2, 0, 0, 0, 0); - - // Verify linking to binder death - verify(binderMockChild).linkToDeath(anyObject(), anyInt()); - verify(binderMockParent).linkToDeath(anyObject(), anyInt()); - } - - @Test - public void testFailLinkToDeath() throws RemoteException { - IBinder binderMock = mock(IBinder.class); - doThrow(new RemoteException()).when(binderMock).linkToDeath(anyObject(), anyInt()); - - try { - getTestRefcountedResource(binderMock); - fail("Expected exception to propogate when binder fails to link to death"); - } catch (RuntimeException expected) { - } - } - - @Test - public void testCleanupAndRelease() throws RemoteException { - IBinder binderMock = mock(IBinder.class); - RefcountedResource refcountedResource = getTestRefcountedResource(binderMock); - - // Verify user-initiated cleanup path decrements refcount and calls full cleanup flow - refcountedResource.userRelease(); - assertResourceState(refcountedResource, -1, 1, 1, 1, 1); - - // Verify user-initated cleanup path unlinks from binder - verify(binderMock).unlinkToDeath(eq(refcountedResource), eq(0)); - assertNull(refcountedResource.mBinder); - } - - @Test - public void testMultipleCallsToCleanupAndRelease() throws RemoteException { - RefcountedResource refcountedResource = getTestRefcountedResource(); - - // Verify calling userRelease multiple times does not trigger any other cleanup - // methods - refcountedResource.userRelease(); - assertResourceState(refcountedResource, -1, 1, 1, 1, 1); - - refcountedResource.userRelease(); - refcountedResource.userRelease(); - assertResourceState(refcountedResource, -1, 3, 1, 1, 1); - } - - @Test - public void testBinderDeathAfterCleanupAndReleaseDoesNothing() throws RemoteException { - RefcountedResource refcountedResource = getTestRefcountedResource(); - - refcountedResource.userRelease(); - assertResourceState(refcountedResource, -1, 1, 1, 1, 1); - - // Verify binder death call does not trigger any other cleanup methods if called after - // userRelease() - refcountedResource.binderDied(); - assertResourceState(refcountedResource, -1, 2, 1, 1, 1); - } - - @Test - public void testBinderDeath() throws RemoteException { - RefcountedResource refcountedResource = getTestRefcountedResource(); - - // Verify binder death caused cleanup - refcountedResource.binderDied(); - verify(refcountedResource, times(1)).binderDied(); - assertResourceState(refcountedResource, -1, 1, 1, 1, 1); - assertNull(refcountedResource.mBinder); - } - - @Test - public void testCleanupParentDecrementsChildRefcount() throws RemoteException { - RefcountedResource childResource = getTestRefcountedResource(); - RefcountedResource parentResource = getTestRefcountedResource(childResource); - - parentResource.userRelease(); - - // Verify parent gets cleaned up properly, and triggers releaseReference on - // child - assertResourceState(childResource, 1, 0, 1, 0, 0); - assertResourceState(parentResource, -1, 1, 1, 1, 1); - } - - @Test - public void testCleanupReferencedChildDoesNotTriggerRelease() throws RemoteException { - RefcountedResource childResource = getTestRefcountedResource(); - RefcountedResource parentResource = getTestRefcountedResource(childResource); - - childResource.userRelease(); - - // Verify that child does not clean up kernel resources and quota. - assertResourceState(childResource, 1, 1, 1, 1, 0); - assertResourceState(parentResource, 1, 0, 0, 0, 0); - } - - @Test - public void testTwoParents() throws RemoteException { - RefcountedResource childResource = getTestRefcountedResource(); - RefcountedResource parentResource1 = getTestRefcountedResource(childResource); - RefcountedResource parentResource2 = getTestRefcountedResource(childResource); - - // Verify that child does not cleanup kernel resources and quota until all references - // have been released. Assumption: parents release correctly based on - // testCleanupParentDecrementsChildRefcount() - childResource.userRelease(); - assertResourceState(childResource, 2, 1, 1, 1, 0); - - parentResource1.userRelease(); - assertResourceState(childResource, 1, 1, 2, 1, 0); - - parentResource2.userRelease(); - assertResourceState(childResource, -1, 1, 3, 1, 1); - } - - @Test - public void testTwoChildren() throws RemoteException { - RefcountedResource childResource1 = getTestRefcountedResource(); - RefcountedResource childResource2 = getTestRefcountedResource(); - RefcountedResource parentResource = - getTestRefcountedResource(childResource1, childResource2); - - childResource1.userRelease(); - assertResourceState(childResource1, 1, 1, 1, 1, 0); - assertResourceState(childResource2, 2, 0, 0, 0, 0); - - parentResource.userRelease(); - assertResourceState(childResource1, -1, 1, 2, 1, 1); - assertResourceState(childResource2, 1, 0, 1, 0, 0); - - childResource2.userRelease(); - assertResourceState(childResource1, -1, 1, 2, 1, 1); - assertResourceState(childResource2, -1, 1, 2, 1, 1); - } - - @Test - public void testSampleUdpEncapTranform() throws RemoteException { - RefcountedResource spi1 = getTestRefcountedResource(); - RefcountedResource spi2 = getTestRefcountedResource(); - RefcountedResource udpEncapSocket = getTestRefcountedResource(); - RefcountedResource transform = - getTestRefcountedResource(spi1, spi2, udpEncapSocket); - - // Pretend one SPI goes out of reference (releaseManagedResource -> userRelease) - spi1.userRelease(); - - // User called releaseManagedResource on udpEncap socket - udpEncapSocket.userRelease(); - - // User dies, and binder kills the rest - spi2.binderDied(); - transform.binderDied(); - - // Check resource states - assertResourceState(spi1, -1, 1, 2, 1, 1); - assertResourceState(spi2, -1, 1, 2, 1, 1); - assertResourceState(udpEncapSocket, -1, 1, 2, 1, 1); - assertResourceState(transform, -1, 1, 1, 1, 1); - } - - @Test - public void testSampleDualTransformEncapSocket() throws RemoteException { - RefcountedResource spi1 = getTestRefcountedResource(); - RefcountedResource spi2 = getTestRefcountedResource(); - RefcountedResource spi3 = getTestRefcountedResource(); - RefcountedResource spi4 = getTestRefcountedResource(); - RefcountedResource udpEncapSocket = getTestRefcountedResource(); - RefcountedResource transform1 = - getTestRefcountedResource(spi1, spi2, udpEncapSocket); - RefcountedResource transform2 = - getTestRefcountedResource(spi3, spi4, udpEncapSocket); - - // Pretend one SPIs goes out of reference (releaseManagedResource -> userRelease) - spi1.userRelease(); - - // User called releaseManagedResource on udpEncap socket and spi4 - udpEncapSocket.userRelease(); - spi4.userRelease(); - - // User dies, and binder kills the rest - spi2.binderDied(); - spi3.binderDied(); - transform2.binderDied(); - transform1.binderDied(); - - // Check resource states - assertResourceState(spi1, -1, 1, 2, 1, 1); - assertResourceState(spi2, -1, 1, 2, 1, 1); - assertResourceState(spi3, -1, 1, 2, 1, 1); - assertResourceState(spi4, -1, 1, 2, 1, 1); - assertResourceState(udpEncapSocket, -1, 1, 3, 1, 1); - assertResourceState(transform1, -1, 1, 1, 1, 1); - assertResourceState(transform2, -1, 1, 1, 1, 1); - } - - @Test - public void fuzzTest() throws RemoteException { - List> resources = new ArrayList<>(); - - // Build a tree of resources - for (int i = 0; i < 100; i++) { - // Choose a random number of children from the existing list - int numChildren = ThreadLocalRandom.current().nextInt(0, resources.size() + 1); - - // Build a (random) list of children - Set> children = new HashSet<>(); - for (int j = 0; j < numChildren; j++) { - int childIndex = ThreadLocalRandom.current().nextInt(0, resources.size()); - children.add(resources.get(childIndex)); - } - - RefcountedResource newRefcountedResource = - getTestRefcountedResource( - children.toArray(new RefcountedResource[children.size()])); - resources.add(newRefcountedResource); - } - - // Cleanup all resources in a random order - List> clonedResources = - new ArrayList<>(resources); // shallow copy - while (!clonedResources.isEmpty()) { - int index = ThreadLocalRandom.current().nextInt(0, clonedResources.size()); - RefcountedResource refcountedResource = clonedResources.get(index); - refcountedResource.userRelease(); - clonedResources.remove(index); - } - - // Verify all resources were cleaned up properly - for (RefcountedResource refcountedResource : resources) { - assertEquals(-1, refcountedResource.mRefCount); - } - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/IpSecServiceTest.java b/packages/Connectivity/tests/unit/java/com/android/server/IpSecServiceTest.java deleted file mode 100644 index 6232423b4f9ec..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/IpSecServiceTest.java +++ /dev/null @@ -1,670 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server; - -import static android.system.OsConstants.AF_INET; -import static android.system.OsConstants.EADDRINUSE; -import static android.system.OsConstants.IPPROTO_UDP; -import static android.system.OsConstants.SOCK_DGRAM; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.argThat; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.INetd; -import android.net.IpSecAlgorithm; -import android.net.IpSecConfig; -import android.net.IpSecManager; -import android.net.IpSecSpiResponse; -import android.net.IpSecUdpEncapResponse; -import android.os.Binder; -import android.os.ParcelFileDescriptor; -import android.os.Process; -import android.system.ErrnoException; -import android.system.Os; -import android.system.StructStat; -import android.util.Range; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import dalvik.system.SocketTagger; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentMatcher; - -import java.io.FileDescriptor; -import java.net.InetAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.List; - -/** Unit tests for {@link IpSecService}. */ -@SmallTest -@RunWith(AndroidJUnit4.class) -public class IpSecServiceTest { - - private static final int DROID_SPI = 0xD1201D; - private static final int MAX_NUM_ENCAP_SOCKETS = 100; - private static final int MAX_NUM_SPIS = 100; - private static final int TEST_UDP_ENCAP_INVALID_PORT = 100; - private static final int TEST_UDP_ENCAP_PORT_OUT_RANGE = 100000; - - private static final InetAddress INADDR_ANY; - - private static final byte[] AEAD_KEY = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, - 0x73, 0x61, 0x6C, 0x74 - }; - private static final byte[] CRYPT_KEY = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F - }; - private static final byte[] AUTH_KEY = { - 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, - 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F - }; - - private static final IpSecAlgorithm AUTH_ALGO = - new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 4); - private static final IpSecAlgorithm CRYPT_ALGO = - new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - private static final IpSecAlgorithm AEAD_ALGO = - new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128); - - static { - try { - INADDR_ANY = InetAddress.getByAddress(new byte[] {0, 0, 0, 0}); - } catch (UnknownHostException e) { - throw new RuntimeException(e); - } - } - - Context mMockContext; - INetd mMockNetd; - IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig; - IpSecService mIpSecService; - - @Before - public void setUp() throws Exception { - mMockContext = mock(Context.class); - mMockNetd = mock(INetd.class); - mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class); - mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig); - - // Injecting mock netd - when(mMockIpSecSrvConfig.getNetdInstance()).thenReturn(mMockNetd); - } - - @Test - public void testIpSecServiceCreate() throws InterruptedException { - IpSecService ipSecSrv = IpSecService.create(mMockContext); - assertNotNull(ipSecSrv); - } - - @Test - public void testReleaseInvalidSecurityParameterIndex() throws Exception { - try { - mIpSecService.releaseSecurityParameterIndex(1); - fail("IllegalArgumentException not thrown"); - } catch (IllegalArgumentException e) { - } - } - - /** This function finds an available port */ - int findUnusedPort() throws Exception { - // Get an available port. - ServerSocket s = new ServerSocket(0); - int port = s.getLocalPort(); - s.close(); - return port; - } - - @Test - public void testOpenAndCloseUdpEncapsulationSocket() throws Exception { - int localport = -1; - IpSecUdpEncapResponse udpEncapResp = null; - - for (int i = 0; i < IpSecService.MAX_PORT_BIND_ATTEMPTS; i++) { - localport = findUnusedPort(); - - udpEncapResp = mIpSecService.openUdpEncapsulationSocket(localport, new Binder()); - assertNotNull(udpEncapResp); - if (udpEncapResp.status == IpSecManager.Status.OK) { - break; - } - - // Else retry to reduce possibility for port-bind failures. - } - - assertNotNull(udpEncapResp); - assertEquals(IpSecManager.Status.OK, udpEncapResp.status); - assertEquals(localport, udpEncapResp.port); - - mIpSecService.closeUdpEncapsulationSocket(udpEncapResp.resourceId); - udpEncapResp.fileDescriptor.close(); - - // Verify quota and RefcountedResource objects cleaned up - IpSecService.UserRecord userRecord = - mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid()); - assertEquals(0, userRecord.mSocketQuotaTracker.mCurrent); - try { - userRecord.mEncapSocketRecords.getRefcountedResourceOrThrow(udpEncapResp.resourceId); - fail("Expected IllegalArgumentException on attempt to access deleted resource"); - } catch (IllegalArgumentException expected) { - - } - } - - @Test - public void testUdpEncapsulationSocketBinderDeath() throws Exception { - IpSecUdpEncapResponse udpEncapResp = - mIpSecService.openUdpEncapsulationSocket(0, new Binder()); - - IpSecService.UserRecord userRecord = - mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid()); - IpSecService.RefcountedResource refcountedRecord = - userRecord.mEncapSocketRecords.getRefcountedResourceOrThrow( - udpEncapResp.resourceId); - - refcountedRecord.binderDied(); - - // Verify quota and RefcountedResource objects cleaned up - assertEquals(0, userRecord.mSocketQuotaTracker.mCurrent); - try { - userRecord.mEncapSocketRecords.getRefcountedResourceOrThrow(udpEncapResp.resourceId); - fail("Expected IllegalArgumentException on attempt to access deleted resource"); - } catch (IllegalArgumentException expected) { - - } - } - - @Test - public void testOpenUdpEncapsulationSocketAfterClose() throws Exception { - IpSecUdpEncapResponse udpEncapResp = - mIpSecService.openUdpEncapsulationSocket(0, new Binder()); - assertNotNull(udpEncapResp); - assertEquals(IpSecManager.Status.OK, udpEncapResp.status); - int localport = udpEncapResp.port; - - mIpSecService.closeUdpEncapsulationSocket(udpEncapResp.resourceId); - udpEncapResp.fileDescriptor.close(); - - /** Check if localport is available. */ - FileDescriptor newSocket = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - Os.bind(newSocket, INADDR_ANY, localport); - Os.close(newSocket); - } - - /** - * This function checks if the IpSecService holds the reserved port. If - * closeUdpEncapsulationSocket is not called, the socket cleanup should not be complete. - */ - @Test - public void testUdpEncapPortNotReleased() throws Exception { - IpSecUdpEncapResponse udpEncapResp = - mIpSecService.openUdpEncapsulationSocket(0, new Binder()); - assertNotNull(udpEncapResp); - assertEquals(IpSecManager.Status.OK, udpEncapResp.status); - int localport = udpEncapResp.port; - - udpEncapResp.fileDescriptor.close(); - - FileDescriptor newSocket = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - try { - Os.bind(newSocket, INADDR_ANY, localport); - fail("ErrnoException not thrown"); - } catch (ErrnoException e) { - assertEquals(EADDRINUSE, e.errno); - } - mIpSecService.closeUdpEncapsulationSocket(udpEncapResp.resourceId); - } - - @Test - public void testOpenUdpEncapsulationSocketOnRandomPort() throws Exception { - IpSecUdpEncapResponse udpEncapResp = - mIpSecService.openUdpEncapsulationSocket(0, new Binder()); - assertNotNull(udpEncapResp); - assertEquals(IpSecManager.Status.OK, udpEncapResp.status); - assertNotEquals(0, udpEncapResp.port); - mIpSecService.closeUdpEncapsulationSocket(udpEncapResp.resourceId); - udpEncapResp.fileDescriptor.close(); - } - - @Test - public void testOpenUdpEncapsulationSocketPortRange() throws Exception { - try { - mIpSecService.openUdpEncapsulationSocket(TEST_UDP_ENCAP_INVALID_PORT, new Binder()); - fail("IllegalArgumentException not thrown"); - } catch (IllegalArgumentException e) { - } - - try { - mIpSecService.openUdpEncapsulationSocket(TEST_UDP_ENCAP_PORT_OUT_RANGE, new Binder()); - fail("IllegalArgumentException not thrown"); - } catch (IllegalArgumentException e) { - } - } - - @Test - public void testOpenUdpEncapsulationSocketTwice() throws Exception { - IpSecUdpEncapResponse udpEncapResp = - mIpSecService.openUdpEncapsulationSocket(0, new Binder()); - assertNotNull(udpEncapResp); - assertEquals(IpSecManager.Status.OK, udpEncapResp.status); - int localport = udpEncapResp.port; - - IpSecUdpEncapResponse testUdpEncapResp = - mIpSecService.openUdpEncapsulationSocket(localport, new Binder()); - assertEquals(IpSecManager.Status.RESOURCE_UNAVAILABLE, testUdpEncapResp.status); - - mIpSecService.closeUdpEncapsulationSocket(udpEncapResp.resourceId); - udpEncapResp.fileDescriptor.close(); - } - - @Test - public void testCloseInvalidUdpEncapsulationSocket() throws Exception { - try { - mIpSecService.closeUdpEncapsulationSocket(1); - fail("IllegalArgumentException not thrown"); - } catch (IllegalArgumentException e) { - } - } - - @Test - public void testValidateAlgorithmsAuth() { - // Validate that correct algorithm type succeeds - IpSecConfig config = new IpSecConfig(); - config.setAuthentication(AUTH_ALGO); - mIpSecService.validateAlgorithms(config); - - // Validate that incorrect algorithm types fails - for (IpSecAlgorithm algo : new IpSecAlgorithm[] {CRYPT_ALGO, AEAD_ALGO}) { - try { - config = new IpSecConfig(); - config.setAuthentication(algo); - mIpSecService.validateAlgorithms(config); - fail("Did not throw exception on invalid algorithm type"); - } catch (IllegalArgumentException expected) { - } - } - } - - @Test - public void testValidateAlgorithmsCrypt() { - // Validate that correct algorithm type succeeds - IpSecConfig config = new IpSecConfig(); - config.setEncryption(CRYPT_ALGO); - mIpSecService.validateAlgorithms(config); - - // Validate that incorrect algorithm types fails - for (IpSecAlgorithm algo : new IpSecAlgorithm[] {AUTH_ALGO, AEAD_ALGO}) { - try { - config = new IpSecConfig(); - config.setEncryption(algo); - mIpSecService.validateAlgorithms(config); - fail("Did not throw exception on invalid algorithm type"); - } catch (IllegalArgumentException expected) { - } - } - } - - @Test - public void testValidateAlgorithmsAead() { - // Validate that correct algorithm type succeeds - IpSecConfig config = new IpSecConfig(); - config.setAuthenticatedEncryption(AEAD_ALGO); - mIpSecService.validateAlgorithms(config); - - // Validate that incorrect algorithm types fails - for (IpSecAlgorithm algo : new IpSecAlgorithm[] {AUTH_ALGO, CRYPT_ALGO}) { - try { - config = new IpSecConfig(); - config.setAuthenticatedEncryption(algo); - mIpSecService.validateAlgorithms(config); - fail("Did not throw exception on invalid algorithm type"); - } catch (IllegalArgumentException expected) { - } - } - } - - @Test - public void testValidateAlgorithmsAuthCrypt() { - // Validate that correct algorithm type succeeds - IpSecConfig config = new IpSecConfig(); - config.setAuthentication(AUTH_ALGO); - config.setEncryption(CRYPT_ALGO); - mIpSecService.validateAlgorithms(config); - } - - @Test - public void testValidateAlgorithmsNoAlgorithms() { - IpSecConfig config = new IpSecConfig(); - try { - mIpSecService.validateAlgorithms(config); - fail("Expected exception; no algorithms specified"); - } catch (IllegalArgumentException expected) { - } - } - - @Test - public void testValidateAlgorithmsAeadWithAuth() { - IpSecConfig config = new IpSecConfig(); - config.setAuthenticatedEncryption(AEAD_ALGO); - config.setAuthentication(AUTH_ALGO); - try { - mIpSecService.validateAlgorithms(config); - fail("Expected exception; both AEAD and auth algorithm specified"); - } catch (IllegalArgumentException expected) { - } - } - - @Test - public void testValidateAlgorithmsAeadWithCrypt() { - IpSecConfig config = new IpSecConfig(); - config.setAuthenticatedEncryption(AEAD_ALGO); - config.setEncryption(CRYPT_ALGO); - try { - mIpSecService.validateAlgorithms(config); - fail("Expected exception; both AEAD and crypt algorithm specified"); - } catch (IllegalArgumentException expected) { - } - } - - @Test - public void testValidateAlgorithmsAeadWithAuthAndCrypt() { - IpSecConfig config = new IpSecConfig(); - config.setAuthenticatedEncryption(AEAD_ALGO); - config.setAuthentication(AUTH_ALGO); - config.setEncryption(CRYPT_ALGO); - try { - mIpSecService.validateAlgorithms(config); - fail("Expected exception; AEAD, auth and crypt algorithm specified"); - } catch (IllegalArgumentException expected) { - } - } - - @Test - public void testDeleteInvalidTransform() throws Exception { - try { - mIpSecService.deleteTransform(1); - fail("IllegalArgumentException not thrown"); - } catch (IllegalArgumentException e) { - } - } - - @Test - public void testRemoveTransportModeTransform() throws Exception { - Socket socket = new Socket(); - socket.bind(null); - ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket); - mIpSecService.removeTransportModeTransforms(pfd); - - verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd); - } - - @Test - public void testValidateIpAddresses() throws Exception { - String[] invalidAddresses = - new String[] {"www.google.com", "::", "2001::/64", "0.0.0.0", ""}; - for (String address : invalidAddresses) { - try { - IpSecSpiResponse spiResp = - mIpSecService.allocateSecurityParameterIndex( - address, DROID_SPI, new Binder()); - fail("Invalid address was passed through IpSecService validation: " + address); - } catch (IllegalArgumentException e) { - } catch (Exception e) { - fail( - "Invalid InetAddress was not caught in validation: " - + address - + ", Exception: " - + e); - } - } - } - - /** - * This function checks if the number of encap UDP socket that one UID can reserve has a - * reasonable limit. - */ - @Test - public void testSocketResourceTrackerLimitation() throws Exception { - List openUdpEncapSockets = new ArrayList(); - // Reserve sockets until it fails. - for (int i = 0; i < MAX_NUM_ENCAP_SOCKETS; i++) { - IpSecUdpEncapResponse newUdpEncapSocket = - mIpSecService.openUdpEncapsulationSocket(0, new Binder()); - assertNotNull(newUdpEncapSocket); - if (IpSecManager.Status.OK != newUdpEncapSocket.status) { - break; - } - openUdpEncapSockets.add(newUdpEncapSocket); - } - // Assert that the total sockets quota has a reasonable limit. - assertTrue("No UDP encap socket was open", !openUdpEncapSockets.isEmpty()); - assertTrue( - "Number of open UDP encap sockets is out of bound", - openUdpEncapSockets.size() < MAX_NUM_ENCAP_SOCKETS); - - // Try to reserve one more UDP encapsulation socket, and should fail. - IpSecUdpEncapResponse extraUdpEncapSocket = - mIpSecService.openUdpEncapsulationSocket(0, new Binder()); - assertNotNull(extraUdpEncapSocket); - assertEquals(IpSecManager.Status.RESOURCE_UNAVAILABLE, extraUdpEncapSocket.status); - - // Close one of the open UDP encapsulation sockets. - mIpSecService.closeUdpEncapsulationSocket(openUdpEncapSockets.get(0).resourceId); - openUdpEncapSockets.get(0).fileDescriptor.close(); - openUdpEncapSockets.remove(0); - - // Try to reserve one more UDP encapsulation socket, and should be successful. - extraUdpEncapSocket = mIpSecService.openUdpEncapsulationSocket(0, new Binder()); - assertNotNull(extraUdpEncapSocket); - assertEquals(IpSecManager.Status.OK, extraUdpEncapSocket.status); - openUdpEncapSockets.add(extraUdpEncapSocket); - - // Close open UDP sockets. - for (IpSecUdpEncapResponse openSocket : openUdpEncapSockets) { - mIpSecService.closeUdpEncapsulationSocket(openSocket.resourceId); - openSocket.fileDescriptor.close(); - } - } - - /** - * This function checks if the number of SPI that one UID can reserve has a reasonable limit. - * This test does not test for both address families or duplicate SPIs because resource tracking - * code does not depend on them. - */ - @Test - public void testSpiResourceTrackerLimitation() throws Exception { - List reservedSpis = new ArrayList(); - // Return the same SPI for all SPI allocation since IpSecService only - // tracks the resource ID. - when(mMockNetd.ipSecAllocateSpi( - anyInt(), - anyString(), - eq(InetAddress.getLoopbackAddress().getHostAddress()), - anyInt())) - .thenReturn(DROID_SPI); - // Reserve spis until it fails. - for (int i = 0; i < MAX_NUM_SPIS; i++) { - IpSecSpiResponse newSpi = - mIpSecService.allocateSecurityParameterIndex( - InetAddress.getLoopbackAddress().getHostAddress(), - DROID_SPI + i, - new Binder()); - assertNotNull(newSpi); - if (IpSecManager.Status.OK != newSpi.status) { - break; - } - reservedSpis.add(newSpi); - } - // Assert that the SPI quota has a reasonable limit. - assertTrue(reservedSpis.size() > 0 && reservedSpis.size() < MAX_NUM_SPIS); - - // Try to reserve one more SPI, and should fail. - IpSecSpiResponse extraSpi = - mIpSecService.allocateSecurityParameterIndex( - InetAddress.getLoopbackAddress().getHostAddress(), - DROID_SPI + MAX_NUM_SPIS, - new Binder()); - assertNotNull(extraSpi); - assertEquals(IpSecManager.Status.RESOURCE_UNAVAILABLE, extraSpi.status); - - // Release one reserved spi. - mIpSecService.releaseSecurityParameterIndex(reservedSpis.get(0).resourceId); - reservedSpis.remove(0); - - // Should successfully reserve one more spi. - extraSpi = - mIpSecService.allocateSecurityParameterIndex( - InetAddress.getLoopbackAddress().getHostAddress(), - DROID_SPI + MAX_NUM_SPIS, - new Binder()); - assertNotNull(extraSpi); - assertEquals(IpSecManager.Status.OK, extraSpi.status); - - // Release reserved SPIs. - for (IpSecSpiResponse spiResp : reservedSpis) { - mIpSecService.releaseSecurityParameterIndex(spiResp.resourceId); - } - } - - @Test - public void testUidFdtagger() throws Exception { - SocketTagger actualSocketTagger = SocketTagger.get(); - - try { - FileDescriptor sockFd = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - - // Has to be done after socket creation because BlockGuardOS calls tag on new sockets - SocketTagger mockSocketTagger = mock(SocketTagger.class); - SocketTagger.set(mockSocketTagger); - - mIpSecService.mUidFdTagger.tag(sockFd, Process.LAST_APPLICATION_UID); - verify(mockSocketTagger).tag(eq(sockFd)); - } finally { - SocketTagger.set(actualSocketTagger); - } - } - - /** - * Checks if two file descriptors point to the same file. - * - *

      According to stat.h documentation, the correct way to check for equivalent or duplicated - * file descriptors is to check their inode and device. These two entries uniquely identify any - * file. - */ - private boolean fileDescriptorsEqual(FileDescriptor fd1, FileDescriptor fd2) { - try { - StructStat fd1Stat = Os.fstat(fd1); - StructStat fd2Stat = Os.fstat(fd2); - - return fd1Stat.st_ino == fd2Stat.st_ino && fd1Stat.st_dev == fd2Stat.st_dev; - } catch (ErrnoException e) { - return false; - } - } - - @Test - public void testOpenUdpEncapSocketTagsSocket() throws Exception { - IpSecService.UidFdTagger mockTagger = mock(IpSecService.UidFdTagger.class); - IpSecService testIpSecService = new IpSecService( - mMockContext, mMockIpSecSrvConfig, mockTagger); - - IpSecUdpEncapResponse udpEncapResp = - testIpSecService.openUdpEncapsulationSocket(0, new Binder()); - assertNotNull(udpEncapResp); - assertEquals(IpSecManager.Status.OK, udpEncapResp.status); - - FileDescriptor sockFd = udpEncapResp.fileDescriptor.getFileDescriptor(); - ArgumentMatcher fdMatcher = - (argFd) -> { - return fileDescriptorsEqual(sockFd, argFd); - }; - verify(mockTagger).tag(argThat(fdMatcher), eq(Os.getuid())); - - testIpSecService.closeUdpEncapsulationSocket(udpEncapResp.resourceId); - udpEncapResp.fileDescriptor.close(); - } - - @Test - public void testOpenUdpEncapsulationSocketCallsSetEncapSocketOwner() throws Exception { - IpSecUdpEncapResponse udpEncapResp = - mIpSecService.openUdpEncapsulationSocket(0, new Binder()); - - FileDescriptor sockFd = udpEncapResp.fileDescriptor.getFileDescriptor(); - ArgumentMatcher fdMatcher = (arg) -> { - try { - StructStat sockStat = Os.fstat(sockFd); - StructStat argStat = Os.fstat(arg.getFileDescriptor()); - - return sockStat.st_ino == argStat.st_ino - && sockStat.st_dev == argStat.st_dev; - } catch (ErrnoException e) { - return false; - } - }; - - verify(mMockNetd).ipSecSetEncapSocketOwner(argThat(fdMatcher), eq(Os.getuid())); - mIpSecService.closeUdpEncapsulationSocket(udpEncapResp.resourceId); - } - - @Test - public void testReserveNetId() { - final Range netIdRange = ConnectivityManager.getIpSecNetIdRange(); - for (int netId = netIdRange.getLower(); netId <= netIdRange.getUpper(); netId++) { - assertEquals(netId, mIpSecService.reserveNetId()); - } - - // Check that resource exhaustion triggers an exception - try { - mIpSecService.reserveNetId(); - fail("Did not throw error for all netIds reserved"); - } catch (IllegalStateException expected) { - } - - // Now release one and try again - int releasedNetId = - netIdRange.getLower() + (netIdRange.getUpper() - netIdRange.getLower()) / 2; - mIpSecService.releaseNetId(releasedNetId); - assertEquals(releasedNetId, mIpSecService.reserveNetId()); - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/LegacyTypeTrackerTest.kt b/packages/Connectivity/tests/unit/java/com/android/server/LegacyTypeTrackerTest.kt deleted file mode 100644 index 5ec111954fccd..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/LegacyTypeTrackerTest.kt +++ /dev/null @@ -1,197 +0,0 @@ -/* - * 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. - */ - -// Don't warn about deprecated types anywhere in this test, because LegacyTypeTracker's very reason -// for existence is to power deprecated APIs. The annotation has to apply to the whole file because -// otherwise warnings will be generated by the imports of deprecated constants like TYPE_xxx. -@file:Suppress("DEPRECATION") - -package com.android.server - -import android.content.Context -import android.content.pm.PackageManager -import android.content.pm.PackageManager.FEATURE_WIFI -import android.content.pm.PackageManager.FEATURE_WIFI_DIRECT -import android.net.ConnectivityManager.TYPE_ETHERNET -import android.net.ConnectivityManager.TYPE_MOBILE -import android.net.ConnectivityManager.TYPE_MOBILE_CBS -import android.net.ConnectivityManager.TYPE_MOBILE_DUN -import android.net.ConnectivityManager.TYPE_MOBILE_EMERGENCY -import android.net.ConnectivityManager.TYPE_MOBILE_FOTA -import android.net.ConnectivityManager.TYPE_MOBILE_HIPRI -import android.net.ConnectivityManager.TYPE_MOBILE_IA -import android.net.ConnectivityManager.TYPE_MOBILE_IMS -import android.net.ConnectivityManager.TYPE_MOBILE_MMS -import android.net.ConnectivityManager.TYPE_MOBILE_SUPL -import android.net.ConnectivityManager.TYPE_VPN -import android.net.ConnectivityManager.TYPE_WIFI -import android.net.ConnectivityManager.TYPE_WIFI_P2P -import android.net.ConnectivityManager.TYPE_WIMAX -import android.net.EthernetManager -import android.net.NetworkInfo.DetailedState.CONNECTED -import android.net.NetworkInfo.DetailedState.DISCONNECTED -import android.telephony.TelephonyManager -import androidx.test.filters.SmallTest -import androidx.test.runner.AndroidJUnit4 -import com.android.server.ConnectivityService.LegacyTypeTracker -import com.android.server.connectivity.NetworkAgentInfo -import org.junit.Assert.assertFalse -import org.junit.Assert.assertNull -import org.junit.Assert.assertSame -import org.junit.Assert.assertTrue -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.ArgumentMatchers.any -import org.mockito.ArgumentMatchers.anyInt -import org.mockito.Mockito.doReturn -import org.mockito.Mockito.mock -import org.mockito.Mockito.never -import org.mockito.Mockito.reset -import org.mockito.Mockito.verify - -const val UNSUPPORTED_TYPE = TYPE_WIMAX - -@RunWith(AndroidJUnit4::class) -@SmallTest -class LegacyTypeTrackerTest { - private val supportedTypes = arrayOf(TYPE_WIFI, TYPE_WIFI_P2P, TYPE_ETHERNET, TYPE_MOBILE, - TYPE_MOBILE_SUPL, TYPE_MOBILE_MMS, TYPE_MOBILE_SUPL, TYPE_MOBILE_DUN, TYPE_MOBILE_HIPRI, - TYPE_MOBILE_FOTA, TYPE_MOBILE_IMS, TYPE_MOBILE_CBS, TYPE_MOBILE_IA, - TYPE_MOBILE_EMERGENCY, TYPE_VPN) - - private val mMockService = mock(ConnectivityService::class.java).apply { - doReturn(false).`when`(this).isDefaultNetwork(any()) - } - private val mPm = mock(PackageManager::class.java) - private val mContext = mock(Context::class.java).apply { - doReturn(true).`when`(mPm).hasSystemFeature(FEATURE_WIFI) - doReturn(true).`when`(mPm).hasSystemFeature(FEATURE_WIFI_DIRECT) - doReturn(mPm).`when`(this).packageManager - doReturn(mock(EthernetManager::class.java)).`when`(this).getSystemService( - Context.ETHERNET_SERVICE) - } - private val mTm = mock(TelephonyManager::class.java).apply { - doReturn(true).`when`(this).isDataCapable - } - - private fun makeTracker() = LegacyTypeTracker(mMockService).apply { - loadSupportedTypes(mContext, mTm) - } - - @Test - fun testSupportedTypes() { - val tracker = makeTracker() - supportedTypes.forEach { - assertTrue(tracker.isTypeSupported(it)) - } - assertFalse(tracker.isTypeSupported(UNSUPPORTED_TYPE)) - } - - @Test - fun testSupportedTypes_NoEthernet() { - doReturn(null).`when`(mContext).getSystemService(Context.ETHERNET_SERVICE) - assertFalse(makeTracker().isTypeSupported(TYPE_ETHERNET)) - } - - @Test - fun testSupportedTypes_NoTelephony() { - doReturn(false).`when`(mTm).isDataCapable - val tracker = makeTracker() - val nonMobileTypes = arrayOf(TYPE_WIFI, TYPE_WIFI_P2P, TYPE_ETHERNET, TYPE_VPN) - nonMobileTypes.forEach { - assertTrue(tracker.isTypeSupported(it)) - } - supportedTypes.toSet().minus(nonMobileTypes).forEach { - assertFalse(tracker.isTypeSupported(it)) - } - } - - @Test - fun testSupportedTypes_NoWifiDirect() { - doReturn(false).`when`(mPm).hasSystemFeature(FEATURE_WIFI_DIRECT) - val tracker = makeTracker() - assertFalse(tracker.isTypeSupported(TYPE_WIFI_P2P)) - supportedTypes.toSet().minus(TYPE_WIFI_P2P).forEach { - assertTrue(tracker.isTypeSupported(it)) - } - } - - @Test - fun testSupl() { - val tracker = makeTracker() - val mobileNai = mock(NetworkAgentInfo::class.java) - tracker.add(TYPE_MOBILE, mobileNai) - verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, CONNECTED, TYPE_MOBILE) - reset(mMockService) - tracker.add(TYPE_MOBILE_SUPL, mobileNai) - verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, CONNECTED, TYPE_MOBILE_SUPL) - reset(mMockService) - tracker.remove(TYPE_MOBILE_SUPL, mobileNai, false /* wasDefault */) - verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, DISCONNECTED, TYPE_MOBILE_SUPL) - reset(mMockService) - tracker.add(TYPE_MOBILE_SUPL, mobileNai) - verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, CONNECTED, TYPE_MOBILE_SUPL) - reset(mMockService) - tracker.remove(mobileNai, false) - verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, DISCONNECTED, TYPE_MOBILE_SUPL) - verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, DISCONNECTED, TYPE_MOBILE) - } - - @Test - fun testAddNetwork() { - val tracker = makeTracker() - val mobileNai = mock(NetworkAgentInfo::class.java) - val wifiNai = mock(NetworkAgentInfo::class.java) - tracker.add(TYPE_MOBILE, mobileNai) - tracker.add(TYPE_WIFI, wifiNai) - assertSame(tracker.getNetworkForType(TYPE_MOBILE), mobileNai) - assertSame(tracker.getNetworkForType(TYPE_WIFI), wifiNai) - // Make sure adding a second NAI does not change the results. - val secondMobileNai = mock(NetworkAgentInfo::class.java) - tracker.add(TYPE_MOBILE, secondMobileNai) - assertSame(tracker.getNetworkForType(TYPE_MOBILE), mobileNai) - assertSame(tracker.getNetworkForType(TYPE_WIFI), wifiNai) - // Make sure removing a network that wasn't added for this type is a no-op. - tracker.remove(TYPE_MOBILE, wifiNai, false /* wasDefault */) - assertSame(tracker.getNetworkForType(TYPE_MOBILE), mobileNai) - assertSame(tracker.getNetworkForType(TYPE_WIFI), wifiNai) - // Remove the top network for mobile and make sure the second one becomes the network - // of record for this type. - tracker.remove(TYPE_MOBILE, mobileNai, false /* wasDefault */) - assertSame(tracker.getNetworkForType(TYPE_MOBILE), secondMobileNai) - assertSame(tracker.getNetworkForType(TYPE_WIFI), wifiNai) - // Make sure adding a network for an unsupported type does not register it. - tracker.add(UNSUPPORTED_TYPE, mobileNai) - assertNull(tracker.getNetworkForType(UNSUPPORTED_TYPE)) - } - - @Test - fun testBroadcastOnDisconnect() { - val tracker = makeTracker() - val mobileNai1 = mock(NetworkAgentInfo::class.java) - val mobileNai2 = mock(NetworkAgentInfo::class.java) - doReturn(false).`when`(mMockService).isDefaultNetwork(mobileNai1) - tracker.add(TYPE_MOBILE, mobileNai1) - verify(mMockService).sendLegacyNetworkBroadcast(mobileNai1, CONNECTED, TYPE_MOBILE) - reset(mMockService) - doReturn(false).`when`(mMockService).isDefaultNetwork(mobileNai2) - tracker.add(TYPE_MOBILE, mobileNai2) - verify(mMockService, never()).sendLegacyNetworkBroadcast(any(), any(), anyInt()) - tracker.remove(TYPE_MOBILE, mobileNai1, false /* wasDefault */) - verify(mMockService).sendLegacyNetworkBroadcast(mobileNai1, DISCONNECTED, TYPE_MOBILE) - verify(mMockService).sendLegacyNetworkBroadcast(mobileNai2, CONNECTED, TYPE_MOBILE) - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/NetIdManagerTest.kt b/packages/Connectivity/tests/unit/java/com/android/server/NetIdManagerTest.kt deleted file mode 100644 index 6f5e740d344c3..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/NetIdManagerTest.kt +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.server - -import androidx.test.filters.SmallTest -import androidx.test.runner.AndroidJUnit4 -import com.android.server.NetIdManager.MIN_NET_ID -import com.android.testutils.assertThrows -import com.android.testutils.ExceptionUtils.ThrowingRunnable -import org.junit.Test -import org.junit.runner.RunWith -import kotlin.test.assertEquals - -@RunWith(AndroidJUnit4::class) -@SmallTest -class NetIdManagerTest { - @Test - fun testReserveReleaseNetId() { - val manager = NetIdManager(MIN_NET_ID + 4) - assertEquals(MIN_NET_ID, manager.reserveNetId()) - assertEquals(MIN_NET_ID + 1, manager.reserveNetId()) - assertEquals(MIN_NET_ID + 2, manager.reserveNetId()) - assertEquals(MIN_NET_ID + 3, manager.reserveNetId()) - - manager.releaseNetId(MIN_NET_ID + 1) - manager.releaseNetId(MIN_NET_ID + 3) - // IDs only loop once there is no higher ID available - assertEquals(MIN_NET_ID + 4, manager.reserveNetId()) - assertEquals(MIN_NET_ID + 1, manager.reserveNetId()) - assertEquals(MIN_NET_ID + 3, manager.reserveNetId()) - assertThrows(IllegalStateException::class.java, ThrowingRunnable { manager.reserveNetId() }) - manager.releaseNetId(MIN_NET_ID + 5) - // Still no ID available: MIN_NET_ID + 5 was not reserved - assertThrows(IllegalStateException::class.java, ThrowingRunnable { manager.reserveNetId() }) - manager.releaseNetId(MIN_NET_ID + 2) - // Throwing an exception still leaves the manager in a working state - assertEquals(MIN_NET_ID + 2, manager.reserveNetId()) - } -} \ No newline at end of file diff --git a/packages/Connectivity/tests/unit/java/com/android/server/NetworkManagementServiceTest.java b/packages/Connectivity/tests/unit/java/com/android/server/NetworkManagementServiceTest.java deleted file mode 100644 index 13516d75a50d7..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/NetworkManagementServiceTest.java +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server; - -import static android.util.DebugUtils.valueToString; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.timeout; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; - -import android.annotation.NonNull; -import android.content.Context; -import android.net.INetd; -import android.net.INetdUnsolicitedEventListener; -import android.net.LinkAddress; -import android.net.NetworkPolicyManager; -import android.os.BatteryStats; -import android.os.Binder; -import android.os.IBinder; -import android.os.Process; -import android.os.RemoteException; -import android.test.suitebuilder.annotation.SmallTest; -import android.util.ArrayMap; - -import androidx.test.runner.AndroidJUnit4; - -import com.android.internal.app.IBatteryStats; -import com.android.server.NetworkManagementService.Dependencies; -import com.android.server.net.BaseNetworkObserver; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.function.BiFunction; - -/** - * Tests for {@link NetworkManagementService}. - */ -@RunWith(AndroidJUnit4.class) -@SmallTest -public class NetworkManagementServiceTest { - private NetworkManagementService mNMService; - @Mock private Context mContext; - @Mock private IBatteryStats.Stub mBatteryStatsService; - @Mock private INetd.Stub mNetdService; - - private static final int TEST_UID = 111; - - @NonNull - @Captor - private ArgumentCaptor mUnsolListenerCaptor; - - private final MockDependencies mDeps = new MockDependencies(); - - private final class MockDependencies extends Dependencies { - @Override - public IBinder getService(String name) { - switch (name) { - case BatteryStats.SERVICE_NAME: - return mBatteryStatsService; - default: - throw new UnsupportedOperationException("Unknown service " + name); - } - } - - @Override - public void registerLocalService(NetworkManagementInternal nmi) { - } - - @Override - public INetd getNetd() { - return mNetdService; - } - - @Override - public int getCallingUid() { - return Process.SYSTEM_UID; - } - } - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - doNothing().when(mNetdService) - .registerUnsolicitedEventListener(mUnsolListenerCaptor.capture()); - // Start the service and wait until it connects to our socket. - mNMService = NetworkManagementService.create(mContext, mDeps); - } - - @After - public void tearDown() throws Exception { - mNMService.shutdown(); - } - - private static T expectSoon(T mock) { - return verify(mock, timeout(200)); - } - - /** - * Tests that network observers work properly. - */ - @Test - public void testNetworkObservers() throws Exception { - BaseNetworkObserver observer = mock(BaseNetworkObserver.class); - doReturn(new Binder()).when(observer).asBinder(); // Used by registerObserver. - mNMService.registerObserver(observer); - - // Forget everything that happened to the mock so far, so we can explicitly verify - // everything that happens and does not happen to it from now on. - - INetdUnsolicitedEventListener unsolListener = mUnsolListenerCaptor.getValue(); - reset(observer); - // Now call unsolListener methods and ensure that the observer methods are - // called. After every method we expect a callback soon after; to ensure that - // invalid messages don't cause any callbacks, we call verifyNoMoreInteractions at the end. - - /** - * Interface changes. - */ - unsolListener.onInterfaceAdded("rmnet12"); - expectSoon(observer).interfaceAdded("rmnet12"); - - unsolListener.onInterfaceRemoved("eth1"); - expectSoon(observer).interfaceRemoved("eth1"); - - unsolListener.onInterfaceChanged("clat4", true); - expectSoon(observer).interfaceStatusChanged("clat4", true); - - unsolListener.onInterfaceLinkStateChanged("rmnet0", false); - expectSoon(observer).interfaceLinkStateChanged("rmnet0", false); - - /** - * Bandwidth control events. - */ - unsolListener.onQuotaLimitReached("data", "rmnet_usb0"); - expectSoon(observer).limitReached("data", "rmnet_usb0"); - - /** - * Interface class activity. - */ - unsolListener.onInterfaceClassActivityChanged(true, 1, 1234, TEST_UID); - expectSoon(observer).interfaceClassDataActivityChanged(1, true, 1234, TEST_UID); - - unsolListener.onInterfaceClassActivityChanged(false, 9, 5678, TEST_UID); - expectSoon(observer).interfaceClassDataActivityChanged(9, false, 5678, TEST_UID); - - unsolListener.onInterfaceClassActivityChanged(false, 9, 4321, TEST_UID); - expectSoon(observer).interfaceClassDataActivityChanged(9, false, 4321, TEST_UID); - - /** - * IP address changes. - */ - unsolListener.onInterfaceAddressUpdated("fe80::1/64", "wlan0", 128, 253); - expectSoon(observer).addressUpdated("wlan0", new LinkAddress("fe80::1/64", 128, 253)); - - unsolListener.onInterfaceAddressRemoved("fe80::1/64", "wlan0", 128, 253); - expectSoon(observer).addressRemoved("wlan0", new LinkAddress("fe80::1/64", 128, 253)); - - unsolListener.onInterfaceAddressRemoved("2001:db8::1/64", "wlan0", 1, 0); - expectSoon(observer).addressRemoved("wlan0", new LinkAddress("2001:db8::1/64", 1, 0)); - - /** - * DNS information broadcasts. - */ - unsolListener.onInterfaceDnsServerInfo("rmnet_usb0", 3600, new String[]{"2001:db8::1"}); - expectSoon(observer).interfaceDnsServerInfo("rmnet_usb0", 3600, - new String[]{"2001:db8::1"}); - - unsolListener.onInterfaceDnsServerInfo("wlan0", 14400, - new String[]{"2001:db8::1", "2001:db8::2"}); - expectSoon(observer).interfaceDnsServerInfo("wlan0", 14400, - new String[]{"2001:db8::1", "2001:db8::2"}); - - // We don't check for negative lifetimes, only for parse errors. - unsolListener.onInterfaceDnsServerInfo("wlan0", -3600, new String[]{"::1"}); - expectSoon(observer).interfaceDnsServerInfo("wlan0", -3600, - new String[]{"::1"}); - - // No syntax checking on the addresses. - unsolListener.onInterfaceDnsServerInfo("wlan0", 600, - new String[]{"", "::", "", "foo", "::1"}); - expectSoon(observer).interfaceDnsServerInfo("wlan0", 600, - new String[]{"", "::", "", "foo", "::1"}); - - // Make sure nothing else was called. - verifyNoMoreInteractions(observer); - } - - @Test - public void testFirewallEnabled() { - mNMService.setFirewallEnabled(true); - assertTrue(mNMService.isFirewallEnabled()); - - mNMService.setFirewallEnabled(false); - assertFalse(mNMService.isFirewallEnabled()); - } - - @Test - public void testNetworkRestrictedDefault() { - assertFalse(mNMService.isNetworkRestricted(TEST_UID)); - } - - @Test - public void testMeteredNetworkRestrictions() throws RemoteException { - // Make sure the mocked netd method returns true. - doReturn(true).when(mNetdService).bandwidthEnableDataSaver(anyBoolean()); - - // Restrict usage of mobile data in background - mNMService.setUidOnMeteredNetworkDenylist(TEST_UID, true); - assertTrue("Should be true since mobile data usage is restricted", - mNMService.isNetworkRestricted(TEST_UID)); - - mNMService.setDataSaverModeEnabled(true); - verify(mNetdService).bandwidthEnableDataSaver(true); - - mNMService.setUidOnMeteredNetworkDenylist(TEST_UID, false); - assertTrue("Should be true since data saver is on and the uid is not allowlisted", - mNMService.isNetworkRestricted(TEST_UID)); - - mNMService.setUidOnMeteredNetworkAllowlist(TEST_UID, true); - assertFalse("Should be false since data saver is on and the uid is allowlisted", - mNMService.isNetworkRestricted(TEST_UID)); - - // remove uid from allowlist and turn datasaver off again - mNMService.setUidOnMeteredNetworkAllowlist(TEST_UID, false); - mNMService.setDataSaverModeEnabled(false); - verify(mNetdService).bandwidthEnableDataSaver(false); - assertFalse("Network should not be restricted when data saver is off", - mNMService.isNetworkRestricted(TEST_UID)); - } - - @Test - public void testFirewallChains() { - final ArrayMap> expected = new ArrayMap<>(); - // Dozable chain - final ArrayMap isRestrictedForDozable = new ArrayMap<>(); - isRestrictedForDozable.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, true); - isRestrictedForDozable.put(INetd.FIREWALL_RULE_ALLOW, false); - isRestrictedForDozable.put(INetd.FIREWALL_RULE_DENY, true); - expected.put(INetd.FIREWALL_CHAIN_DOZABLE, isRestrictedForDozable); - // Powersaver chain - final ArrayMap isRestrictedForPowerSave = new ArrayMap<>(); - isRestrictedForPowerSave.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, true); - isRestrictedForPowerSave.put(INetd.FIREWALL_RULE_ALLOW, false); - isRestrictedForPowerSave.put(INetd.FIREWALL_RULE_DENY, true); - expected.put(INetd.FIREWALL_CHAIN_POWERSAVE, isRestrictedForPowerSave); - // Standby chain - final ArrayMap isRestrictedForStandby = new ArrayMap<>(); - isRestrictedForStandby.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, false); - isRestrictedForStandby.put(INetd.FIREWALL_RULE_ALLOW, false); - isRestrictedForStandby.put(INetd.FIREWALL_RULE_DENY, true); - expected.put(INetd.FIREWALL_CHAIN_STANDBY, isRestrictedForStandby); - // Restricted mode chain - final ArrayMap isRestrictedForRestrictedMode = new ArrayMap<>(); - isRestrictedForRestrictedMode.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, true); - isRestrictedForRestrictedMode.put(INetd.FIREWALL_RULE_ALLOW, false); - isRestrictedForRestrictedMode.put(INetd.FIREWALL_RULE_DENY, true); - expected.put(INetd.FIREWALL_CHAIN_RESTRICTED, isRestrictedForRestrictedMode); - - final int[] chains = { - INetd.FIREWALL_CHAIN_STANDBY, - INetd.FIREWALL_CHAIN_POWERSAVE, - INetd.FIREWALL_CHAIN_DOZABLE, - INetd.FIREWALL_CHAIN_RESTRICTED - }; - final int[] states = { - INetd.FIREWALL_RULE_ALLOW, - INetd.FIREWALL_RULE_DENY, - NetworkPolicyManager.FIREWALL_RULE_DEFAULT - }; - BiFunction errorMsg = (chain, state) -> { - return String.format("Unexpected value for chain: %s and state: %s", - valueToString(INetd.class, "FIREWALL_CHAIN_", chain), - valueToString(INetd.class, "FIREWALL_RULE_", state)); - }; - for (int chain : chains) { - final ArrayMap expectedValues = expected.get(chain); - mNMService.setFirewallChainEnabled(chain, true); - for (int state : states) { - mNMService.setFirewallUidRule(chain, TEST_UID, state); - assertEquals(errorMsg.apply(chain, state), - expectedValues.get(state), mNMService.isNetworkRestricted(TEST_UID)); - } - mNMService.setFirewallChainEnabled(chain, false); - } - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/NsdServiceTest.java b/packages/Connectivity/tests/unit/java/com/android/server/NsdServiceTest.java deleted file mode 100644 index a90fa6882c257..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/NsdServiceTest.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.timeout; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.content.ContentResolver; -import android.content.Context; -import android.net.nsd.NsdManager; -import android.net.nsd.NsdServiceInfo; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Looper; -import android.os.Message; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.server.NsdService.DaemonConnection; -import com.android.server.NsdService.DaemonConnectionSupplier; -import com.android.server.NsdService.NativeCallbackReceiver; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -// TODOs: -// - test client can send requests and receive replies -// - test NSD_ON ENABLE/DISABLED listening -@RunWith(AndroidJUnit4.class) -@SmallTest -public class NsdServiceTest { - - static final int PROTOCOL = NsdManager.PROTOCOL_DNS_SD; - - long mTimeoutMs = 100; // non-final so that tests can adjust the value. - - @Mock Context mContext; - @Mock ContentResolver mResolver; - @Mock NsdService.NsdSettings mSettings; - @Mock DaemonConnection mDaemon; - NativeCallbackReceiver mDaemonCallback; - HandlerThread mThread; - TestHandler mHandler; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mThread = new HandlerThread("mock-service-handler"); - mThread.start(); - mHandler = new TestHandler(mThread.getLooper()); - when(mContext.getContentResolver()).thenReturn(mResolver); - } - - @After - public void tearDown() throws Exception { - if (mThread != null) { - mThread.quit(); - mThread = null; - } - } - - @Test - public void testClientsCanConnectAndDisconnect() { - when(mSettings.isEnabled()).thenReturn(true); - - NsdService service = makeService(); - - NsdManager client1 = connectClient(service); - verify(mDaemon, timeout(100).times(1)).start(); - - NsdManager client2 = connectClient(service); - - client1.disconnect(); - client2.disconnect(); - - verify(mDaemon, timeout(mTimeoutMs).times(1)).stop(); - - client1.disconnect(); - client2.disconnect(); - } - - @Test - public void testClientRequestsAreGCedAtDisconnection() { - when(mSettings.isEnabled()).thenReturn(true); - when(mDaemon.execute(any())).thenReturn(true); - - NsdService service = makeService(); - NsdManager client = connectClient(service); - - verify(mDaemon, timeout(100).times(1)).start(); - - NsdServiceInfo request = new NsdServiceInfo("a_name", "a_type"); - request.setPort(2201); - - // Client registration request - NsdManager.RegistrationListener listener1 = mock(NsdManager.RegistrationListener.class); - client.registerService(request, PROTOCOL, listener1); - verifyDaemonCommand("register 2 a_name a_type 2201"); - - // Client discovery request - NsdManager.DiscoveryListener listener2 = mock(NsdManager.DiscoveryListener.class); - client.discoverServices("a_type", PROTOCOL, listener2); - verifyDaemonCommand("discover 3 a_type"); - - // Client resolve request - NsdManager.ResolveListener listener3 = mock(NsdManager.ResolveListener.class); - client.resolveService(request, listener3); - verifyDaemonCommand("resolve 4 a_name a_type local."); - - // Client disconnects - client.disconnect(); - verify(mDaemon, timeout(mTimeoutMs).times(1)).stop(); - - // checks that request are cleaned - verifyDaemonCommands("stop-register 2", "stop-discover 3", "stop-resolve 4"); - - client.disconnect(); - } - - NsdService makeService() { - DaemonConnectionSupplier supplier = (callback) -> { - mDaemonCallback = callback; - return mDaemon; - }; - NsdService service = new NsdService(mContext, mSettings, mHandler, supplier); - verify(mDaemon, never()).execute(any(String.class)); - return service; - } - - NsdManager connectClient(NsdService service) { - return new NsdManager(mContext, service); - } - - void verifyDaemonCommands(String... wants) { - verifyDaemonCommand(String.join(" ", wants), wants.length); - } - - void verifyDaemonCommand(String want) { - verifyDaemonCommand(want, 1); - } - - void verifyDaemonCommand(String want, int n) { - ArgumentCaptor argumentsCaptor = ArgumentCaptor.forClass(Object.class); - verify(mDaemon, timeout(mTimeoutMs).times(n)).execute(argumentsCaptor.capture()); - String got = ""; - for (Object o : argumentsCaptor.getAllValues()) { - got += o + " "; - } - assertEquals(want, got.trim()); - // rearm deamon for next command verification - reset(mDaemon); - when(mDaemon.execute(any())).thenReturn(true); - } - - public static class TestHandler extends Handler { - public Message lastMessage; - - TestHandler(Looper looper) { - super(looper); - } - - @Override - public void handleMessage(Message msg) { - lastMessage = obtainMessage(); - lastMessage.copyFrom(msg); - } - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/DnsManagerTest.java b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/DnsManagerTest.java deleted file mode 100644 index 0ffeec98cf90e..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/DnsManagerTest.java +++ /dev/null @@ -1,433 +0,0 @@ -/* - * Copyright (C) 2018, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_DEFAULT_MODE; -import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE; -import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OFF; -import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME; -import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_SPECIFIER; -import static android.net.NetworkCapabilities.MAX_TRANSPORT; -import static android.net.NetworkCapabilities.MIN_TRANSPORT; -import static android.net.NetworkCapabilities.TRANSPORT_VPN; -import static android.net.NetworkCapabilities.TRANSPORT_WIFI; -import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_FAILURE; -import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_SUCCESS; - -import static com.android.testutils.MiscAsserts.assertContainsExactly; -import static com.android.testutils.MiscAsserts.assertContainsStringsExactly; -import static com.android.testutils.MiscAsserts.assertFieldCountEquals; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.annotation.NonNull; -import android.content.Context; -import android.net.ConnectivitySettingsManager; -import android.net.IDnsResolver; -import android.net.IpPrefix; -import android.net.LinkAddress; -import android.net.LinkProperties; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.ResolverOptionsParcel; -import android.net.ResolverParamsParcel; -import android.net.RouteInfo; -import android.net.shared.PrivateDnsConfig; -import android.provider.Settings; -import android.test.mock.MockContentResolver; -import android.util.SparseArray; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.internal.util.MessageUtils; -import com.android.internal.util.test.FakeSettingsProvider; - -import libcore.net.InetAddressUtils; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.net.InetAddress; -import java.util.Arrays; - -/** - * Tests for {@link DnsManager}. - * - * Build, install and run with: - * runtest frameworks-net -c com.android.server.connectivity.DnsManagerTest - */ -@RunWith(AndroidJUnit4.class) -@SmallTest -public class DnsManagerTest { - static final String TEST_IFACENAME = "test_wlan0"; - static final int TEST_NETID = 100; - static final int TEST_NETID_ALTERNATE = 101; - static final int TEST_NETID_UNTRACKED = 102; - static final int TEST_DEFAULT_SAMPLE_VALIDITY_SECONDS = 1800; - static final int TEST_DEFAULT_SUCCESS_THRESHOLD_PERCENT = 25; - static final int TEST_DEFAULT_MIN_SAMPLES = 8; - static final int TEST_DEFAULT_MAX_SAMPLES = 64; - static final int[] TEST_TRANSPORT_TYPES = {TRANSPORT_WIFI, TRANSPORT_VPN}; - - DnsManager mDnsManager; - MockContentResolver mContentResolver; - - @Mock Context mCtx; - @Mock IDnsResolver mMockDnsResolver; - - private void assertResolverOptionsEquals( - @NonNull ResolverOptionsParcel actual, - @NonNull ResolverOptionsParcel expected) { - assertEquals(actual.hosts, expected.hosts); - assertEquals(actual.tcMode, expected.tcMode); - assertEquals(actual.enforceDnsUid, expected.enforceDnsUid); - assertFieldCountEquals(3, ResolverOptionsParcel.class); - } - - private void assertResolverParamsEquals(@NonNull ResolverParamsParcel actual, - @NonNull ResolverParamsParcel expected) { - assertEquals(actual.netId, expected.netId); - assertEquals(actual.sampleValiditySeconds, expected.sampleValiditySeconds); - assertEquals(actual.successThreshold, expected.successThreshold); - assertEquals(actual.minSamples, expected.minSamples); - assertEquals(actual.maxSamples, expected.maxSamples); - assertEquals(actual.baseTimeoutMsec, expected.baseTimeoutMsec); - assertEquals(actual.retryCount, expected.retryCount); - assertContainsStringsExactly(actual.servers, expected.servers); - assertContainsStringsExactly(actual.domains, expected.domains); - assertEquals(actual.tlsName, expected.tlsName); - assertContainsStringsExactly(actual.tlsServers, expected.tlsServers); - assertContainsStringsExactly(actual.tlsFingerprints, expected.tlsFingerprints); - assertEquals(actual.caCertificate, expected.caCertificate); - assertEquals(actual.tlsConnectTimeoutMs, expected.tlsConnectTimeoutMs); - assertResolverOptionsEquals(actual.resolverOptions, expected.resolverOptions); - assertContainsExactly(actual.transportTypes, expected.transportTypes); - assertFieldCountEquals(16, ResolverParamsParcel.class); - } - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mContentResolver = new MockContentResolver(); - mContentResolver.addProvider(Settings.AUTHORITY, - new FakeSettingsProvider()); - when(mCtx.getContentResolver()).thenReturn(mContentResolver); - mDnsManager = new DnsManager(mCtx, mMockDnsResolver); - - // Clear the private DNS settings - Settings.Global.putString(mContentResolver, PRIVATE_DNS_DEFAULT_MODE, ""); - Settings.Global.putString(mContentResolver, PRIVATE_DNS_MODE, ""); - Settings.Global.putString(mContentResolver, PRIVATE_DNS_SPECIFIER, ""); - } - - @Test - public void testTrackedValidationUpdates() throws Exception { - mDnsManager.updatePrivateDns(new Network(TEST_NETID), - mDnsManager.getPrivateDnsConfig()); - mDnsManager.updatePrivateDns(new Network(TEST_NETID_ALTERNATE), - mDnsManager.getPrivateDnsConfig()); - LinkProperties lp = new LinkProperties(); - lp.setInterfaceName(TEST_IFACENAME); - lp.addDnsServer(InetAddress.getByName("3.3.3.3")); - lp.addDnsServer(InetAddress.getByName("4.4.4.4")); - - // Send a validation event that is tracked on the alternate netId - mDnsManager.updateTransportsForNetwork(TEST_NETID, TEST_TRANSPORT_TYPES); - mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp); - mDnsManager.flushVmDnsCache(); - mDnsManager.updateTransportsForNetwork(TEST_NETID_ALTERNATE, TEST_TRANSPORT_TYPES); - mDnsManager.noteDnsServersForNetwork(TEST_NETID_ALTERNATE, lp); - mDnsManager.flushVmDnsCache(); - mDnsManager.updatePrivateDnsValidation( - new DnsManager.PrivateDnsValidationUpdate(TEST_NETID_ALTERNATE, - InetAddress.parseNumericAddress("4.4.4.4"), "", - VALIDATION_RESULT_SUCCESS)); - LinkProperties fixedLp = new LinkProperties(lp); - mDnsManager.updatePrivateDnsStatus(TEST_NETID, fixedLp); - assertFalse(fixedLp.isPrivateDnsActive()); - assertNull(fixedLp.getPrivateDnsServerName()); - fixedLp = new LinkProperties(lp); - mDnsManager.updatePrivateDnsStatus(TEST_NETID_ALTERNATE, fixedLp); - assertTrue(fixedLp.isPrivateDnsActive()); - assertNull(fixedLp.getPrivateDnsServerName()); - assertEquals(Arrays.asList(InetAddress.getByName("4.4.4.4")), - fixedLp.getValidatedPrivateDnsServers()); - - // Set up addresses for strict mode and switch to it. - lp.addLinkAddress(new LinkAddress("192.0.2.4/24")); - lp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"), - TEST_IFACENAME)); - lp.addLinkAddress(new LinkAddress("2001:db8:1::1/64")); - lp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"), - TEST_IFACENAME)); - - ConnectivitySettingsManager.setPrivateDnsMode(mCtx, PRIVATE_DNS_MODE_PROVIDER_HOSTNAME); - ConnectivitySettingsManager.setPrivateDnsHostname(mCtx, "strictmode.com"); - mDnsManager.updatePrivateDns(new Network(TEST_NETID), - new PrivateDnsConfig("strictmode.com", new InetAddress[] { - InetAddress.parseNumericAddress("6.6.6.6"), - InetAddress.parseNumericAddress("2001:db8:66:66::1") - })); - mDnsManager.updateTransportsForNetwork(TEST_NETID, TEST_TRANSPORT_TYPES); - mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp); - mDnsManager.flushVmDnsCache(); - fixedLp = new LinkProperties(lp); - mDnsManager.updatePrivateDnsStatus(TEST_NETID, fixedLp); - assertTrue(fixedLp.isPrivateDnsActive()); - assertEquals("strictmode.com", fixedLp.getPrivateDnsServerName()); - // No validation events yet. - assertEquals(Arrays.asList(new InetAddress[0]), fixedLp.getValidatedPrivateDnsServers()); - // Validate one. - mDnsManager.updatePrivateDnsValidation( - new DnsManager.PrivateDnsValidationUpdate(TEST_NETID, - InetAddress.parseNumericAddress("6.6.6.6"), "strictmode.com", - VALIDATION_RESULT_SUCCESS)); - fixedLp = new LinkProperties(lp); - mDnsManager.updatePrivateDnsStatus(TEST_NETID, fixedLp); - assertEquals(Arrays.asList(InetAddress.parseNumericAddress("6.6.6.6")), - fixedLp.getValidatedPrivateDnsServers()); - // Validate the 2nd one. - mDnsManager.updatePrivateDnsValidation( - new DnsManager.PrivateDnsValidationUpdate(TEST_NETID, - InetAddress.parseNumericAddress("2001:db8:66:66::1"), "strictmode.com", - VALIDATION_RESULT_SUCCESS)); - fixedLp = new LinkProperties(lp); - mDnsManager.updatePrivateDnsStatus(TEST_NETID, fixedLp); - assertEquals(Arrays.asList( - InetAddress.parseNumericAddress("2001:db8:66:66::1"), - InetAddress.parseNumericAddress("6.6.6.6")), - fixedLp.getValidatedPrivateDnsServers()); - } - - @Test - public void testIgnoreUntrackedValidationUpdates() throws Exception { - // The PrivateDnsConfig map is empty, so no validation events will - // be tracked. - LinkProperties lp = new LinkProperties(); - lp.addDnsServer(InetAddress.getByName("3.3.3.3")); - mDnsManager.updateTransportsForNetwork(TEST_NETID, TEST_TRANSPORT_TYPES); - mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp); - mDnsManager.flushVmDnsCache(); - mDnsManager.updatePrivateDnsValidation( - new DnsManager.PrivateDnsValidationUpdate(TEST_NETID, - InetAddress.parseNumericAddress("3.3.3.3"), "", - VALIDATION_RESULT_SUCCESS)); - mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp); - assertFalse(lp.isPrivateDnsActive()); - assertNull(lp.getPrivateDnsServerName()); - - // Validation event has untracked netId - mDnsManager.updatePrivateDns(new Network(TEST_NETID), - mDnsManager.getPrivateDnsConfig()); - mDnsManager.updateTransportsForNetwork(TEST_NETID, TEST_TRANSPORT_TYPES); - mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp); - mDnsManager.flushVmDnsCache(); - mDnsManager.updatePrivateDnsValidation( - new DnsManager.PrivateDnsValidationUpdate(TEST_NETID_UNTRACKED, - InetAddress.parseNumericAddress("3.3.3.3"), "", - VALIDATION_RESULT_SUCCESS)); - mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp); - assertFalse(lp.isPrivateDnsActive()); - assertNull(lp.getPrivateDnsServerName()); - - // Validation event has untracked ipAddress - mDnsManager.updatePrivateDnsValidation( - new DnsManager.PrivateDnsValidationUpdate(TEST_NETID, - InetAddress.parseNumericAddress("4.4.4.4"), "", - VALIDATION_RESULT_SUCCESS)); - mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp); - assertFalse(lp.isPrivateDnsActive()); - assertNull(lp.getPrivateDnsServerName()); - - // Validation event has untracked hostname - mDnsManager.updatePrivateDnsValidation( - new DnsManager.PrivateDnsValidationUpdate(TEST_NETID, - InetAddress.parseNumericAddress("3.3.3.3"), "hostname", - VALIDATION_RESULT_SUCCESS)); - mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp); - assertFalse(lp.isPrivateDnsActive()); - assertNull(lp.getPrivateDnsServerName()); - - // Validation event failed - mDnsManager.updatePrivateDnsValidation( - new DnsManager.PrivateDnsValidationUpdate(TEST_NETID, - InetAddress.parseNumericAddress("3.3.3.3"), "", - VALIDATION_RESULT_FAILURE)); - mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp); - assertFalse(lp.isPrivateDnsActive()); - assertNull(lp.getPrivateDnsServerName()); - - // Network removed - mDnsManager.removeNetwork(new Network(TEST_NETID)); - mDnsManager.updatePrivateDnsValidation( - new DnsManager.PrivateDnsValidationUpdate(TEST_NETID, - InetAddress.parseNumericAddress("3.3.3.3"), "", VALIDATION_RESULT_SUCCESS)); - mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp); - assertFalse(lp.isPrivateDnsActive()); - assertNull(lp.getPrivateDnsServerName()); - - // Turn private DNS mode off - ConnectivitySettingsManager.setPrivateDnsMode(mCtx, PRIVATE_DNS_MODE_OFF); - mDnsManager.updatePrivateDns(new Network(TEST_NETID), - mDnsManager.getPrivateDnsConfig()); - mDnsManager.updateTransportsForNetwork(TEST_NETID, TEST_TRANSPORT_TYPES); - mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp); - mDnsManager.flushVmDnsCache(); - mDnsManager.updatePrivateDnsValidation( - new DnsManager.PrivateDnsValidationUpdate(TEST_NETID, - InetAddress.parseNumericAddress("3.3.3.3"), "", - VALIDATION_RESULT_SUCCESS)); - mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp); - assertFalse(lp.isPrivateDnsActive()); - assertNull(lp.getPrivateDnsServerName()); - } - - @Test - public void testOverrideDefaultMode() throws Exception { - // Hard-coded default is opportunistic mode. - final PrivateDnsConfig cfgAuto = DnsManager.getPrivateDnsConfig(mCtx); - assertTrue(cfgAuto.useTls); - assertEquals("", cfgAuto.hostname); - assertEquals(new InetAddress[0], cfgAuto.ips); - - // Pretend a gservices push sets the default to "off". - ConnectivitySettingsManager.setPrivateDnsDefaultMode(mCtx, PRIVATE_DNS_MODE_OFF); - final PrivateDnsConfig cfgOff = DnsManager.getPrivateDnsConfig(mCtx); - assertFalse(cfgOff.useTls); - assertEquals("", cfgOff.hostname); - assertEquals(new InetAddress[0], cfgOff.ips); - - // Strict mode still works. - ConnectivitySettingsManager.setPrivateDnsMode(mCtx, PRIVATE_DNS_MODE_PROVIDER_HOSTNAME); - ConnectivitySettingsManager.setPrivateDnsHostname(mCtx, "strictmode.com"); - final PrivateDnsConfig cfgStrict = DnsManager.getPrivateDnsConfig(mCtx); - assertTrue(cfgStrict.useTls); - assertEquals("strictmode.com", cfgStrict.hostname); - assertEquals(new InetAddress[0], cfgStrict.ips); - } - - @Test - public void testSendDnsConfiguration() throws Exception { - reset(mMockDnsResolver); - mDnsManager.updatePrivateDns(new Network(TEST_NETID), - mDnsManager.getPrivateDnsConfig()); - final LinkProperties lp = new LinkProperties(); - lp.setInterfaceName(TEST_IFACENAME); - lp.addDnsServer(InetAddress.getByName("3.3.3.3")); - lp.addDnsServer(InetAddress.getByName("4.4.4.4")); - mDnsManager.updateTransportsForNetwork(TEST_NETID, TEST_TRANSPORT_TYPES); - mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp); - mDnsManager.flushVmDnsCache(); - - final ArgumentCaptor resolverParamsParcelCaptor = - ArgumentCaptor.forClass(ResolverParamsParcel.class); - verify(mMockDnsResolver, times(1)).setResolverConfiguration( - resolverParamsParcelCaptor.capture()); - final ResolverParamsParcel actualParams = resolverParamsParcelCaptor.getValue(); - final ResolverParamsParcel expectedParams = new ResolverParamsParcel(); - expectedParams.netId = TEST_NETID; - expectedParams.sampleValiditySeconds = TEST_DEFAULT_SAMPLE_VALIDITY_SECONDS; - expectedParams.successThreshold = TEST_DEFAULT_SUCCESS_THRESHOLD_PERCENT; - expectedParams.minSamples = TEST_DEFAULT_MIN_SAMPLES; - expectedParams.maxSamples = TEST_DEFAULT_MAX_SAMPLES; - expectedParams.servers = new String[]{"3.3.3.3", "4.4.4.4"}; - expectedParams.domains = new String[]{}; - expectedParams.tlsName = ""; - expectedParams.tlsServers = new String[]{"3.3.3.3", "4.4.4.4"}; - expectedParams.transportTypes = TEST_TRANSPORT_TYPES; - expectedParams.resolverOptions = new ResolverOptionsParcel(); - assertResolverParamsEquals(actualParams, expectedParams); - } - - @Test - public void testTransportTypesEqual() throws Exception { - SparseArray ncTransTypes = MessageUtils.findMessageNames( - new Class[] { NetworkCapabilities.class }, new String[]{ "TRANSPORT_" }); - SparseArray dnsTransTypes = MessageUtils.findMessageNames( - new Class[] { IDnsResolver.class }, new String[]{ "TRANSPORT_" }); - assertEquals(0, MIN_TRANSPORT); - assertEquals(MAX_TRANSPORT + 1, ncTransTypes.size()); - // TRANSPORT_UNKNOWN in IDnsResolver is defined to -1 and only for resolver. - assertEquals("TRANSPORT_UNKNOWN", dnsTransTypes.get(-1)); - assertEquals(ncTransTypes.size(), dnsTransTypes.size() - 1); - for (int i = MIN_TRANSPORT; i < MAX_TRANSPORT; i++) { - String name = ncTransTypes.get(i, null); - assertNotNull("Could not find NetworkCapabilies.TRANSPORT_* constant equal to " - + i, name); - assertEquals(name, dnsTransTypes.get(i)); - } - } - - @Test - public void testGetPrivateDnsConfigForNetwork() throws Exception { - final Network network = new Network(TEST_NETID); - final InetAddress dnsAddr = InetAddressUtils.parseNumericAddress("3.3.3.3"); - final InetAddress[] tlsAddrs = new InetAddress[]{ - InetAddressUtils.parseNumericAddress("6.6.6.6"), - InetAddressUtils.parseNumericAddress("2001:db8:66:66::1") - }; - final String tlsName = "strictmode.com"; - LinkProperties lp = new LinkProperties(); - lp.addDnsServer(dnsAddr); - - // The PrivateDnsConfig map is empty, so the default PRIVATE_DNS_OFF is returned. - PrivateDnsConfig privateDnsCfg = mDnsManager.getPrivateDnsConfig(network); - assertFalse(privateDnsCfg.useTls); - assertEquals("", privateDnsCfg.hostname); - assertEquals(new InetAddress[0], privateDnsCfg.ips); - - // An entry with default PrivateDnsConfig is added to the PrivateDnsConfig map. - mDnsManager.updatePrivateDns(network, mDnsManager.getPrivateDnsConfig()); - mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp); - mDnsManager.updatePrivateDnsValidation( - new DnsManager.PrivateDnsValidationUpdate(TEST_NETID, dnsAddr, "", - VALIDATION_RESULT_SUCCESS)); - mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp); - privateDnsCfg = mDnsManager.getPrivateDnsConfig(network); - assertTrue(privateDnsCfg.useTls); - assertEquals("", privateDnsCfg.hostname); - assertEquals(new InetAddress[0], privateDnsCfg.ips); - - // The original entry is overwritten by a new PrivateDnsConfig. - mDnsManager.updatePrivateDns(network, new PrivateDnsConfig(tlsName, tlsAddrs)); - mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp); - privateDnsCfg = mDnsManager.getPrivateDnsConfig(network); - assertTrue(privateDnsCfg.useTls); - assertEquals(tlsName, privateDnsCfg.hostname); - assertEquals(tlsAddrs, privateDnsCfg.ips); - - // The network is removed, so the PrivateDnsConfig map becomes empty again. - mDnsManager.removeNetwork(network); - privateDnsCfg = mDnsManager.getPrivateDnsConfig(network); - assertFalse(privateDnsCfg.useTls); - assertEquals("", privateDnsCfg.hostname); - assertEquals(new InetAddress[0], privateDnsCfg.ips); - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/FullScoreTest.kt b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/FullScoreTest.kt deleted file mode 100644 index 45b575a4365d4..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/FullScoreTest.kt +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity - -import android.net.NetworkAgentConfig -import android.net.NetworkCapabilities -import android.net.NetworkScore.KEEP_CONNECTED_NONE -import android.text.TextUtils -import android.util.ArraySet -import androidx.test.filters.SmallTest -import androidx.test.runner.AndroidJUnit4 -import com.android.server.connectivity.FullScore.MAX_CS_MANAGED_POLICY -import com.android.server.connectivity.FullScore.POLICY_ACCEPT_UNVALIDATED -import com.android.server.connectivity.FullScore.POLICY_EVER_USER_SELECTED -import com.android.server.connectivity.FullScore.POLICY_IS_VALIDATED -import com.android.server.connectivity.FullScore.POLICY_IS_VPN -import org.junit.Test -import org.junit.runner.RunWith -import kotlin.collections.minOfOrNull -import kotlin.collections.maxOfOrNull -import kotlin.reflect.full.staticProperties -import kotlin.test.assertEquals -import kotlin.test.assertFailsWith -import kotlin.test.assertFalse -import kotlin.test.assertTrue - -@RunWith(AndroidJUnit4::class) -@SmallTest -class FullScoreTest { - // Convenience methods - fun FullScore.withPolicies( - validated: Boolean = false, - vpn: Boolean = false, - onceChosen: Boolean = false, - acceptUnvalidated: Boolean = false - ): FullScore { - val nac = NetworkAgentConfig.Builder().apply { - setUnvalidatedConnectivityAcceptable(acceptUnvalidated) - setExplicitlySelected(onceChosen) - }.build() - val nc = NetworkCapabilities.Builder().apply { - if (vpn) addTransportType(NetworkCapabilities.TRANSPORT_VPN) - if (validated) addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) - }.build() - return mixInScore(nc, nac, validated, false /* yieldToBadWifi */) - } - - @Test - fun testGetLegacyInt() { - val ns = FullScore(50, 0L /* policy */, KEEP_CONNECTED_NONE) - assertEquals(10, ns.legacyInt) // -40 penalty for not being validated - assertEquals(50, ns.legacyIntAsValidated) - - val vpnNs = FullScore(101, 0L /* policy */, KEEP_CONNECTED_NONE).withPolicies(vpn = true) - assertEquals(101, vpnNs.legacyInt) // VPNs are not subject to unvalidation penalty - assertEquals(101, vpnNs.legacyIntAsValidated) - assertEquals(101, vpnNs.withPolicies(validated = true).legacyInt) - assertEquals(101, vpnNs.withPolicies(validated = true).legacyIntAsValidated) - - val validatedNs = ns.withPolicies(validated = true) - assertEquals(50, validatedNs.legacyInt) // No penalty, this is validated - assertEquals(50, validatedNs.legacyIntAsValidated) - - val chosenNs = ns.withPolicies(onceChosen = true) - assertEquals(10, chosenNs.legacyInt) - assertEquals(100, chosenNs.legacyIntAsValidated) - assertEquals(10, chosenNs.withPolicies(acceptUnvalidated = true).legacyInt) - assertEquals(50, chosenNs.withPolicies(acceptUnvalidated = true).legacyIntAsValidated) - } - - @Test - fun testToString() { - val string = FullScore(10, 0L /* policy */, KEEP_CONNECTED_NONE) - .withPolicies(vpn = true, acceptUnvalidated = true).toString() - assertTrue(string.contains("Score(10"), string) - assertTrue(string.contains("ACCEPT_UNVALIDATED"), string) - assertTrue(string.contains("IS_VPN"), string) - assertFalse(string.contains("IS_VALIDATED"), string) - val foundNames = ArraySet() - getAllPolicies().forEach { - val name = FullScore.policyNameOf(it.get() as Int) - assertFalse(TextUtils.isEmpty(name)) - assertFalse(foundNames.contains(name)) - foundNames.add(name) - } - assertFailsWith { - FullScore.policyNameOf(MAX_CS_MANAGED_POLICY + 1) - } - } - - fun getAllPolicies() = Regex("POLICY_.*").let { nameRegex -> - FullScore::class.staticProperties.filter { it.name.matches(nameRegex) } - } - - @Test - fun testHasPolicy() { - val ns = FullScore(50, 0L /* policy */, KEEP_CONNECTED_NONE) - assertFalse(ns.hasPolicy(POLICY_IS_VALIDATED)) - assertFalse(ns.hasPolicy(POLICY_IS_VPN)) - assertFalse(ns.hasPolicy(POLICY_EVER_USER_SELECTED)) - assertFalse(ns.hasPolicy(POLICY_ACCEPT_UNVALIDATED)) - assertTrue(ns.withPolicies(validated = true).hasPolicy(POLICY_IS_VALIDATED)) - assertTrue(ns.withPolicies(vpn = true).hasPolicy(POLICY_IS_VPN)) - assertTrue(ns.withPolicies(onceChosen = true).hasPolicy(POLICY_EVER_USER_SELECTED)) - assertTrue(ns.withPolicies(acceptUnvalidated = true).hasPolicy(POLICY_ACCEPT_UNVALIDATED)) - } - - @Test - fun testMinMaxPolicyConstants() { - val policies = getAllPolicies() - - policies.forEach { policy -> - assertTrue(policy.get() as Int >= FullScore.MIN_CS_MANAGED_POLICY) - assertTrue(policy.get() as Int <= FullScore.MAX_CS_MANAGED_POLICY) - } - assertEquals(FullScore.MIN_CS_MANAGED_POLICY, - policies.minOfOrNull { it.get() as Int }) - assertEquals(FullScore.MAX_CS_MANAGED_POLICY, - policies.maxOfOrNull { it.get() as Int }) - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java deleted file mode 100644 index 70495cced5366..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java +++ /dev/null @@ -1,561 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import static com.android.server.connectivity.MetricsTestUtil.aLong; -import static com.android.server.connectivity.MetricsTestUtil.aString; -import static com.android.server.connectivity.MetricsTestUtil.aType; -import static com.android.server.connectivity.MetricsTestUtil.anInt; -import static com.android.server.connectivity.MetricsTestUtil.describeIpEvent; -import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.BLUETOOTH; -import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.CELLULAR; -import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityLog; -import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.MULTIPLE; -import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.WIFI; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import android.net.ConnectivityMetricsEvent; -import android.net.metrics.ApfProgramEvent; -import android.net.metrics.ApfStats; -import android.net.metrics.DefaultNetworkEvent; -import android.net.metrics.DhcpClientEvent; -import android.net.metrics.DhcpErrorEvent; -import android.net.metrics.IpManagerEvent; -import android.net.metrics.IpReachabilityEvent; -import android.net.metrics.NetworkEvent; -import android.net.metrics.RaEvent; -import android.net.metrics.ValidationProbeEvent; -import android.net.metrics.WakeupStats; -import android.test.suitebuilder.annotation.SmallTest; - -import androidx.test.runner.AndroidJUnit4; - -import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.Arrays; -import java.util.List; - -// TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto. -@RunWith(AndroidJUnit4.class) -@SmallTest -public class IpConnectivityEventBuilderTest { - - @Test - public void testLinkLayerInferrence() { - ConnectivityMetricsEvent ev = describeIpEvent( - aType(IpReachabilityEvent.class), - anInt(IpReachabilityEvent.NUD_FAILED)); - - String want = String.join("\n", - "dropped_events: 0", - "events <", - " if_name: \"\"", - " link_layer: 0", - " network_id: 0", - " time_ms: 1", - " transports: 0", - " ip_reachability_event <", - " event_type: 512", - " if_name: \"\"", - " >", - ">", - "version: 2\n"); - verifySerialization(want, ev); - - ev.netId = 123; - ev.transports = 3; // transports have priority for inferrence of link layer - ev.ifname = "wlan0"; - want = String.join("\n", - "dropped_events: 0", - "events <", - " if_name: \"\"", - String.format(" link_layer: %d", MULTIPLE), - " network_id: 123", - " time_ms: 1", - " transports: 3", - " ip_reachability_event <", - " event_type: 512", - " if_name: \"\"", - " >", - ">", - "version: 2\n"); - verifySerialization(want, ev); - - ev.transports = 1; - ev.ifname = null; - want = String.join("\n", - "dropped_events: 0", - "events <", - " if_name: \"\"", - String.format(" link_layer: %d", CELLULAR), - " network_id: 123", - " time_ms: 1", - " transports: 1", - " ip_reachability_event <", - " event_type: 512", - " if_name: \"\"", - " >", - ">", - "version: 2\n"); - verifySerialization(want, ev); - - ev.transports = 0; - ev.ifname = "not_inferred"; - want = String.join("\n", - "dropped_events: 0", - "events <", - " if_name: \"not_inferred\"", - " link_layer: 0", - " network_id: 123", - " time_ms: 1", - " transports: 0", - " ip_reachability_event <", - " event_type: 512", - " if_name: \"\"", - " >", - ">", - "version: 2\n"); - verifySerialization(want, ev); - - ev.ifname = "bt-pan"; - want = String.join("\n", - "dropped_events: 0", - "events <", - " if_name: \"\"", - String.format(" link_layer: %d", BLUETOOTH), - " network_id: 123", - " time_ms: 1", - " transports: 0", - " ip_reachability_event <", - " event_type: 512", - " if_name: \"\"", - " >", - ">", - "version: 2\n"); - verifySerialization(want, ev); - - ev.ifname = "rmnet_ipa0"; - want = String.join("\n", - "dropped_events: 0", - "events <", - " if_name: \"\"", - String.format(" link_layer: %d", CELLULAR), - " network_id: 123", - " time_ms: 1", - " transports: 0", - " ip_reachability_event <", - " event_type: 512", - " if_name: \"\"", - " >", - ">", - "version: 2\n"); - verifySerialization(want, ev); - - ev.ifname = "wlan0"; - want = String.join("\n", - "dropped_events: 0", - "events <", - " if_name: \"\"", - String.format(" link_layer: %d", WIFI), - " network_id: 123", - " time_ms: 1", - " transports: 0", - " ip_reachability_event <", - " event_type: 512", - " if_name: \"\"", - " >", - ">", - "version: 2\n"); - verifySerialization(want, ev); - } - - @Test - public void testDefaultNetworkEventSerialization() { - DefaultNetworkEvent ev = new DefaultNetworkEvent(1001); - ev.netId = 102; - ev.transports = 2; - ev.previousTransports = 4; - ev.ipv4 = true; - ev.initialScore = 20; - ev.finalScore = 60; - ev.durationMs = 54; - ev.validatedMs = 27; - - String want = String.join("\n", - "dropped_events: 0", - "events <", - " if_name: \"\"", - " link_layer: 4", - " network_id: 102", - " time_ms: 0", - " transports: 2", - " default_network_event <", - " default_network_duration_ms: 54", - " final_score: 60", - " initial_score: 20", - " ip_support: 1", - " no_default_network_duration_ms: 0", - " previous_default_network_link_layer: 1", - " previous_network_ip_support: 0", - " validation_duration_ms: 27", - " >", - ">", - "version: 2\n"); - - verifySerialization(want, IpConnectivityEventBuilder.toProto(ev)); - } - - @Test - public void testDhcpClientEventSerialization() { - ConnectivityMetricsEvent ev = describeIpEvent( - aType(DhcpClientEvent.class), - aString("SomeState"), - anInt(192)); - - String want = String.join("\n", - "dropped_events: 0", - "events <", - " if_name: \"\"", - " link_layer: 0", - " network_id: 0", - " time_ms: 1", - " transports: 0", - " dhcp_event <", - " duration_ms: 192", - " if_name: \"\"", - " state_transition: \"SomeState\"", - " >", - ">", - "version: 2\n"); - - verifySerialization(want, ev); - } - - @Test - public void testDhcpErrorEventSerialization() { - ConnectivityMetricsEvent ev = describeIpEvent( - aType(DhcpErrorEvent.class), - anInt(DhcpErrorEvent.L4_NOT_UDP)); - - String want = String.join("\n", - "dropped_events: 0", - "events <", - " if_name: \"\"", - " link_layer: 0", - " network_id: 0", - " time_ms: 1", - " transports: 0", - " dhcp_event <", - " duration_ms: 0", - " if_name: \"\"", - " error_code: 50397184", - " >", - ">", - "version: 2\n"); - - verifySerialization(want, ev); - } - - @Test - public void testIpManagerEventSerialization() { - ConnectivityMetricsEvent ev = describeIpEvent( - aType(IpManagerEvent.class), - anInt(IpManagerEvent.PROVISIONING_OK), - aLong(5678)); - - String want = String.join("\n", - "dropped_events: 0", - "events <", - " if_name: \"\"", - " link_layer: 0", - " network_id: 0", - " time_ms: 1", - " transports: 0", - " ip_provisioning_event <", - " event_type: 1", - " if_name: \"\"", - " latency_ms: 5678", - " >", - ">", - "version: 2\n"); - - verifySerialization(want, ev); - } - - @Test - public void testIpReachabilityEventSerialization() { - ConnectivityMetricsEvent ev = describeIpEvent( - aType(IpReachabilityEvent.class), - anInt(IpReachabilityEvent.NUD_FAILED)); - - String want = String.join("\n", - "dropped_events: 0", - "events <", - " if_name: \"\"", - " link_layer: 0", - " network_id: 0", - " time_ms: 1", - " transports: 0", - " ip_reachability_event <", - " event_type: 512", - " if_name: \"\"", - " >", - ">", - "version: 2\n"); - - verifySerialization(want, ev); - } - - @Test - public void testNetworkEventSerialization() { - ConnectivityMetricsEvent ev = describeIpEvent( - aType(NetworkEvent.class), - anInt(5), - aLong(20410)); - - String want = String.join("\n", - "dropped_events: 0", - "events <", - " if_name: \"\"", - " link_layer: 0", - " network_id: 0", - " time_ms: 1", - " transports: 0", - " network_event <", - " event_type: 5", - " latency_ms: 20410", - " >", - ">", - "version: 2\n"); - - verifySerialization(want, ev); - } - - @Test - public void testValidationProbeEventSerialization() { - ConnectivityMetricsEvent ev = describeIpEvent( - aType(ValidationProbeEvent.class), - aLong(40730), - anInt(ValidationProbeEvent.PROBE_HTTP), - anInt(204)); - - String want = String.join("\n", - "dropped_events: 0", - "events <", - " if_name: \"\"", - " link_layer: 0", - " network_id: 0", - " time_ms: 1", - " transports: 0", - " validation_probe_event <", - " latency_ms: 40730", - " probe_result: 204", - " probe_type: 1", - " >", - ">", - "version: 2\n"); - - verifySerialization(want, ev); - } - - @Test - public void testApfProgramEventSerialization() { - ConnectivityMetricsEvent ev = describeIpEvent( - aType(ApfProgramEvent.class), - aLong(200), - aLong(18), - anInt(7), - anInt(9), - anInt(2048), - anInt(3)); - - String want = String.join("\n", - "dropped_events: 0", - "events <", - " if_name: \"\"", - " link_layer: 0", - " network_id: 0", - " time_ms: 1", - " transports: 0", - " apf_program_event <", - " current_ras: 9", - " drop_multicast: true", - " effective_lifetime: 18", - " filtered_ras: 7", - " has_ipv4_addr: true", - " lifetime: 200", - " program_length: 2048", - " >", - ">", - "version: 2\n"); - - verifySerialization(want, ev); - } - - @Test - public void testApfStatsSerialization() { - ConnectivityMetricsEvent ev = describeIpEvent( - aType(ApfStats.class), - aLong(45000), - anInt(10), - anInt(2), - anInt(2), - anInt(1), - anInt(2), - anInt(4), - anInt(7), - anInt(3), - anInt(2048)); - - String want = String.join("\n", - "dropped_events: 0", - "events <", - " if_name: \"\"", - " link_layer: 0", - " network_id: 0", - " time_ms: 1", - " transports: 0", - " apf_statistics <", - " dropped_ras: 2", - " duration_ms: 45000", - " matching_ras: 2", - " max_program_size: 2048", - " parse_errors: 2", - " program_updates: 4", - " program_updates_all: 7", - " program_updates_allowing_multicast: 3", - " received_ras: 10", - " total_packet_dropped: 0", - " total_packet_processed: 0", - " zero_lifetime_ras: 1", - " >", - ">", - "version: 2\n"); - - verifySerialization(want, ev); - } - - @Test - public void testRaEventSerialization() { - ConnectivityMetricsEvent ev = describeIpEvent( - aType(RaEvent.class), - aLong(2000), - aLong(400), - aLong(300), - aLong(-1), - aLong(1000), - aLong(-1)); - - String want = String.join("\n", - "dropped_events: 0", - "events <", - " if_name: \"\"", - " link_layer: 0", - " network_id: 0", - " time_ms: 1", - " transports: 0", - " ra_event <", - " dnssl_lifetime: -1", - " prefix_preferred_lifetime: 300", - " prefix_valid_lifetime: 400", - " rdnss_lifetime: 1000", - " route_info_lifetime: -1", - " router_lifetime: 2000", - " >", - ">", - "version: 2\n"); - - verifySerialization(want, ev); - } - - @Test - public void testWakeupStatsSerialization() { - WakeupStats stats = new WakeupStats("wlan0"); - stats.totalWakeups = 14; - stats.applicationWakeups = 5; - stats.nonApplicationWakeups = 1; - stats.rootWakeups = 2; - stats.systemWakeups = 3; - stats.noUidWakeups = 3; - stats.l2UnicastCount = 5; - stats.l2MulticastCount = 1; - stats.l2BroadcastCount = 2; - stats.ethertypes.put(0x800, 3); - stats.ethertypes.put(0x86dd, 3); - stats.ipNextHeaders.put(6, 5); - - - IpConnectivityEvent got = IpConnectivityEventBuilder.toProto(stats); - String want = String.join("\n", - "dropped_events: 0", - "events <", - " if_name: \"\"", - " link_layer: 4", - " network_id: 0", - " time_ms: 0", - " transports: 0", - " wakeup_stats <", - " application_wakeups: 5", - " duration_sec: 0", - " ethertype_counts <", - " key: 2048", - " value: 3", - " >", - " ethertype_counts <", - " key: 34525", - " value: 3", - " >", - " ip_next_header_counts <", - " key: 6", - " value: 5", - " >", - " l2_broadcast_count: 2", - " l2_multicast_count: 1", - " l2_unicast_count: 5", - " no_uid_wakeups: 3", - " non_application_wakeups: 1", - " root_wakeups: 2", - " system_wakeups: 3", - " total_wakeups: 14", - " >", - ">", - "version: 2\n"); - - verifySerialization(want, got); - } - - static void verifySerialization(String want, ConnectivityMetricsEvent... input) { - List protoInput = - IpConnectivityEventBuilder.toProto(Arrays.asList(input)); - verifySerialization(want, protoInput.toArray(new IpConnectivityEvent[0])); - } - - static void verifySerialization(String want, IpConnectivityEvent... input) { - try { - byte[] got = IpConnectivityEventBuilder.serialize(0, Arrays.asList(input)); - IpConnectivityLog log = IpConnectivityLog.parseFrom(got); - assertEquals(want, log.toString()); - } catch (Exception e) { - fail(e.toString()); - } - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/IpConnectivityMetricsTest.java deleted file mode 100644 index 8b072c49de826..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/IpConnectivityMetricsTest.java +++ /dev/null @@ -1,645 +0,0 @@ -/* - * Copyright (C) 2016, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import static android.net.metrics.INetdEventListener.EVENT_GETADDRINFO; -import static android.net.metrics.INetdEventListener.EVENT_GETHOSTBYNAME; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.ConnectivityMetricsEvent; -import android.net.IIpConnectivityMetrics; -import android.net.IpPrefix; -import android.net.LinkAddress; -import android.net.LinkProperties; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.RouteInfo; -import android.net.metrics.ApfProgramEvent; -import android.net.metrics.ApfStats; -import android.net.metrics.DhcpClientEvent; -import android.net.metrics.IpConnectivityLog; -import android.net.metrics.IpManagerEvent; -import android.net.metrics.IpReachabilityEvent; -import android.net.metrics.RaEvent; -import android.net.metrics.ValidationProbeEvent; -import android.os.Parcelable; -import android.system.OsConstants; -import android.test.suitebuilder.annotation.SmallTest; -import android.util.Base64; - -import androidx.test.runner.AndroidJUnit4; - -import com.android.internal.util.BitUtils; -import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.io.PrintWriter; -import java.io.StringWriter; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class IpConnectivityMetricsTest { - static final IpReachabilityEvent FAKE_EV = - new IpReachabilityEvent(IpReachabilityEvent.NUD_FAILED); - - private static final String EXAMPLE_IPV4 = "192.0.2.1"; - private static final String EXAMPLE_IPV6 = "2001:db8:1200::2:1"; - - private static final byte[] MAC_ADDR = - {(byte)0x84, (byte)0xc9, (byte)0xb2, (byte)0x6a, (byte)0xed, (byte)0x4b}; - - @Mock Context mCtx; - @Mock IIpConnectivityMetrics mMockService; - @Mock ConnectivityManager mCm; - - IpConnectivityMetrics mService; - NetdEventListenerService mNetdListener; - private static final NetworkCapabilities CAPABILITIES_WIFI = new NetworkCapabilities.Builder() - .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) - .build(); - private static final NetworkCapabilities CAPABILITIES_CELL = new NetworkCapabilities.Builder() - .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) - .build(); - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mService = new IpConnectivityMetrics(mCtx, (ctx) -> 2000); - mNetdListener = new NetdEventListenerService(mCm); - mService.mNetdListener = mNetdListener; - } - - @Test - public void testBufferFlushing() { - String output1 = getdump("flush"); - assertEquals("", output1); - - new IpConnectivityLog(mService.impl).log(1, FAKE_EV); - String output2 = getdump("flush"); - assertFalse("".equals(output2)); - - String output3 = getdump("flush"); - assertEquals("", output3); - } - - @Test - public void testRateLimiting() { - final IpConnectivityLog logger = new IpConnectivityLog(mService.impl); - final ApfProgramEvent ev = new ApfProgramEvent.Builder().build(); - final long fakeTimestamp = 1; - - int attempt = 100; // More than burst quota, but less than buffer size. - for (int i = 0; i < attempt; i++) { - logger.log(ev); - } - - String output1 = getdump("flush"); - assertFalse("".equals(output1)); - - for (int i = 0; i < attempt; i++) { - assertFalse("expected event to be dropped", logger.log(fakeTimestamp, ev)); - } - - String output2 = getdump("flush"); - assertEquals("", output2); - } - - private void logDefaultNetworkEvent(long timeMs, NetworkAgentInfo nai, - NetworkAgentInfo oldNai) { - final Network network = (nai != null) ? nai.network() : null; - final int score = (nai != null) ? nai.getCurrentScore() : 0; - final boolean validated = (nai != null) ? nai.lastValidated : false; - final LinkProperties lp = (nai != null) ? nai.linkProperties : null; - final NetworkCapabilities nc = (nai != null) ? nai.networkCapabilities : null; - - final Network prevNetwork = (oldNai != null) ? oldNai.network() : null; - final int prevScore = (oldNai != null) ? oldNai.getCurrentScore() : 0; - final LinkProperties prevLp = (oldNai != null) ? oldNai.linkProperties : null; - final NetworkCapabilities prevNc = (oldNai != null) ? oldNai.networkCapabilities : null; - - mService.mDefaultNetworkMetrics.logDefaultNetworkEvent(timeMs, network, score, validated, - lp, nc, prevNetwork, prevScore, prevLp, prevNc); - } - @Test - public void testDefaultNetworkEvents() throws Exception { - final long cell = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_CELLULAR}); - final long wifi = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_WIFI}); - - NetworkAgentInfo[][] defaultNetworks = { - // nothing -> cell - {null, makeNai(100, 10, false, true, cell)}, - // cell -> wifi - {makeNai(100, 50, true, true, cell), makeNai(101, 20, true, false, wifi)}, - // wifi -> nothing - {makeNai(101, 60, true, false, wifi), null}, - // nothing -> cell - {null, makeNai(102, 10, true, true, cell)}, - // cell -> wifi - {makeNai(102, 50, true, true, cell), makeNai(103, 20, true, false, wifi)}, - }; - - long timeMs = mService.mDefaultNetworkMetrics.creationTimeMs; - long durationMs = 1001; - for (NetworkAgentInfo[] pair : defaultNetworks) { - timeMs += durationMs; - durationMs += durationMs; - logDefaultNetworkEvent(timeMs, pair[1], pair[0]); - } - - String want = String.join("\n", - "dropped_events: 0", - "events <", - " if_name: \"\"", - " link_layer: 5", - " network_id: 0", - " time_ms: 0", - " transports: 0", - " default_network_event <", - " default_network_duration_ms: 1001", - " final_score: 0", - " initial_score: 0", - " ip_support: 0", - " no_default_network_duration_ms: 0", - " previous_default_network_link_layer: 0", - " previous_network_ip_support: 0", - " validation_duration_ms: 0", - " >", - ">", - "events <", - " if_name: \"\"", - " link_layer: 2", - " network_id: 100", - " time_ms: 0", - " transports: 1", - " default_network_event <", - " default_network_duration_ms: 2002", - " final_score: 50", - " initial_score: 10", - " ip_support: 3", - " no_default_network_duration_ms: 0", - " previous_default_network_link_layer: 0", - " previous_network_ip_support: 0", - " validation_duration_ms: 2002", - " >", - ">", - "events <", - " if_name: \"\"", - " link_layer: 4", - " network_id: 101", - " time_ms: 0", - " transports: 2", - " default_network_event <", - " default_network_duration_ms: 4004", - " final_score: 60", - " initial_score: 20", - " ip_support: 1", - " no_default_network_duration_ms: 0", - " previous_default_network_link_layer: 2", - " previous_network_ip_support: 0", - " validation_duration_ms: 4004", - " >", - ">", - "events <", - " if_name: \"\"", - " link_layer: 5", - " network_id: 0", - " time_ms: 0", - " transports: 0", - " default_network_event <", - " default_network_duration_ms: 8008", - " final_score: 0", - " initial_score: 0", - " ip_support: 0", - " no_default_network_duration_ms: 0", - " previous_default_network_link_layer: 4", - " previous_network_ip_support: 0", - " validation_duration_ms: 0", - " >", - ">", - "events <", - " if_name: \"\"", - " link_layer: 2", - " network_id: 102", - " time_ms: 0", - " transports: 1", - " default_network_event <", - " default_network_duration_ms: 16016", - " final_score: 50", - " initial_score: 10", - " ip_support: 3", - " no_default_network_duration_ms: 0", - " previous_default_network_link_layer: 4", - " previous_network_ip_support: 0", - " validation_duration_ms: 16016", - " >", - ">", - "version: 2\n"); - - verifySerialization(want, getdump("flush")); - } - - @Test - public void testEndToEndLogging() throws Exception { - // TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto. - IpConnectivityLog logger = new IpConnectivityLog(mService.impl); - - ApfStats apfStats = new ApfStats.Builder() - .setDurationMs(45000) - .setReceivedRas(10) - .setMatchingRas(2) - .setDroppedRas(2) - .setParseErrors(2) - .setZeroLifetimeRas(1) - .setProgramUpdates(4) - .setProgramUpdatesAll(7) - .setProgramUpdatesAllowingMulticast(3) - .setMaxProgramSize(2048) - .build(); - - final ValidationProbeEvent validationEv = new ValidationProbeEvent.Builder() - .setDurationMs(40730) - .setProbeType(ValidationProbeEvent.PROBE_HTTP, true) - .setReturnCode(204) - .build(); - - final DhcpClientEvent event = new DhcpClientEvent.Builder() - .setMsg("SomeState") - .setDurationMs(192) - .build(); - Parcelable[] events = { - new IpReachabilityEvent(IpReachabilityEvent.NUD_FAILED), event, - new IpManagerEvent(IpManagerEvent.PROVISIONING_OK, 5678), - validationEv, - apfStats, - new RaEvent(2000, 400, 300, -1, 1000, -1) - }; - - for (int i = 0; i < events.length; i++) { - ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent(); - ev.timestamp = 100 * (i + 1); - ev.ifname = "wlan0"; - ev.data = events[i]; - logger.log(ev); - } - - // netId, errno, latency, destination - connectEvent(100, OsConstants.EALREADY, 0, EXAMPLE_IPV4); - connectEvent(100, OsConstants.EINPROGRESS, 0, EXAMPLE_IPV6); - connectEvent(100, 0, 110, EXAMPLE_IPV4); - connectEvent(101, 0, 23, EXAMPLE_IPV4); - connectEvent(101, 0, 45, EXAMPLE_IPV6); - connectEvent(100, OsConstants.EAGAIN, 0, EXAMPLE_IPV4); - - // netId, type, return code, latency - dnsEvent(100, EVENT_GETADDRINFO, 0, 3456); - dnsEvent(100, EVENT_GETADDRINFO, 3, 45); - dnsEvent(100, EVENT_GETHOSTBYNAME, 0, 638); - dnsEvent(101, EVENT_GETADDRINFO, 0, 56); - dnsEvent(101, EVENT_GETHOSTBYNAME, 0, 34); - - // iface, uid - final byte[] mac = {0x48, 0x7c, 0x2b, 0x6a, 0x3e, 0x4b}; - final String srcIp = "192.168.2.1"; - final String dstIp = "192.168.2.23"; - final int sport = 2356; - final int dport = 13489; - final long now = 1001L; - final int v4 = 0x800; - final int tcp = 6; - final int udp = 17; - wakeupEvent("wlan0", 1000, v4, tcp, mac, srcIp, dstIp, sport, dport, 1001L); - wakeupEvent("wlan0", 10123, v4, tcp, mac, srcIp, dstIp, sport, dport, 1001L); - wakeupEvent("wlan0", 1000, v4, udp, mac, srcIp, dstIp, sport, dport, 1001L); - wakeupEvent("wlan0", 10008, v4, udp, mac, srcIp, dstIp, sport, dport, 1001L); - wakeupEvent("wlan0", -1, v4, udp, mac, srcIp, dstIp, sport, dport, 1001L); - wakeupEvent("wlan0", 10008, v4, tcp, mac, srcIp, dstIp, sport, dport, 1001L); - - long timeMs = mService.mDefaultNetworkMetrics.creationTimeMs; - final long cell = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_CELLULAR}); - final long wifi = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_WIFI}); - NetworkAgentInfo cellNai = makeNai(100, 50, false, true, cell); - NetworkAgentInfo wifiNai = makeNai(101, 60, true, false, wifi); - logDefaultNetworkEvent(timeMs + 200L, cellNai, null); - logDefaultNetworkEvent(timeMs + 300L, wifiNai, cellNai); - - String want = String.join("\n", - "dropped_events: 0", - "events <", - " if_name: \"\"", - " link_layer: 4", - " network_id: 0", - " time_ms: 100", - " transports: 0", - " ip_reachability_event <", - " event_type: 512", - " if_name: \"\"", - " >", - ">", - "events <", - " if_name: \"\"", - " link_layer: 4", - " network_id: 0", - " time_ms: 200", - " transports: 0", - " dhcp_event <", - " duration_ms: 192", - " if_name: \"\"", - " state_transition: \"SomeState\"", - " >", - ">", - "events <", - " if_name: \"\"", - " link_layer: 4", - " network_id: 0", - " time_ms: 300", - " transports: 0", - " ip_provisioning_event <", - " event_type: 1", - " if_name: \"\"", - " latency_ms: 5678", - " >", - ">", - "events <", - " if_name: \"\"", - " link_layer: 4", - " network_id: 0", - " time_ms: 400", - " transports: 0", - " validation_probe_event <", - " latency_ms: 40730", - " probe_result: 204", - " probe_type: 257", - " >", - ">", - "events <", - " if_name: \"\"", - " link_layer: 4", - " network_id: 0", - " time_ms: 500", - " transports: 0", - " apf_statistics <", - " dropped_ras: 2", - " duration_ms: 45000", - " matching_ras: 2", - " max_program_size: 2048", - " parse_errors: 2", - " program_updates: 4", - " program_updates_all: 7", - " program_updates_allowing_multicast: 3", - " received_ras: 10", - " total_packet_dropped: 0", - " total_packet_processed: 0", - " zero_lifetime_ras: 1", - " >", - ">", - "events <", - " if_name: \"\"", - " link_layer: 4", - " network_id: 0", - " time_ms: 600", - " transports: 0", - " ra_event <", - " dnssl_lifetime: -1", - " prefix_preferred_lifetime: 300", - " prefix_valid_lifetime: 400", - " rdnss_lifetime: 1000", - " route_info_lifetime: -1", - " router_lifetime: 2000", - " >", - ">", - "events <", - " if_name: \"\"", - " link_layer: 5", - " network_id: 0", - " time_ms: 0", - " transports: 0", - " default_network_event <", - " default_network_duration_ms: 200", - " final_score: 0", - " initial_score: 0", - " ip_support: 0", - " no_default_network_duration_ms: 0", - " previous_default_network_link_layer: 0", - " previous_network_ip_support: 0", - " validation_duration_ms: 0", - " >", - ">", - "events <", - " if_name: \"\"", - " link_layer: 2", - " network_id: 100", - " time_ms: 0", - " transports: 1", - " default_network_event <", - " default_network_duration_ms: 100", - " final_score: 50", - " initial_score: 50", - " ip_support: 2", - " no_default_network_duration_ms: 0", - " previous_default_network_link_layer: 0", - " previous_network_ip_support: 0", - " validation_duration_ms: 100", - " >", - ">", - "events <", - " if_name: \"\"", - " link_layer: 4", - " network_id: 100", - " time_ms: 0", - " transports: 2", - " connect_statistics <", - " connect_blocking_count: 1", - " connect_count: 3", - " errnos_counters <", - " key: 11", - " value: 1", - " >", - " ipv6_addr_count: 1", - " latencies_ms: 110", - " >", - ">", - "events <", - " if_name: \"\"", - " link_layer: 2", - " network_id: 101", - " time_ms: 0", - " transports: 1", - " connect_statistics <", - " connect_blocking_count: 2", - " connect_count: 2", - " ipv6_addr_count: 1", - " latencies_ms: 23", - " latencies_ms: 45", - " >", - ">", - "events <", - " if_name: \"\"", - " link_layer: 4", - " network_id: 100", - " time_ms: 0", - " transports: 2", - " dns_lookup_batch <", - " event_types: 1", - " event_types: 1", - " event_types: 2", - " getaddrinfo_error_count: 0", - " getaddrinfo_query_count: 0", - " gethostbyname_error_count: 0", - " gethostbyname_query_count: 0", - " latencies_ms: 3456", - " latencies_ms: 45", - " latencies_ms: 638", - " return_codes: 0", - " return_codes: 3", - " return_codes: 0", - " >", - ">", - "events <", - " if_name: \"\"", - " link_layer: 2", - " network_id: 101", - " time_ms: 0", - " transports: 1", - " dns_lookup_batch <", - " event_types: 1", - " event_types: 2", - " getaddrinfo_error_count: 0", - " getaddrinfo_query_count: 0", - " gethostbyname_error_count: 0", - " gethostbyname_query_count: 0", - " latencies_ms: 56", - " latencies_ms: 34", - " return_codes: 0", - " return_codes: 0", - " >", - ">", - "events <", - " if_name: \"\"", - " link_layer: 4", - " network_id: 0", - " time_ms: 0", - " transports: 0", - " wakeup_stats <", - " application_wakeups: 3", - " duration_sec: 0", - " ethertype_counts <", - " key: 2048", - " value: 6", - " >", - " ip_next_header_counts <", - " key: 6", - " value: 3", - " >", - " ip_next_header_counts <", - " key: 17", - " value: 3", - " >", - " l2_broadcast_count: 0", - " l2_multicast_count: 0", - " l2_unicast_count: 6", - " no_uid_wakeups: 1", - " non_application_wakeups: 0", - " root_wakeups: 0", - " system_wakeups: 2", - " total_wakeups: 6", - " >", - ">", - "version: 2\n"); - - verifySerialization(want, getdump("flush")); - } - - String getdump(String ... command) { - StringWriter buffer = new StringWriter(); - PrintWriter writer = new PrintWriter(buffer); - mService.impl.dump(null, writer, command); - return buffer.toString(); - } - - private void setCapabilities(int netId) { - final ArgumentCaptor networkCallback = - ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class); - verify(mCm).registerNetworkCallback(any(), networkCallback.capture()); - networkCallback.getValue().onCapabilitiesChanged(new Network(netId), - netId == 100 ? CAPABILITIES_WIFI : CAPABILITIES_CELL); - } - - void connectEvent(int netId, int error, int latencyMs, String ipAddr) throws Exception { - setCapabilities(netId); - mNetdListener.onConnectEvent(netId, error, latencyMs, ipAddr, 80, 1); - } - - void dnsEvent(int netId, int type, int result, int latency) throws Exception { - setCapabilities(netId); - mNetdListener.onDnsEvent(netId, type, result, latency, "", null, 0, 0); - } - - void wakeupEvent(String iface, int uid, int ether, int ip, byte[] mac, String srcIp, - String dstIp, int sport, int dport, long now) throws Exception { - String prefix = NetdEventListenerService.WAKEUP_EVENT_IFACE_PREFIX + iface; - mNetdListener.onWakeupEvent(prefix, uid, ether, ip, mac, srcIp, dstIp, sport, dport, now); - } - - NetworkAgentInfo makeNai(int netId, int score, boolean ipv4, boolean ipv6, long transports) { - NetworkAgentInfo nai = mock(NetworkAgentInfo.class); - when(nai.network()).thenReturn(new Network(netId)); - when(nai.getCurrentScore()).thenReturn(score); - nai.linkProperties = new LinkProperties(); - nai.networkCapabilities = new NetworkCapabilities(); - nai.lastValidated = true; - for (int t : BitUtils.unpackBits(transports)) { - nai.networkCapabilities.addTransportType(t); - } - if (ipv4) { - nai.linkProperties.addLinkAddress(new LinkAddress("192.0.2.12/24")); - nai.linkProperties.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0"))); - } - if (ipv6) { - nai.linkProperties.addLinkAddress(new LinkAddress("2001:db8:dead:beef:f00::a0/64")); - nai.linkProperties.addRoute(new RouteInfo(new IpPrefix("::/0"))); - } - return nai; - } - - - - static void verifySerialization(String want, String output) { - try { - byte[] got = Base64.decode(output, Base64.DEFAULT); - IpConnectivityLogClass.IpConnectivityLog log = - IpConnectivityLogClass.IpConnectivityLog.parseFrom(got); - assertEquals(want, log.toString()); - } catch (Exception e) { - fail(e.toString()); - } - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/LingerMonitorTest.java b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/LingerMonitorTest.java deleted file mode 100644 index 36e229d8aa731..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/LingerMonitorTest.java +++ /dev/null @@ -1,395 +0,0 @@ -/* - * Copyright (C) 2016, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyBoolean; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.app.PendingIntent; -import android.content.Context; -import android.content.res.Resources; -import android.net.ConnectivityManager; -import android.net.ConnectivityResources; -import android.net.IDnsResolver; -import android.net.INetd; -import android.net.LinkProperties; -import android.net.Network; -import android.net.NetworkAgentConfig; -import android.net.NetworkCapabilities; -import android.net.NetworkInfo; -import android.net.NetworkProvider; -import android.net.NetworkScore; -import android.os.Binder; -import android.text.format.DateUtils; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.connectivity.resources.R; -import com.android.server.ConnectivityService; -import com.android.server.connectivity.NetworkNotificationManager.NotificationType; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class LingerMonitorTest { - static final String CELLULAR = "CELLULAR"; - static final String WIFI = "WIFI"; - - static final long LOW_RATE_LIMIT = DateUtils.MINUTE_IN_MILLIS; - static final long HIGH_RATE_LIMIT = 0; - - static final int LOW_DAILY_LIMIT = 2; - static final int HIGH_DAILY_LIMIT = 1000; - - private static final int TEST_LINGER_DELAY_MS = 400; - - LingerMonitor mMonitor; - - @Mock ConnectivityService mConnService; - @Mock IDnsResolver mDnsResolver; - @Mock INetd mNetd; - @Mock Context mCtx; - @Mock NetworkNotificationManager mNotifier; - @Mock Resources mResources; - @Mock QosCallbackTracker mQosCallbackTracker; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - when(mCtx.getResources()).thenReturn(mResources); - when(mCtx.getPackageName()).thenReturn("com.android.server.connectivity"); - ConnectivityResources.setResourcesContextForTest(mCtx); - - mMonitor = new TestableLingerMonitor(mCtx, mNotifier, HIGH_DAILY_LIMIT, HIGH_RATE_LIMIT); - } - - @After - public void tearDown() { - ConnectivityResources.setResourcesContextForTest(null); - } - - @Test - public void testTransitions() { - setNotificationSwitch(transition(WIFI, CELLULAR)); - NetworkAgentInfo nai1 = wifiNai(100); - NetworkAgentInfo nai2 = cellNai(101); - - assertTrue(mMonitor.isNotificationEnabled(nai1, nai2)); - assertFalse(mMonitor.isNotificationEnabled(nai2, nai1)); - } - - @Test - public void testNotificationOnLinger() { - setNotificationSwitch(transition(WIFI, CELLULAR)); - setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); - NetworkAgentInfo from = wifiNai(100); - NetworkAgentInfo to = cellNai(101); - - mMonitor.noteLingerDefaultNetwork(from, to); - verifyNotification(from, to); - } - - @Test - public void testToastOnLinger() { - setNotificationSwitch(transition(WIFI, CELLULAR)); - setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); - NetworkAgentInfo from = wifiNai(100); - NetworkAgentInfo to = cellNai(101); - - mMonitor.noteLingerDefaultNetwork(from, to); - verifyToast(from, to); - } - - @Test - public void testNotificationClearedAfterDisconnect() { - setNotificationSwitch(transition(WIFI, CELLULAR)); - setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); - NetworkAgentInfo from = wifiNai(100); - NetworkAgentInfo to = cellNai(101); - - mMonitor.noteLingerDefaultNetwork(from, to); - verifyNotification(from, to); - - mMonitor.noteDisconnect(to); - verify(mNotifier, times(1)).clearNotification(100); - } - - @Test - public void testNotificationClearedAfterSwitchingBack() { - setNotificationSwitch(transition(WIFI, CELLULAR)); - setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); - NetworkAgentInfo from = wifiNai(100); - NetworkAgentInfo to = cellNai(101); - - mMonitor.noteLingerDefaultNetwork(from, to); - verifyNotification(from, to); - - mMonitor.noteLingerDefaultNetwork(to, from); - verify(mNotifier, times(1)).clearNotification(100); - } - - @Test - public void testUniqueToast() { - setNotificationSwitch(transition(WIFI, CELLULAR)); - setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); - NetworkAgentInfo from = wifiNai(100); - NetworkAgentInfo to = cellNai(101); - - mMonitor.noteLingerDefaultNetwork(from, to); - verifyToast(from, to); - - mMonitor.noteLingerDefaultNetwork(to, from); - verify(mNotifier, times(1)).clearNotification(100); - - reset(mNotifier); - mMonitor.noteLingerDefaultNetwork(from, to); - verifyNoNotifications(); - } - - @Test - public void testMultipleNotifications() { - setNotificationSwitch(transition(WIFI, CELLULAR)); - setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); - NetworkAgentInfo wifi1 = wifiNai(100); - NetworkAgentInfo wifi2 = wifiNai(101); - NetworkAgentInfo cell = cellNai(102); - - mMonitor.noteLingerDefaultNetwork(wifi1, cell); - verifyNotification(wifi1, cell); - - mMonitor.noteLingerDefaultNetwork(cell, wifi2); - verify(mNotifier, times(1)).clearNotification(100); - - reset(mNotifier); - mMonitor.noteLingerDefaultNetwork(wifi2, cell); - verifyNotification(wifi2, cell); - } - - @Test - public void testRateLimiting() throws InterruptedException { - mMonitor = new TestableLingerMonitor(mCtx, mNotifier, HIGH_DAILY_LIMIT, LOW_RATE_LIMIT); - - setNotificationSwitch(transition(WIFI, CELLULAR)); - setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); - NetworkAgentInfo wifi1 = wifiNai(100); - NetworkAgentInfo wifi2 = wifiNai(101); - NetworkAgentInfo wifi3 = wifiNai(102); - NetworkAgentInfo cell = cellNai(103); - - mMonitor.noteLingerDefaultNetwork(wifi1, cell); - verifyNotification(wifi1, cell); - reset(mNotifier); - - Thread.sleep(50); - mMonitor.noteLingerDefaultNetwork(cell, wifi2); - mMonitor.noteLingerDefaultNetwork(wifi2, cell); - verifyNoNotifications(); - - Thread.sleep(50); - mMonitor.noteLingerDefaultNetwork(cell, wifi3); - mMonitor.noteLingerDefaultNetwork(wifi3, cell); - verifyNoNotifications(); - } - - @Test - public void testDailyLimiting() throws InterruptedException { - mMonitor = new TestableLingerMonitor(mCtx, mNotifier, LOW_DAILY_LIMIT, HIGH_RATE_LIMIT); - - setNotificationSwitch(transition(WIFI, CELLULAR)); - setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); - NetworkAgentInfo wifi1 = wifiNai(100); - NetworkAgentInfo wifi2 = wifiNai(101); - NetworkAgentInfo wifi3 = wifiNai(102); - NetworkAgentInfo cell = cellNai(103); - - mMonitor.noteLingerDefaultNetwork(wifi1, cell); - verifyNotification(wifi1, cell); - reset(mNotifier); - - Thread.sleep(50); - mMonitor.noteLingerDefaultNetwork(cell, wifi2); - mMonitor.noteLingerDefaultNetwork(wifi2, cell); - verifyNotification(wifi2, cell); - reset(mNotifier); - - Thread.sleep(50); - mMonitor.noteLingerDefaultNetwork(cell, wifi3); - mMonitor.noteLingerDefaultNetwork(wifi3, cell); - verifyNoNotifications(); - } - - @Test - public void testUniqueNotification() { - setNotificationSwitch(transition(WIFI, CELLULAR)); - setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); - NetworkAgentInfo from = wifiNai(100); - NetworkAgentInfo to = cellNai(101); - - mMonitor.noteLingerDefaultNetwork(from, to); - verifyNotification(from, to); - - mMonitor.noteLingerDefaultNetwork(to, from); - verify(mNotifier, times(1)).clearNotification(100); - - mMonitor.noteLingerDefaultNetwork(from, to); - verifyNotification(from, to); - } - - @Test - public void testIgnoreNeverValidatedNetworks() { - setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); - setNotificationSwitch(transition(WIFI, CELLULAR)); - NetworkAgentInfo from = wifiNai(100); - NetworkAgentInfo to = cellNai(101); - from.everValidated = false; - - mMonitor.noteLingerDefaultNetwork(from, to); - verifyNoNotifications(); - } - - @Test - public void testIgnoreCurrentlyValidatedNetworks() { - setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); - setNotificationSwitch(transition(WIFI, CELLULAR)); - NetworkAgentInfo from = wifiNai(100); - NetworkAgentInfo to = cellNai(101); - from.lastValidated = true; - - mMonitor.noteLingerDefaultNetwork(from, to); - verifyNoNotifications(); - } - - @Test - public void testNoNotificationType() { - setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); - setNotificationSwitch(); - NetworkAgentInfo from = wifiNai(100); - NetworkAgentInfo to = cellNai(101); - - mMonitor.noteLingerDefaultNetwork(from, to); - verifyNoNotifications(); - } - - @Test - public void testNoTransitionToNotify() { - setNotificationType(LingerMonitor.NOTIFY_TYPE_NONE); - setNotificationSwitch(transition(WIFI, CELLULAR)); - NetworkAgentInfo from = wifiNai(100); - NetworkAgentInfo to = cellNai(101); - - mMonitor.noteLingerDefaultNetwork(from, to); - verifyNoNotifications(); - } - - @Test - public void testDifferentTransitionToNotify() { - setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); - setNotificationSwitch(transition(CELLULAR, WIFI)); - NetworkAgentInfo from = wifiNai(100); - NetworkAgentInfo to = cellNai(101); - - mMonitor.noteLingerDefaultNetwork(from, to); - verifyNoNotifications(); - } - - void setNotificationSwitch(String... transitions) { - when(mResources.getStringArray(R.array.config_networkNotifySwitches)) - .thenReturn(transitions); - } - - String transition(String from, String to) { - return from + "-" + to; - } - - void setNotificationType(int type) { - when(mResources.getInteger(R.integer.config_networkNotifySwitchType)).thenReturn(type); - } - - void verifyNoToast() { - verify(mNotifier, never()).showToast(any(), any()); - } - - void verifyNoNotification() { - verify(mNotifier, never()) - .showNotification(anyInt(), any(), any(), any(), any(), anyBoolean()); - } - - void verifyNoNotifications() { - verifyNoToast(); - verifyNoNotification(); - } - - void verifyToast(NetworkAgentInfo from, NetworkAgentInfo to) { - verifyNoNotification(); - verify(mNotifier, times(1)).showToast(from, to); - } - - void verifyNotification(NetworkAgentInfo from, NetworkAgentInfo to) { - verifyNoToast(); - verify(mNotifier, times(1)).showNotification(eq(from.network.netId), - eq(NotificationType.NETWORK_SWITCH), eq(from), eq(to), any(), eq(true)); - } - - NetworkAgentInfo nai(int netId, int transport, int networkType, String networkTypeName) { - NetworkInfo info = new NetworkInfo(networkType, 0, networkTypeName, ""); - NetworkCapabilities caps = new NetworkCapabilities(); - caps.addCapability(0); - caps.addTransportType(transport); - NetworkAgentInfo nai = new NetworkAgentInfo(null, new Network(netId), info, - new LinkProperties(), caps, new NetworkScore.Builder().setLegacyInt(50).build(), - mCtx, null, new NetworkAgentConfig.Builder().build(), mConnService, mNetd, - mDnsResolver, NetworkProvider.ID_NONE, Binder.getCallingUid(), TEST_LINGER_DELAY_MS, - mQosCallbackTracker, new ConnectivityService.Dependencies()); - nai.everValidated = true; - return nai; - } - - NetworkAgentInfo wifiNai(int netId) { - return nai(netId, NetworkCapabilities.TRANSPORT_WIFI, - ConnectivityManager.TYPE_WIFI, WIFI); - } - - NetworkAgentInfo cellNai(int netId) { - return nai(netId, NetworkCapabilities.TRANSPORT_CELLULAR, - ConnectivityManager.TYPE_MOBILE, CELLULAR); - } - - public static class TestableLingerMonitor extends LingerMonitor { - public TestableLingerMonitor(Context c, NetworkNotificationManager n, int l, long r) { - super(c, n, l, r); - } - @Override protected PendingIntent createNotificationIntent() { - return null; - } - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/MetricsTestUtil.java b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/MetricsTestUtil.java deleted file mode 100644 index 5064b9bd91b9b..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/MetricsTestUtil.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import android.net.ConnectivityMetricsEvent; -import android.os.Bundle; -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.function.Consumer; - -abstract public class MetricsTestUtil { - private MetricsTestUtil() { - } - - static ConnectivityMetricsEvent ev(Parcelable p) { - ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent(); - ev.timestamp = 1L; - ev.data = p; - return ev; - } - - static ConnectivityMetricsEvent describeIpEvent(Consumer... fs) { - Parcel p = Parcel.obtain(); - for (Consumer f : fs) { - f.accept(p); - } - p.setDataPosition(0); - return ev(p.readParcelable(ClassLoader.getSystemClassLoader())); - } - - static Consumer aType(Class c) { - return aString(c.getName()); - } - - static Consumer aBool(boolean b) { - return aByte((byte) (b ? 1 : 0)); - } - - static Consumer aByte(byte b) { - return (p) -> p.writeByte(b); - } - - static Consumer anInt(int i) { - return (p) -> p.writeInt(i); - } - - static Consumer aLong(long l) { - return (p) -> p.writeLong(l); - } - - static Consumer aString(String s) { - return (p) -> p.writeString(s); - } - - static Consumer aByteArray(byte... ary) { - return (p) -> p.writeByteArray(ary); - } - - static Consumer anIntArray(int... ary) { - return (p) -> p.writeIntArray(ary); - } - - static byte b(int i) { - return (byte) i; - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java deleted file mode 100644 index 38f6d7f3172d9..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import static android.content.Intent.ACTION_CONFIGURATION_CHANGED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; -import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; -import static android.net.NetworkPolicy.LIMIT_DISABLED; -import static android.net.NetworkPolicy.SNOOZE_NEVER; -import static android.net.NetworkPolicy.WARNING_DISABLED; -import static android.provider.Settings.Global.NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES; - -import static com.android.server.net.NetworkPolicyManagerInternal.QUOTA_TYPE_MULTIPATH; -import static com.android.server.net.NetworkPolicyManagerService.OPPORTUNISTIC_QUOTA_UNKNOWN; - -import static junit.framework.TestCase.assertNotNull; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.app.usage.NetworkStatsManager; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.res.Resources; -import android.net.ConnectivityManager; -import android.net.EthernetNetworkSpecifier; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.NetworkPolicy; -import android.net.NetworkPolicyManager; -import android.net.NetworkTemplate; -import android.net.TelephonyNetworkSpecifier; -import android.os.Handler; -import android.os.UserHandle; -import android.provider.Settings; -import android.telephony.TelephonyManager; -import android.test.mock.MockContentResolver; -import android.util.DataUnit; -import android.util.RecurrenceRule; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.internal.R; -import com.android.internal.util.test.FakeSettingsProvider; -import com.android.server.LocalServices; -import com.android.server.net.NetworkPolicyManagerInternal; -import com.android.server.net.NetworkStatsManagerInternal; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; - -import java.time.Clock; -import java.time.Instant; -import java.time.Period; -import java.time.ZoneId; -import java.time.ZonedDateTime; -import java.time.temporal.ChronoUnit; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class MultipathPolicyTrackerTest { - private static final Network TEST_NETWORK = new Network(123); - private static final int POLICY_SNOOZED = -100; - - @Mock private Context mContext; - @Mock private Context mUserAllContext; - @Mock private Resources mResources; - @Mock private Handler mHandler; - @Mock private MultipathPolicyTracker.Dependencies mDeps; - @Mock private Clock mClock; - @Mock private ConnectivityManager mCM; - @Mock private NetworkPolicyManager mNPM; - @Mock private NetworkStatsManager mStatsManager; - @Mock private NetworkPolicyManagerInternal mNPMI; - @Mock private NetworkStatsManagerInternal mNetworkStatsManagerInternal; - @Mock private TelephonyManager mTelephonyManager; - private MockContentResolver mContentResolver; - - private ArgumentCaptor mConfigChangeReceiverCaptor; - - private MultipathPolicyTracker mTracker; - - private Clock mPreviousRecurrenceRuleClock; - private boolean mRecurrenceRuleClockMocked; - - private void mockService(String serviceName, Class serviceClass, T service) { - when(mContext.getSystemServiceName(serviceClass)).thenReturn(serviceName); - when(mContext.getSystemService(serviceName)).thenReturn(service); - } - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - - mPreviousRecurrenceRuleClock = RecurrenceRule.sClock; - RecurrenceRule.sClock = mClock; - mRecurrenceRuleClockMocked = true; - - mConfigChangeReceiverCaptor = ArgumentCaptor.forClass(BroadcastReceiver.class); - - when(mContext.getResources()).thenReturn(mResources); - when(mContext.getApplicationInfo()).thenReturn(new ApplicationInfo()); - // Mock user id to all users that Context#registerReceiver will register with all users too. - doReturn(UserHandle.ALL.getIdentifier()).when(mUserAllContext).getUserId(); - when(mContext.createContextAsUser(eq(UserHandle.ALL), anyInt())) - .thenReturn(mUserAllContext); - when(mUserAllContext.registerReceiver(mConfigChangeReceiverCaptor.capture(), - argThat(f -> f.hasAction(ACTION_CONFIGURATION_CHANGED)), any(), any())) - .thenReturn(null); - - when(mDeps.getClock()).thenReturn(mClock); - - when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager); - - mContentResolver = Mockito.spy(new MockContentResolver(mContext)); - mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); - Settings.Global.clearProviderForTest(); - when(mContext.getContentResolver()).thenReturn(mContentResolver); - - mockService(Context.CONNECTIVITY_SERVICE, ConnectivityManager.class, mCM); - mockService(Context.NETWORK_POLICY_SERVICE, NetworkPolicyManager.class, mNPM); - mockService(Context.NETWORK_STATS_SERVICE, NetworkStatsManager.class, mStatsManager); - mockService(Context.TELEPHONY_SERVICE, TelephonyManager.class, mTelephonyManager); - - LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class); - LocalServices.addService(NetworkPolicyManagerInternal.class, mNPMI); - - LocalServices.removeServiceForTest(NetworkStatsManagerInternal.class); - LocalServices.addService(NetworkStatsManagerInternal.class, mNetworkStatsManagerInternal); - - mTracker = new MultipathPolicyTracker(mContext, mHandler, mDeps); - } - - @After - public void tearDown() { - // Avoid setting static clock to null (which should normally not be the case) - // if MockitoAnnotations.initMocks threw an exception - if (mRecurrenceRuleClockMocked) { - RecurrenceRule.sClock = mPreviousRecurrenceRuleClock; - } - mRecurrenceRuleClockMocked = false; - } - - private void setDefaultQuotaGlobalSetting(long setting) { - Settings.Global.putInt(mContentResolver, NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES, - (int) setting); - } - - private void testGetMultipathPreference( - long usedBytesToday, long subscriptionQuota, long policyWarning, long policyLimit, - long defaultGlobalSetting, long defaultResSetting, boolean roaming) { - - // TODO: tests should not use ZoneId.systemDefault() once code handles TZ correctly. - final ZonedDateTime now = ZonedDateTime.ofInstant( - Instant.parse("2017-04-02T10:11:12Z"), ZoneId.systemDefault()); - final ZonedDateTime startOfDay = now.truncatedTo(ChronoUnit.DAYS); - when(mClock.millis()).thenReturn(now.toInstant().toEpochMilli()); - when(mClock.instant()).thenReturn(now.toInstant()); - when(mClock.getZone()).thenReturn(ZoneId.systemDefault()); - - // Setup plan quota - when(mNPMI.getSubscriptionOpportunisticQuota(TEST_NETWORK, QUOTA_TYPE_MULTIPATH)) - .thenReturn(subscriptionQuota); - - // Setup user policy warning / limit - if (policyWarning != WARNING_DISABLED || policyLimit != LIMIT_DISABLED) { - final Instant recurrenceStart = Instant.parse("2017-04-01T00:00:00Z"); - final RecurrenceRule recurrenceRule = new RecurrenceRule( - ZonedDateTime.ofInstant( - recurrenceStart, - ZoneId.systemDefault()), - null /* end */, - Period.ofMonths(1)); - final boolean snoozeWarning = policyWarning == POLICY_SNOOZED; - final boolean snoozeLimit = policyLimit == POLICY_SNOOZED; - when(mNPM.getNetworkPolicies()).thenReturn(new NetworkPolicy[] { - new NetworkPolicy( - NetworkTemplate.buildTemplateMobileWildcard(), - recurrenceRule, - snoozeWarning ? 0 : policyWarning, - snoozeLimit ? 0 : policyLimit, - snoozeWarning ? recurrenceStart.toEpochMilli() + 1 : SNOOZE_NEVER, - snoozeLimit ? recurrenceStart.toEpochMilli() + 1 : SNOOZE_NEVER, - SNOOZE_NEVER, - true /* metered */, - false /* inferred */) - }); - } else { - when(mNPM.getNetworkPolicies()).thenReturn(new NetworkPolicy[0]); - } - - // Setup default quota in settings and resources - if (defaultGlobalSetting > 0) { - setDefaultQuotaGlobalSetting(defaultGlobalSetting); - } - when(mResources.getInteger(R.integer.config_networkDefaultDailyMultipathQuotaBytes)) - .thenReturn((int) defaultResSetting); - - when(mNetworkStatsManagerInternal.getNetworkTotalBytes( - any(), - eq(startOfDay.toInstant().toEpochMilli()), - eq(now.toInstant().toEpochMilli()))).thenReturn(usedBytesToday); - - ArgumentCaptor networkCallback = - ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class); - mTracker.start(); - verify(mCM).registerNetworkCallback(any(), networkCallback.capture(), any()); - - // Simulate callback after capability changes - NetworkCapabilities capabilities = new NetworkCapabilities() - .addCapability(NET_CAPABILITY_INTERNET) - .addTransportType(TRANSPORT_CELLULAR) - .setNetworkSpecifier(new EthernetNetworkSpecifier("eth234")); - if (!roaming) { - capabilities.addCapability(NET_CAPABILITY_NOT_ROAMING); - } - networkCallback.getValue().onCapabilitiesChanged( - TEST_NETWORK, - capabilities); - - // make sure it also works with the new introduced TelephonyNetworkSpecifier - capabilities = new NetworkCapabilities() - .addCapability(NET_CAPABILITY_INTERNET) - .addTransportType(TRANSPORT_CELLULAR) - .setNetworkSpecifier(new TelephonyNetworkSpecifier.Builder() - .setSubscriptionId(234).build()); - if (!roaming) { - capabilities.addCapability(NET_CAPABILITY_NOT_ROAMING); - } - networkCallback.getValue().onCapabilitiesChanged( - TEST_NETWORK, - capabilities); - } - - @Test - public void testGetMultipathPreference_SubscriptionQuota() { - testGetMultipathPreference( - DataUnit.MEGABYTES.toBytes(2) /* usedBytesToday */, - DataUnit.MEGABYTES.toBytes(14) /* subscriptionQuota */, - DataUnit.MEGABYTES.toBytes(100) /* policyWarning */, - LIMIT_DISABLED, - DataUnit.MEGABYTES.toBytes(12) /* defaultGlobalSetting */, - 2_500_000 /* defaultResSetting */, - false /* roaming */); - - verify(mStatsManager, times(1)).registerUsageCallback( - any(), anyInt(), eq(DataUnit.MEGABYTES.toBytes(12)), any(), any()); - } - - @Test - public void testGetMultipathPreference_UserWarningQuota() { - testGetMultipathPreference( - DataUnit.MEGABYTES.toBytes(7) /* usedBytesToday */, - OPPORTUNISTIC_QUOTA_UNKNOWN, - // 29 days from Apr. 2nd to May 1st - DataUnit.MEGABYTES.toBytes(15 * 29 * 20) /* policyWarning */, - LIMIT_DISABLED, - DataUnit.MEGABYTES.toBytes(12) /* defaultGlobalSetting */, - 2_500_000 /* defaultResSetting */, - false /* roaming */); - - // Daily budget should be 15MB (5% of daily quota), 7MB used today: callback set for 8MB - verify(mStatsManager, times(1)).registerUsageCallback( - any(), anyInt(), eq(DataUnit.MEGABYTES.toBytes(8)), any(), any()); - } - - @Test - public void testGetMultipathPreference_SnoozedWarningQuota() { - testGetMultipathPreference( - DataUnit.MEGABYTES.toBytes(7) /* usedBytesToday */, - OPPORTUNISTIC_QUOTA_UNKNOWN, - // 29 days from Apr. 2nd to May 1st - POLICY_SNOOZED /* policyWarning */, - DataUnit.MEGABYTES.toBytes(15 * 29 * 20) /* policyLimit */, - DataUnit.MEGABYTES.toBytes(12) /* defaultGlobalSetting */, - 2_500_000 /* defaultResSetting */, - false /* roaming */); - - // Daily budget should be 15MB (5% of daily quota), 7MB used today: callback set for 8MB - verify(mStatsManager, times(1)).registerUsageCallback( - any(), anyInt(), eq(DataUnit.MEGABYTES.toBytes(8)), any(), any()); - } - - @Test - public void testGetMultipathPreference_SnoozedBothQuota() { - testGetMultipathPreference( - DataUnit.MEGABYTES.toBytes(7) /* usedBytesToday */, - OPPORTUNISTIC_QUOTA_UNKNOWN, - // 29 days from Apr. 2nd to May 1st - POLICY_SNOOZED /* policyWarning */, - POLICY_SNOOZED /* policyLimit */, - DataUnit.MEGABYTES.toBytes(12) /* defaultGlobalSetting */, - 2_500_000 /* defaultResSetting */, - false /* roaming */); - - // Default global setting should be used: 12 - 7 = 5 - verify(mStatsManager, times(1)).registerUsageCallback( - any(), anyInt(), eq(DataUnit.MEGABYTES.toBytes(5)), any(), any()); - } - - @Test - public void testGetMultipathPreference_SettingChanged() { - testGetMultipathPreference( - DataUnit.MEGABYTES.toBytes(2) /* usedBytesToday */, - OPPORTUNISTIC_QUOTA_UNKNOWN, - WARNING_DISABLED, - LIMIT_DISABLED, - -1 /* defaultGlobalSetting */, - DataUnit.MEGABYTES.toBytes(10) /* defaultResSetting */, - false /* roaming */); - - verify(mStatsManager, times(1)).registerUsageCallback( - any(), anyInt(), eq(DataUnit.MEGABYTES.toBytes(8)), any(), any()); - - // Update setting - setDefaultQuotaGlobalSetting(DataUnit.MEGABYTES.toBytes(14)); - mTracker.mSettingsObserver.onChange( - false, Settings.Global.getUriFor(NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES)); - - // Callback must have been re-registered with new setting - verify(mStatsManager, times(1)).unregisterUsageCallback(any()); - verify(mStatsManager, times(1)).registerUsageCallback( - any(), anyInt(), eq(DataUnit.MEGABYTES.toBytes(12)), any(), any()); - } - - @Test - public void testGetMultipathPreference_ResourceChanged() { - testGetMultipathPreference( - DataUnit.MEGABYTES.toBytes(2) /* usedBytesToday */, - OPPORTUNISTIC_QUOTA_UNKNOWN, - WARNING_DISABLED, - LIMIT_DISABLED, - -1 /* defaultGlobalSetting */, - DataUnit.MEGABYTES.toBytes(14) /* defaultResSetting */, - false /* roaming */); - - verify(mStatsManager, times(1)).registerUsageCallback( - any(), anyInt(), eq(DataUnit.MEGABYTES.toBytes(12)), any(), any()); - - when(mResources.getInteger(R.integer.config_networkDefaultDailyMultipathQuotaBytes)) - .thenReturn((int) DataUnit.MEGABYTES.toBytes(16)); - - final BroadcastReceiver configChangeReceiver = mConfigChangeReceiverCaptor.getValue(); - assertNotNull(configChangeReceiver); - configChangeReceiver.onReceive(mContext, new Intent()); - - // Uses the new setting (16 - 2 = 14MB) - verify(mStatsManager, times(1)).registerUsageCallback( - any(), anyInt(), eq(DataUnit.MEGABYTES.toBytes(14)), any(), any()); - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/Nat464XlatTest.java b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/Nat464XlatTest.java deleted file mode 100644 index 9b2a638f8b399..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/Nat464XlatTest.java +++ /dev/null @@ -1,555 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import android.net.ConnectivityManager; -import android.net.IDnsResolver; -import android.net.INetd; -import android.net.InterfaceConfigurationParcel; -import android.net.IpPrefix; -import android.net.LinkAddress; -import android.net.LinkProperties; -import android.net.NetworkAgentConfig; -import android.net.NetworkCapabilities; -import android.net.NetworkInfo; -import android.os.Handler; -import android.os.test.TestLooper; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.server.ConnectivityService; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class Nat464XlatTest { - - static final String BASE_IFACE = "test0"; - static final String STACKED_IFACE = "v4-test0"; - static final LinkAddress V6ADDR = new LinkAddress("2001:db8:1::f00/64"); - static final LinkAddress ADDR = new LinkAddress("192.0.2.5/29"); - static final String NAT64_PREFIX = "64:ff9b::/96"; - static final String OTHER_NAT64_PREFIX = "2001:db8:0:64::/96"; - static final int NETID = 42; - - @Mock ConnectivityService mConnectivity; - @Mock IDnsResolver mDnsResolver; - @Mock INetd mNetd; - @Mock NetworkAgentInfo mNai; - - TestLooper mLooper; - Handler mHandler; - NetworkAgentConfig mAgentConfig = new NetworkAgentConfig(); - - Nat464Xlat makeNat464Xlat(boolean isCellular464XlatEnabled) { - return new Nat464Xlat(mNai, mNetd, mDnsResolver, new ConnectivityService.Dependencies()) { - @Override protected int getNetId() { - return NETID; - } - - @Override protected boolean isCellular464XlatEnabled() { - return isCellular464XlatEnabled; - } - }; - } - - private void markNetworkConnected() { - mNai.networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", ""); - } - - private void markNetworkDisconnected() { - mNai.networkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, "", ""); - } - - @Before - public void setUp() throws Exception { - mLooper = new TestLooper(); - mHandler = new Handler(mLooper.getLooper()); - - MockitoAnnotations.initMocks(this); - - mNai.linkProperties = new LinkProperties(); - mNai.linkProperties.setInterfaceName(BASE_IFACE); - mNai.networkInfo = new NetworkInfo(null); - mNai.networkInfo.setType(ConnectivityManager.TYPE_WIFI); - mNai.networkCapabilities = new NetworkCapabilities(); - markNetworkConnected(); - when(mNai.connService()).thenReturn(mConnectivity); - when(mNai.netAgentConfig()).thenReturn(mAgentConfig); - when(mNai.handler()).thenReturn(mHandler); - final InterfaceConfigurationParcel mConfig = new InterfaceConfigurationParcel(); - when(mNetd.interfaceGetCfg(eq(STACKED_IFACE))).thenReturn(mConfig); - mConfig.ipv4Addr = ADDR.getAddress().getHostAddress(); - mConfig.prefixLength = ADDR.getPrefixLength(); - } - - private void assertRequiresClat(boolean expected, NetworkAgentInfo nai) { - Nat464Xlat nat = makeNat464Xlat(true); - String msg = String.format("requiresClat expected %b for type=%d state=%s skip=%b " - + "nat64Prefix=%s addresses=%s", expected, nai.networkInfo.getType(), - nai.networkInfo.getDetailedState(), - mAgentConfig.skip464xlat, nai.linkProperties.getNat64Prefix(), - nai.linkProperties.getLinkAddresses()); - assertEquals(msg, expected, nat.requiresClat(nai)); - } - - private void assertShouldStartClat(boolean expected, NetworkAgentInfo nai) { - Nat464Xlat nat = makeNat464Xlat(true); - String msg = String.format("shouldStartClat expected %b for type=%d state=%s skip=%b " - + "nat64Prefix=%s addresses=%s", expected, nai.networkInfo.getType(), - nai.networkInfo.getDetailedState(), - mAgentConfig.skip464xlat, nai.linkProperties.getNat64Prefix(), - nai.linkProperties.getLinkAddresses()); - assertEquals(msg, expected, nat.shouldStartClat(nai)); - } - - @Test - public void testRequiresClat() throws Exception { - final int[] supportedTypes = { - ConnectivityManager.TYPE_MOBILE, - ConnectivityManager.TYPE_WIFI, - ConnectivityManager.TYPE_ETHERNET, - }; - - // NetworkInfo doesn't allow setting the State directly, but rather - // requires setting DetailedState in order set State as a side-effect. - final NetworkInfo.DetailedState[] supportedDetailedStates = { - NetworkInfo.DetailedState.CONNECTED, - NetworkInfo.DetailedState.SUSPENDED, - }; - - LinkProperties oldLp = new LinkProperties(mNai.linkProperties); - for (int type : supportedTypes) { - mNai.networkInfo.setType(type); - for (NetworkInfo.DetailedState state : supportedDetailedStates) { - mNai.networkInfo.setDetailedState(state, "reason", "extraInfo"); - - mNai.linkProperties.setNat64Prefix(new IpPrefix(OTHER_NAT64_PREFIX)); - assertRequiresClat(false, mNai); - assertShouldStartClat(false, mNai); - - mNai.linkProperties.addLinkAddress(new LinkAddress("fc00::1/64")); - assertRequiresClat(false, mNai); - assertShouldStartClat(false, mNai); - - mNai.linkProperties.addLinkAddress(new LinkAddress("2001:db8::1/64")); - assertRequiresClat(true, mNai); - assertShouldStartClat(true, mNai); - - mAgentConfig.skip464xlat = true; - assertRequiresClat(false, mNai); - assertShouldStartClat(false, mNai); - - mAgentConfig.skip464xlat = false; - assertRequiresClat(true, mNai); - assertShouldStartClat(true, mNai); - - mNai.linkProperties.addLinkAddress(new LinkAddress("192.0.2.2/24")); - assertRequiresClat(false, mNai); - assertShouldStartClat(false, mNai); - - mNai.linkProperties.removeLinkAddress(new LinkAddress("192.0.2.2/24")); - assertRequiresClat(true, mNai); - assertShouldStartClat(true, mNai); - - mNai.linkProperties.setNat64Prefix(null); - assertRequiresClat(true, mNai); - assertShouldStartClat(false, mNai); - - mNai.linkProperties = new LinkProperties(oldLp); - } - } - } - - private void makeClatUnnecessary(boolean dueToDisconnect) { - if (dueToDisconnect) { - markNetworkDisconnected(); - } else { - mNai.linkProperties.addLinkAddress(ADDR); - } - } - - private void checkNormalStartAndStop(boolean dueToDisconnect) throws Exception { - Nat464Xlat nat = makeNat464Xlat(true); - ArgumentCaptor c = ArgumentCaptor.forClass(LinkProperties.class); - - mNai.linkProperties.addLinkAddress(V6ADDR); - - nat.setNat64PrefixFromDns(new IpPrefix(NAT64_PREFIX)); - - // Start clat. - nat.start(); - - verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX)); - - // Stacked interface up notification arrives. - nat.interfaceLinkStateChanged(STACKED_IFACE, true); - mLooper.dispatchNext(); - - verify(mNetd).interfaceGetCfg(eq(STACKED_IFACE)); - verify(mConnectivity).handleUpdateLinkProperties(eq(mNai), c.capture()); - assertFalse(c.getValue().getStackedLinks().isEmpty()); - assertTrue(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); - assertRunning(nat); - - // Stop clat (Network disconnects, IPv4 addr appears, ...). - makeClatUnnecessary(dueToDisconnect); - nat.stop(); - - verify(mNetd).clatdStop(eq(BASE_IFACE)); - verify(mConnectivity, times(2)).handleUpdateLinkProperties(eq(mNai), c.capture()); - assertTrue(c.getValue().getStackedLinks().isEmpty()); - assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); - verify(mDnsResolver).stopPrefix64Discovery(eq(NETID)); - assertIdle(nat); - - // Stacked interface removed notification arrives and is ignored. - nat.interfaceRemoved(STACKED_IFACE); - mLooper.dispatchNext(); - - verifyNoMoreInteractions(mNetd, mConnectivity); - } - - @Test - public void testNormalStartAndStopDueToDisconnect() throws Exception { - checkNormalStartAndStop(true); - } - - @Test - public void testNormalStartAndStopDueToIpv4Addr() throws Exception { - checkNormalStartAndStop(false); - } - - private void checkStartStopStart(boolean interfaceRemovedFirst) throws Exception { - Nat464Xlat nat = makeNat464Xlat(true); - ArgumentCaptor c = ArgumentCaptor.forClass(LinkProperties.class); - InOrder inOrder = inOrder(mNetd, mConnectivity); - - mNai.linkProperties.addLinkAddress(V6ADDR); - - nat.setNat64PrefixFromDns(new IpPrefix(NAT64_PREFIX)); - - nat.start(); - - inOrder.verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX)); - - // Stacked interface up notification arrives. - nat.interfaceLinkStateChanged(STACKED_IFACE, true); - mLooper.dispatchNext(); - - inOrder.verify(mConnectivity).handleUpdateLinkProperties(eq(mNai), c.capture()); - assertFalse(c.getValue().getStackedLinks().isEmpty()); - assertTrue(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); - assertRunning(nat); - - // ConnectivityService stops clat (Network disconnects, IPv4 addr appears, ...). - nat.stop(); - - inOrder.verify(mNetd).clatdStop(eq(BASE_IFACE)); - - inOrder.verify(mConnectivity, times(1)).handleUpdateLinkProperties(eq(mNai), c.capture()); - assertTrue(c.getValue().getStackedLinks().isEmpty()); - assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); - assertIdle(nat); - - if (interfaceRemovedFirst) { - // Stacked interface removed notification arrives and is ignored. - nat.interfaceRemoved(STACKED_IFACE); - mLooper.dispatchNext(); - nat.interfaceLinkStateChanged(STACKED_IFACE, false); - mLooper.dispatchNext(); - } - - assertTrue(c.getValue().getStackedLinks().isEmpty()); - assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); - assertIdle(nat); - inOrder.verifyNoMoreInteractions(); - - nat.start(); - - inOrder.verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX)); - - if (!interfaceRemovedFirst) { - // Stacked interface removed notification arrives and is ignored. - nat.interfaceRemoved(STACKED_IFACE); - mLooper.dispatchNext(); - nat.interfaceLinkStateChanged(STACKED_IFACE, false); - mLooper.dispatchNext(); - } - - // Stacked interface up notification arrives. - nat.interfaceLinkStateChanged(STACKED_IFACE, true); - mLooper.dispatchNext(); - - inOrder.verify(mConnectivity).handleUpdateLinkProperties(eq(mNai), c.capture()); - assertFalse(c.getValue().getStackedLinks().isEmpty()); - assertTrue(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); - assertRunning(nat); - - // ConnectivityService stops clat again. - nat.stop(); - - inOrder.verify(mNetd).clatdStop(eq(BASE_IFACE)); - - inOrder.verify(mConnectivity, times(1)).handleUpdateLinkProperties(eq(mNai), c.capture()); - assertTrue(c.getValue().getStackedLinks().isEmpty()); - assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); - assertIdle(nat); - - inOrder.verifyNoMoreInteractions(); - } - - @Test - public void testStartStopStart() throws Exception { - checkStartStopStart(true); - } - - @Test - public void testStartStopStartBeforeInterfaceRemoved() throws Exception { - checkStartStopStart(false); - } - - @Test - public void testClatdCrashWhileRunning() throws Exception { - Nat464Xlat nat = makeNat464Xlat(true); - ArgumentCaptor c = ArgumentCaptor.forClass(LinkProperties.class); - - nat.setNat64PrefixFromDns(new IpPrefix(NAT64_PREFIX)); - - nat.start(); - - verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX)); - - // Stacked interface up notification arrives. - nat.interfaceLinkStateChanged(STACKED_IFACE, true); - mLooper.dispatchNext(); - - verify(mNetd).interfaceGetCfg(eq(STACKED_IFACE)); - verify(mConnectivity, times(1)).handleUpdateLinkProperties(eq(mNai), c.capture()); - assertFalse(c.getValue().getStackedLinks().isEmpty()); - assertTrue(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); - assertRunning(nat); - - // Stacked interface removed notification arrives (clatd crashed, ...). - nat.interfaceRemoved(STACKED_IFACE); - mLooper.dispatchNext(); - - verify(mNetd).clatdStop(eq(BASE_IFACE)); - verify(mConnectivity, times(2)).handleUpdateLinkProperties(eq(mNai), c.capture()); - verify(mDnsResolver).stopPrefix64Discovery(eq(NETID)); - assertTrue(c.getValue().getStackedLinks().isEmpty()); - assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); - assertIdle(nat); - - // ConnectivityService stops clat: no-op. - nat.stop(); - - verifyNoMoreInteractions(mNetd, mConnectivity); - } - - private void checkStopBeforeClatdStarts(boolean dueToDisconnect) throws Exception { - Nat464Xlat nat = makeNat464Xlat(true); - - mNai.linkProperties.addLinkAddress(new LinkAddress("2001:db8::1/64")); - - nat.setNat64PrefixFromDns(new IpPrefix(NAT64_PREFIX)); - - nat.start(); - - verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX)); - - // ConnectivityService immediately stops clat (Network disconnects, IPv4 addr appears, ...) - makeClatUnnecessary(dueToDisconnect); - nat.stop(); - - verify(mNetd).clatdStop(eq(BASE_IFACE)); - verify(mDnsResolver).stopPrefix64Discovery(eq(NETID)); - assertIdle(nat); - - // In-flight interface up notification arrives: no-op - nat.interfaceLinkStateChanged(STACKED_IFACE, true); - mLooper.dispatchNext(); - - // Interface removed notification arrives after stopClatd() takes effect: no-op. - nat.interfaceRemoved(STACKED_IFACE); - mLooper.dispatchNext(); - - assertIdle(nat); - - verifyNoMoreInteractions(mNetd, mConnectivity); - } - - @Test - public void testStopDueToDisconnectBeforeClatdStarts() throws Exception { - checkStopBeforeClatdStarts(true); - } - - @Test - public void testStopDueToIpv4AddrBeforeClatdStarts() throws Exception { - checkStopBeforeClatdStarts(false); - } - - private void checkStopAndClatdNeverStarts(boolean dueToDisconnect) throws Exception { - Nat464Xlat nat = makeNat464Xlat(true); - - mNai.linkProperties.addLinkAddress(new LinkAddress("2001:db8::1/64")); - - nat.setNat64PrefixFromDns(new IpPrefix(NAT64_PREFIX)); - - nat.start(); - - verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX)); - - // ConnectivityService immediately stops clat (Network disconnects, IPv4 addr appears, ...) - makeClatUnnecessary(dueToDisconnect); - nat.stop(); - - verify(mNetd).clatdStop(eq(BASE_IFACE)); - verify(mDnsResolver).stopPrefix64Discovery(eq(NETID)); - assertIdle(nat); - - verifyNoMoreInteractions(mNetd, mConnectivity); - } - - @Test - public void testStopDueToDisconnectAndClatdNeverStarts() throws Exception { - checkStopAndClatdNeverStarts(true); - } - - @Test - public void testStopDueToIpv4AddressAndClatdNeverStarts() throws Exception { - checkStopAndClatdNeverStarts(false); - } - - @Test - public void testNat64PrefixPreference() throws Exception { - final IpPrefix prefixFromDns = new IpPrefix(NAT64_PREFIX); - final IpPrefix prefixFromRa = new IpPrefix(OTHER_NAT64_PREFIX); - - Nat464Xlat nat = makeNat464Xlat(true); - - final LinkProperties emptyLp = new LinkProperties(); - LinkProperties fixedupLp; - - fixedupLp = new LinkProperties(); - nat.setNat64PrefixFromDns(prefixFromDns); - nat.fixupLinkProperties(emptyLp, fixedupLp); - assertEquals(prefixFromDns, fixedupLp.getNat64Prefix()); - - fixedupLp = new LinkProperties(); - nat.setNat64PrefixFromRa(prefixFromRa); - nat.fixupLinkProperties(emptyLp, fixedupLp); - assertEquals(prefixFromRa, fixedupLp.getNat64Prefix()); - - fixedupLp = new LinkProperties(); - nat.setNat64PrefixFromRa(null); - nat.fixupLinkProperties(emptyLp, fixedupLp); - assertEquals(prefixFromDns, fixedupLp.getNat64Prefix()); - - fixedupLp = new LinkProperties(); - nat.setNat64PrefixFromRa(prefixFromRa); - nat.fixupLinkProperties(emptyLp, fixedupLp); - assertEquals(prefixFromRa, fixedupLp.getNat64Prefix()); - - fixedupLp = new LinkProperties(); - nat.setNat64PrefixFromDns(null); - nat.fixupLinkProperties(emptyLp, fixedupLp); - assertEquals(prefixFromRa, fixedupLp.getNat64Prefix()); - - fixedupLp = new LinkProperties(); - nat.setNat64PrefixFromRa(null); - nat.fixupLinkProperties(emptyLp, fixedupLp); - assertEquals(null, fixedupLp.getNat64Prefix()); - } - - private void checkClatDisabledOnCellular(boolean onCellular) throws Exception { - // Disable 464xlat on cellular networks. - Nat464Xlat nat = makeNat464Xlat(false); - mNai.linkProperties.addLinkAddress(V6ADDR); - mNai.networkCapabilities.setTransportType(TRANSPORT_CELLULAR, onCellular); - nat.update(); - - final IpPrefix nat64Prefix = new IpPrefix(NAT64_PREFIX); - if (onCellular) { - // Prefix discovery is never started. - verify(mDnsResolver, never()).startPrefix64Discovery(eq(NETID)); - assertIdle(nat); - - // If a NAT64 prefix comes in from an RA, clat is not started either. - mNai.linkProperties.setNat64Prefix(nat64Prefix); - nat.setNat64PrefixFromRa(nat64Prefix); - nat.update(); - verify(mNetd, never()).clatdStart(anyString(), anyString()); - assertIdle(nat); - } else { - // Prefix discovery is started. - verify(mDnsResolver).startPrefix64Discovery(eq(NETID)); - assertIdle(nat); - - // If a NAT64 prefix comes in from an RA, clat is started. - mNai.linkProperties.setNat64Prefix(nat64Prefix); - nat.setNat64PrefixFromRa(nat64Prefix); - nat.update(); - verify(mNetd).clatdStart(BASE_IFACE, NAT64_PREFIX); - assertStarting(nat); - } - } - - @Test - public void testClatDisabledOnCellular() throws Exception { - checkClatDisabledOnCellular(true); - } - - @Test - public void testClatDisabledOnNonCellular() throws Exception { - checkClatDisabledOnCellular(false); - } - - static void assertIdle(Nat464Xlat nat) { - assertTrue("Nat464Xlat was not IDLE", !nat.isStarted()); - } - - static void assertStarting(Nat464Xlat nat) { - assertTrue("Nat464Xlat was not STARTING", nat.isStarting()); - } - - static void assertRunning(Nat464Xlat nat) { - assertTrue("Nat464Xlat was not RUNNING", nat.isRunning()); - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/NetdEventListenerServiceTest.java deleted file mode 100644 index 50aaaee244189..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/NetdEventListenerServiceTest.java +++ /dev/null @@ -1,554 +0,0 @@ -/* - * Copyright (C) 2016, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import static android.net.metrics.INetdEventListener.EVENT_GETADDRINFO; -import static android.net.metrics.INetdEventListener.EVENT_GETHOSTBYNAME; - -import static com.android.testutils.MiscAsserts.assertStringContains; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.system.OsConstants; -import android.test.suitebuilder.annotation.SmallTest; -import android.util.Base64; - -import androidx.test.runner.AndroidJUnit4; - -import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent; -import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityLog; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; - -import java.io.FileOutputStream; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class NetdEventListenerServiceTest { - private static final String EXAMPLE_IPV4 = "192.0.2.1"; - private static final String EXAMPLE_IPV6 = "2001:db8:1200::2:1"; - - private static final byte[] MAC_ADDR = - {(byte)0x84, (byte)0xc9, (byte)0xb2, (byte)0x6a, (byte)0xed, (byte)0x4b}; - - NetdEventListenerService mService; - ConnectivityManager mCm; - private static final NetworkCapabilities CAPABILITIES_WIFI = new NetworkCapabilities.Builder() - .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) - .build(); - private static final NetworkCapabilities CAPABILITIES_CELL = new NetworkCapabilities.Builder() - .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) - .build(); - - @Before - public void setUp() { - mCm = mock(ConnectivityManager.class); - mService = new NetdEventListenerService(mCm); - } - - @Test - public void testWakeupEventLogging() throws Exception { - final int BUFFER_LENGTH = NetdEventListenerService.WAKEUP_EVENT_BUFFER_LENGTH; - final long now = System.currentTimeMillis(); - final String iface = "wlan0"; - final byte[] mac = MAC_ADDR; - final String srcIp = "192.168.2.1"; - final String dstIp = "192.168.2.23"; - final String srcIp6 = "2001:db8:4:fd00:a585:13d1:6a23:4fb4"; - final String dstIp6 = "2001:db8:4006:807::200a"; - final int sport = 2356; - final int dport = 13489; - - final int v4 = 0x800; - final int v6 = 0x86dd; - final int tcp = 6; - final int udp = 17; - final int icmp6 = 58; - - // Baseline without any event - String[] baseline = listNetdEvent(); - - int[] uids = {10001, 10002, 10004, 1000, 10052, 10023, 10002, 10123, 10004}; - wakeupEvent(iface, uids[0], v4, tcp, mac, srcIp, dstIp, sport, dport, now); - wakeupEvent(iface, uids[1], v6, udp, mac, srcIp6, dstIp6, sport, dport, now); - wakeupEvent(iface, uids[2], v6, udp, mac, srcIp6, dstIp6, sport, dport, now); - wakeupEvent(iface, uids[3], v4, icmp6, mac, srcIp, dstIp, sport, dport, now); - wakeupEvent(iface, uids[4], v6, tcp, mac, srcIp6, dstIp6, sport, dport, now); - wakeupEvent(iface, uids[5], v4, tcp, mac, srcIp, dstIp, sport, dport, now); - wakeupEvent(iface, uids[6], v6, udp, mac, srcIp6, dstIp6, sport, dport, now); - wakeupEvent(iface, uids[7], v6, tcp, mac, srcIp6, dstIp6, sport, dport, now); - wakeupEvent(iface, uids[8], v6, udp, mac, srcIp6, dstIp6, sport, dport, now); - - String[] events2 = remove(listNetdEvent(), baseline); - int expectedLength2 = uids.length + 1; // +1 for the WakeupStats line - assertEquals(expectedLength2, events2.length); - assertStringContains(events2[0], "WakeupStats"); - assertStringContains(events2[0], "wlan0"); - assertStringContains(events2[0], "0x800"); - assertStringContains(events2[0], "0x86dd"); - for (int i = 0; i < uids.length; i++) { - String got = events2[i+1]; - assertStringContains(got, "WakeupEvent"); - assertStringContains(got, "wlan0"); - assertStringContains(got, "uid: " + uids[i]); - } - - int uid = 20000; - for (int i = 0; i < BUFFER_LENGTH * 2; i++) { - long ts = now + 10; - wakeupEvent(iface, uid, 0x800, 6, mac, srcIp, dstIp, 23, 24, ts); - } - - String[] events3 = remove(listNetdEvent(), baseline); - int expectedLength3 = BUFFER_LENGTH + 1; // +1 for the WakeupStats line - assertEquals(expectedLength3, events3.length); - assertStringContains(events2[0], "WakeupStats"); - assertStringContains(events2[0], "wlan0"); - for (int i = 1; i < expectedLength3; i++) { - String got = events3[i]; - assertStringContains(got, "WakeupEvent"); - assertStringContains(got, "wlan0"); - assertStringContains(got, "uid: " + uid); - } - - uid = 45678; - wakeupEvent(iface, uid, 0x800, 6, mac, srcIp, dstIp, 23, 24, now); - - String[] events4 = remove(listNetdEvent(), baseline); - String lastEvent = events4[events4.length - 1]; - assertStringContains(lastEvent, "WakeupEvent"); - assertStringContains(lastEvent, "wlan0"); - assertStringContains(lastEvent, "uid: " + uid); - } - - @Test - public void testWakeupStatsLogging() throws Exception { - final byte[] mac = MAC_ADDR; - final String srcIp = "192.168.2.1"; - final String dstIp = "192.168.2.23"; - final String srcIp6 = "2401:fa00:4:fd00:a585:13d1:6a23:4fb4"; - final String dstIp6 = "2404:6800:4006:807::200a"; - final int sport = 2356; - final int dport = 13489; - final long now = 1001L; - - final int v4 = 0x800; - final int v6 = 0x86dd; - final int tcp = 6; - final int udp = 17; - final int icmp6 = 58; - - wakeupEvent("wlan0", 1000, v4, tcp, mac, srcIp, dstIp, sport, dport, now); - wakeupEvent("rmnet0", 10123, v4, tcp, mac, srcIp, dstIp, sport, dport, now); - wakeupEvent("wlan0", 1000, v4, udp, mac, srcIp, dstIp, sport, dport, now); - wakeupEvent("rmnet0", 10008, v4, tcp, mac, srcIp, dstIp, sport, dport, now); - wakeupEvent("wlan0", -1, v6, icmp6, mac, srcIp6, dstIp6, sport, dport, now); - wakeupEvent("wlan0", 10008, v4, tcp, mac, srcIp, dstIp, sport, dport, now); - wakeupEvent("rmnet0", 1000, v4, tcp, mac, srcIp, dstIp, sport, dport, now); - wakeupEvent("wlan0", 10004, v4, udp, mac, srcIp, dstIp, sport, dport, now); - wakeupEvent("wlan0", 1000, v6, tcp, mac, srcIp6, dstIp6, sport, dport, now); - wakeupEvent("wlan0", 0, v6, udp, mac, srcIp6, dstIp6, sport, dport, now); - wakeupEvent("wlan0", -1, v6, icmp6, mac, srcIp6, dstIp6, sport, dport, now); - wakeupEvent("rmnet0", 10052, v4, tcp, mac, srcIp, dstIp, sport, dport, now); - wakeupEvent("wlan0", 0, v6, udp, mac, srcIp6, dstIp6, sport, dport, now); - wakeupEvent("rmnet0", 1000, v6, tcp, mac, srcIp6, dstIp6, sport, dport, now); - wakeupEvent("wlan0", 1010, v4, udp, mac, srcIp, dstIp, sport, dport, now); - - String got = flushStatistics(); - String want = String.join("\n", - "dropped_events: 0", - "events <", - " if_name: \"\"", - " link_layer: 2", - " network_id: 0", - " time_ms: 0", - " transports: 0", - " wakeup_stats <", - " application_wakeups: 3", - " duration_sec: 0", - " ethertype_counts <", - " key: 2048", - " value: 4", - " >", - " ethertype_counts <", - " key: 34525", - " value: 1", - " >", - " ip_next_header_counts <", - " key: 6", - " value: 5", - " >", - " l2_broadcast_count: 0", - " l2_multicast_count: 0", - " l2_unicast_count: 5", - " no_uid_wakeups: 0", - " non_application_wakeups: 0", - " root_wakeups: 0", - " system_wakeups: 2", - " total_wakeups: 5", - " >", - ">", - "events <", - " if_name: \"\"", - " link_layer: 4", - " network_id: 0", - " time_ms: 0", - " transports: 0", - " wakeup_stats <", - " application_wakeups: 2", - " duration_sec: 0", - " ethertype_counts <", - " key: 2048", - " value: 5", - " >", - " ethertype_counts <", - " key: 34525", - " value: 5", - " >", - " ip_next_header_counts <", - " key: 6", - " value: 3", - " >", - " ip_next_header_counts <", - " key: 17", - " value: 5", - " >", - " ip_next_header_counts <", - " key: 58", - " value: 2", - " >", - " l2_broadcast_count: 0", - " l2_multicast_count: 0", - " l2_unicast_count: 10", - " no_uid_wakeups: 2", - " non_application_wakeups: 1", - " root_wakeups: 2", - " system_wakeups: 3", - " total_wakeups: 10", - " >", - ">", - "version: 2\n"); - assertEquals(want, got); - } - - @Test - public void testDnsLogging() throws Exception { - asyncDump(100); - - dnsEvent(100, EVENT_GETADDRINFO, 0, 3456); - dnsEvent(100, EVENT_GETADDRINFO, 0, 267); - dnsEvent(100, EVENT_GETHOSTBYNAME, 22, 1230); - dnsEvent(100, EVENT_GETADDRINFO, 3, 45); - dnsEvent(100, EVENT_GETADDRINFO, 1, 2111); - dnsEvent(100, EVENT_GETADDRINFO, 0, 450); - dnsEvent(100, EVENT_GETHOSTBYNAME, 200, 638); - dnsEvent(100, EVENT_GETHOSTBYNAME, 178, 1300); - dnsEvent(101, EVENT_GETADDRINFO, 0, 56); - dnsEvent(101, EVENT_GETADDRINFO, 0, 78); - dnsEvent(101, EVENT_GETADDRINFO, 0, 14); - dnsEvent(101, EVENT_GETHOSTBYNAME, 0, 56); - dnsEvent(101, EVENT_GETADDRINFO, 0, 78); - dnsEvent(101, EVENT_GETADDRINFO, 0, 14); - - String got = flushStatistics(); - String want = String.join("\n", - "dropped_events: 0", - "events <", - " if_name: \"\"", - " link_layer: 4", - " network_id: 100", - " time_ms: 0", - " transports: 2", - " dns_lookup_batch <", - " event_types: 1", - " event_types: 1", - " event_types: 2", - " event_types: 1", - " event_types: 1", - " event_types: 1", - " event_types: 2", - " event_types: 2", - " getaddrinfo_error_count: 0", - " getaddrinfo_query_count: 0", - " gethostbyname_error_count: 0", - " gethostbyname_query_count: 0", - " latencies_ms: 3456", - " latencies_ms: 267", - " latencies_ms: 1230", - " latencies_ms: 45", - " latencies_ms: 2111", - " latencies_ms: 450", - " latencies_ms: 638", - " latencies_ms: 1300", - " return_codes: 0", - " return_codes: 0", - " return_codes: 22", - " return_codes: 3", - " return_codes: 1", - " return_codes: 0", - " return_codes: 200", - " return_codes: 178", - " >", - ">", - "events <", - " if_name: \"\"", - " link_layer: 2", - " network_id: 101", - " time_ms: 0", - " transports: 1", - " dns_lookup_batch <", - " event_types: 1", - " event_types: 1", - " event_types: 1", - " event_types: 2", - " event_types: 1", - " event_types: 1", - " getaddrinfo_error_count: 0", - " getaddrinfo_query_count: 0", - " gethostbyname_error_count: 0", - " gethostbyname_query_count: 0", - " latencies_ms: 56", - " latencies_ms: 78", - " latencies_ms: 14", - " latencies_ms: 56", - " latencies_ms: 78", - " latencies_ms: 14", - " return_codes: 0", - " return_codes: 0", - " return_codes: 0", - " return_codes: 0", - " return_codes: 0", - " return_codes: 0", - " >", - ">", - "version: 2\n"); - assertEquals(want, got); - } - - @Test - public void testConnectLogging() throws Exception { - asyncDump(100); - - final int OK = 0; - Thread[] logActions = { - // ignored - connectEventAction(100, OsConstants.EALREADY, 0, EXAMPLE_IPV4), - connectEventAction(100, OsConstants.EALREADY, 0, EXAMPLE_IPV6), - connectEventAction(100, OsConstants.EINPROGRESS, 0, EXAMPLE_IPV4), - connectEventAction(101, OsConstants.EINPROGRESS, 0, EXAMPLE_IPV6), - connectEventAction(101, OsConstants.EINPROGRESS, 0, EXAMPLE_IPV6), - // valid latencies - connectEventAction(100, OK, 110, EXAMPLE_IPV4), - connectEventAction(100, OK, 23, EXAMPLE_IPV4), - connectEventAction(100, OK, 45, EXAMPLE_IPV4), - connectEventAction(101, OK, 56, EXAMPLE_IPV4), - connectEventAction(101, OK, 523, EXAMPLE_IPV6), - connectEventAction(101, OK, 214, EXAMPLE_IPV6), - connectEventAction(101, OK, 67, EXAMPLE_IPV6), - // errors - connectEventAction(100, OsConstants.EPERM, 0, EXAMPLE_IPV4), - connectEventAction(101, OsConstants.EPERM, 0, EXAMPLE_IPV4), - connectEventAction(100, OsConstants.EAGAIN, 0, EXAMPLE_IPV4), - connectEventAction(100, OsConstants.EACCES, 0, EXAMPLE_IPV4), - connectEventAction(101, OsConstants.EACCES, 0, EXAMPLE_IPV4), - connectEventAction(101, OsConstants.EACCES, 0, EXAMPLE_IPV6), - connectEventAction(100, OsConstants.EADDRINUSE, 0, EXAMPLE_IPV4), - connectEventAction(101, OsConstants.ETIMEDOUT, 0, EXAMPLE_IPV4), - connectEventAction(100, OsConstants.ETIMEDOUT, 0, EXAMPLE_IPV6), - connectEventAction(100, OsConstants.ETIMEDOUT, 0, EXAMPLE_IPV6), - connectEventAction(101, OsConstants.ECONNREFUSED, 0, EXAMPLE_IPV4), - }; - - for (Thread t : logActions) { - t.start(); - } - for (Thread t : logActions) { - t.join(); - } - - String got = flushStatistics(); - String want = String.join("\n", - "dropped_events: 0", - "events <", - " if_name: \"\"", - " link_layer: 4", - " network_id: 100", - " time_ms: 0", - " transports: 2", - " connect_statistics <", - " connect_blocking_count: 3", - " connect_count: 6", - " errnos_counters <", - " key: 1", - " value: 1", - " >", - " errnos_counters <", - " key: 11", - " value: 1", - " >", - " errnos_counters <", - " key: 13", - " value: 1", - " >", - " errnos_counters <", - " key: 98", - " value: 1", - " >", - " errnos_counters <", - " key: 110", - " value: 2", - " >", - " ipv6_addr_count: 1", - " latencies_ms: 23", - " latencies_ms: 45", - " latencies_ms: 110", - " >", - ">", - "events <", - " if_name: \"\"", - " link_layer: 2", - " network_id: 101", - " time_ms: 0", - " transports: 1", - " connect_statistics <", - " connect_blocking_count: 4", - " connect_count: 6", - " errnos_counters <", - " key: 1", - " value: 1", - " >", - " errnos_counters <", - " key: 13", - " value: 2", - " >", - " errnos_counters <", - " key: 110", - " value: 1", - " >", - " errnos_counters <", - " key: 111", - " value: 1", - " >", - " ipv6_addr_count: 5", - " latencies_ms: 56", - " latencies_ms: 67", - " latencies_ms: 214", - " latencies_ms: 523", - " >", - ">", - "version: 2\n"); - assertEquals(want, got); - } - - private void setCapabilities(int netId) { - final ArgumentCaptor networkCallback = - ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class); - verify(mCm).registerNetworkCallback(any(), networkCallback.capture()); - networkCallback.getValue().onCapabilitiesChanged(new Network(netId), - netId == 100 ? CAPABILITIES_WIFI : CAPABILITIES_CELL); - } - - Thread connectEventAction(int netId, int error, int latencyMs, String ipAddr) { - setCapabilities(netId); - return new Thread(() -> { - try { - mService.onConnectEvent(netId, error, latencyMs, ipAddr, 80, 1); - } catch (Exception e) { - fail(e.toString()); - } - }); - } - - void dnsEvent(int netId, int type, int result, int latency) throws Exception { - setCapabilities(netId); - mService.onDnsEvent(netId, type, result, latency, "", null, 0, 0); - } - - void wakeupEvent(String iface, int uid, int ether, int ip, byte[] mac, String srcIp, - String dstIp, int sport, int dport, long now) throws Exception { - String prefix = NetdEventListenerService.WAKEUP_EVENT_IFACE_PREFIX + iface; - mService.onWakeupEvent(prefix, uid, ether, ip, mac, srcIp, dstIp, sport, dport, now); - } - - void asyncDump(long durationMs) throws Exception { - final long stop = System.currentTimeMillis() + durationMs; - final PrintWriter pw = new PrintWriter(new FileOutputStream("/dev/null")); - new Thread(() -> { - while (System.currentTimeMillis() < stop) { - mService.list(pw); - } - }).start(); - } - - // TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto. - String flushStatistics() throws Exception { - IpConnectivityMetrics metricsService = - new IpConnectivityMetrics(mock(Context.class), (ctx) -> 2000); - metricsService.mNetdListener = mService; - - StringWriter buffer = new StringWriter(); - PrintWriter writer = new PrintWriter(buffer); - metricsService.impl.dump(null, writer, new String[]{"flush"}); - byte[] bytes = Base64.decode(buffer.toString(), Base64.DEFAULT); - IpConnectivityLog log = IpConnectivityLog.parseFrom(bytes); - for (IpConnectivityEvent ev : log.events) { - if (ev.getConnectStatistics() == null) { - continue; - } - // Sort repeated fields of connect() events arriving in non-deterministic order. - Arrays.sort(ev.getConnectStatistics().latenciesMs); - Arrays.sort(ev.getConnectStatistics().errnosCounters, - Comparator.comparingInt((p) -> p.key)); - } - return log.toString(); - } - - String[] listNetdEvent() throws Exception { - StringWriter buffer = new StringWriter(); - PrintWriter writer = new PrintWriter(buffer); - mService.list(writer); - return buffer.toString().split("\\n"); - } - - static T[] remove(T[] array, T[] filtered) { - List c = Arrays.asList(filtered); - int next = 0; - for (int i = 0; i < array.length; i++) { - if (c.contains(array[i])) { - continue; - } - array[next++] = array[i]; - } - return Arrays.copyOf(array, next); - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/NetworkNotificationManagerTest.java b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/NetworkNotificationManagerTest.java deleted file mode 100644 index c353cea266bb0..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/NetworkNotificationManagerTest.java +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import static android.app.Notification.FLAG_ONGOING_EVENT; - -import static com.android.server.connectivity.NetworkNotificationManager.NotificationType.LOST_INTERNET; -import static com.android.server.connectivity.NetworkNotificationManager.NotificationType.NETWORK_SWITCH; -import static com.android.server.connectivity.NetworkNotificationManager.NotificationType.NO_INTERNET; -import static com.android.server.connectivity.NetworkNotificationManager.NotificationType.PARTIAL_CONNECTIVITY; -import static com.android.server.connectivity.NetworkNotificationManager.NotificationType.PRIVATE_DNS_BROKEN; -import static com.android.server.connectivity.NetworkNotificationManager.NotificationType.SIGN_IN; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.clearInvocations; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.app.Notification; -import android.app.NotificationManager; -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.res.Resources; -import android.net.ConnectivityResources; -import android.net.NetworkCapabilities; -import android.net.NetworkInfo; -import android.os.UserHandle; -import android.telephony.TelephonyManager; -import android.util.DisplayMetrics; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.connectivity.resources.R; -import com.android.server.connectivity.NetworkNotificationManager.NotificationType; - -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.AdditionalAnswers; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class NetworkNotificationManagerTest { - - private static final String TEST_SSID = "Test SSID"; - private static final String TEST_EXTRA_INFO = "extra"; - static final NetworkCapabilities CELL_CAPABILITIES = new NetworkCapabilities(); - static final NetworkCapabilities WIFI_CAPABILITIES = new NetworkCapabilities(); - static final NetworkCapabilities VPN_CAPABILITIES = new NetworkCapabilities(); - static { - CELL_CAPABILITIES.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR); - CELL_CAPABILITIES.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); - - WIFI_CAPABILITIES.addTransportType(NetworkCapabilities.TRANSPORT_WIFI); - WIFI_CAPABILITIES.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); - WIFI_CAPABILITIES.setSSID(TEST_SSID); - - // Set the underyling network to wifi. - VPN_CAPABILITIES.addTransportType(NetworkCapabilities.TRANSPORT_WIFI); - VPN_CAPABILITIES.addTransportType(NetworkCapabilities.TRANSPORT_VPN); - VPN_CAPABILITIES.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); - VPN_CAPABILITIES.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN); - } - - @Mock Context mCtx; - @Mock Resources mResources; - @Mock DisplayMetrics mDisplayMetrics; - @Mock PackageManager mPm; - @Mock TelephonyManager mTelephonyManager; - @Mock NotificationManager mNotificationManager; - @Mock NetworkAgentInfo mWifiNai; - @Mock NetworkAgentInfo mCellNai; - @Mock NetworkAgentInfo mVpnNai; - @Mock NetworkInfo mNetworkInfo; - ArgumentCaptor mCaptor; - - NetworkNotificationManager mManager; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mCaptor = ArgumentCaptor.forClass(Notification.class); - mWifiNai.networkCapabilities = WIFI_CAPABILITIES; - mWifiNai.networkInfo = mNetworkInfo; - mCellNai.networkCapabilities = CELL_CAPABILITIES; - mCellNai.networkInfo = mNetworkInfo; - mVpnNai.networkCapabilities = VPN_CAPABILITIES; - mVpnNai.networkInfo = mNetworkInfo; - mDisplayMetrics.density = 2.275f; - doReturn(true).when(mVpnNai).isVPN(); - when(mCtx.getResources()).thenReturn(mResources); - when(mCtx.getPackageManager()).thenReturn(mPm); - when(mCtx.getApplicationInfo()).thenReturn(new ApplicationInfo()); - final Context asUserCtx = mock(Context.class, AdditionalAnswers.delegatesTo(mCtx)); - doReturn(UserHandle.ALL).when(asUserCtx).getUser(); - when(mCtx.createContextAsUser(eq(UserHandle.ALL), anyInt())).thenReturn(asUserCtx); - when(mCtx.getSystemService(eq(Context.NOTIFICATION_SERVICE))) - .thenReturn(mNotificationManager); - when(mNetworkInfo.getExtraInfo()).thenReturn(TEST_EXTRA_INFO); - ConnectivityResources.setResourcesContextForTest(mCtx); - when(mResources.getColor(anyInt(), any())).thenReturn(0xFF607D8B); - when(mResources.getDisplayMetrics()).thenReturn(mDisplayMetrics); - - // Come up with some credible-looking transport names. The actual values do not matter. - String[] transportNames = new String[NetworkCapabilities.MAX_TRANSPORT + 1]; - for (int transport = 0; transport <= NetworkCapabilities.MAX_TRANSPORT; transport++) { - transportNames[transport] = NetworkCapabilities.transportNameOf(transport); - } - when(mResources.getStringArray(R.array.network_switch_type_name)) - .thenReturn(transportNames); - - mManager = new NetworkNotificationManager(mCtx, mTelephonyManager); - } - - @After - public void tearDown() { - ConnectivityResources.setResourcesContextForTest(null); - } - - private void verifyTitleByNetwork(final int id, final NetworkAgentInfo nai, final int title) { - final String tag = NetworkNotificationManager.tagFor(id); - mManager.showNotification(id, PRIVATE_DNS_BROKEN, nai, null, null, true); - verify(mNotificationManager, times(1)) - .notify(eq(tag), eq(PRIVATE_DNS_BROKEN.eventId), any()); - final int transportType = NetworkNotificationManager.approximateTransportType(nai); - if (transportType == NetworkCapabilities.TRANSPORT_WIFI) { - verify(mResources, times(1)).getString(eq(title), eq(TEST_EXTRA_INFO)); - } else { - verify(mResources, times(1)).getString(title); - } - verify(mResources, times(1)).getString(eq(R.string.private_dns_broken_detailed)); - } - - @Test - public void testTitleOfPrivateDnsBroken() { - // Test the title of mobile data. - verifyTitleByNetwork(100, mCellNai, R.string.mobile_no_internet); - clearInvocations(mResources); - - // Test the title of wifi. - verifyTitleByNetwork(101, mWifiNai, R.string.wifi_no_internet); - clearInvocations(mResources); - - // Test the title of other networks. - verifyTitleByNetwork(102, mVpnNai, R.string.other_networks_no_internet); - clearInvocations(mResources); - } - - @Test - public void testNotificationsShownAndCleared() { - final int NETWORK_ID_BASE = 100; - List types = Arrays.asList(NotificationType.values()); - List ids = new ArrayList<>(types.size()); - for (int i = 0; i < types.size(); i++) { - ids.add(NETWORK_ID_BASE + i); - } - Collections.shuffle(ids); - Collections.shuffle(types); - - for (int i = 0; i < ids.size(); i++) { - mManager.showNotification(ids.get(i), types.get(i), mWifiNai, mCellNai, null, false); - } - - List idsToClear = new ArrayList<>(ids); - Collections.shuffle(idsToClear); - for (int i = 0; i < ids.size(); i++) { - mManager.clearNotification(idsToClear.get(i)); - } - - for (int i = 0; i < ids.size(); i++) { - final int id = ids.get(i); - final int eventId = types.get(i).eventId; - final String tag = NetworkNotificationManager.tagFor(id); - verify(mNotificationManager, times(1)).notify(eq(tag), eq(eventId), any()); - verify(mNotificationManager, times(1)).cancel(eq(tag), eq(eventId)); - } - } - - @Test - @Ignore - // Ignored because the code under test calls Log.wtf, which crashes the tests on eng builds. - // TODO: re-enable after fixing this (e.g., turn Log.wtf into exceptions that this test catches) - public void testNoInternetNotificationsNotShownForCellular() { - mManager.showNotification(100, NO_INTERNET, mCellNai, mWifiNai, null, false); - mManager.showNotification(101, LOST_INTERNET, mCellNai, mWifiNai, null, false); - - verify(mNotificationManager, never()).notify(any(), anyInt(), any()); - - mManager.showNotification(102, NO_INTERNET, mWifiNai, mCellNai, null, false); - - final int eventId = NO_INTERNET.eventId; - final String tag = NetworkNotificationManager.tagFor(102); - verify(mNotificationManager, times(1)).notify(eq(tag), eq(eventId), any()); - } - - @Test - public void testNotificationsNotShownIfNoInternetCapability() { - mWifiNai.networkCapabilities = new NetworkCapabilities(); - mWifiNai.networkCapabilities .addTransportType(NetworkCapabilities.TRANSPORT_WIFI); - mManager.showNotification(102, NO_INTERNET, mWifiNai, mCellNai, null, false); - mManager.showNotification(103, LOST_INTERNET, mWifiNai, mCellNai, null, false); - mManager.showNotification(104, NETWORK_SWITCH, mWifiNai, mCellNai, null, false); - - verify(mNotificationManager, never()).notify(any(), anyInt(), any()); - } - - private void assertNotification(NotificationType type, boolean ongoing) { - final int id = 101; - final String tag = NetworkNotificationManager.tagFor(id); - final ArgumentCaptor noteCaptor = ArgumentCaptor.forClass(Notification.class); - mManager.showNotification(id, type, mWifiNai, mCellNai, null, false); - verify(mNotificationManager, times(1)).notify(eq(tag), eq(type.eventId), - noteCaptor.capture()); - - assertEquals("Notification ongoing flag should be " + (ongoing ? "set" : "unset"), - ongoing, (noteCaptor.getValue().flags & FLAG_ONGOING_EVENT) != 0); - } - - @Test - public void testDuplicatedNotificationsNoInternetThenSignIn() { - final int id = 101; - final String tag = NetworkNotificationManager.tagFor(id); - - // Show first NO_INTERNET - assertNotification(NO_INTERNET, false /* ongoing */); - - // Captive portal detection triggers SIGN_IN a bit later, clearing the previous NO_INTERNET - assertNotification(SIGN_IN, false /* ongoing */); - verify(mNotificationManager, times(1)).cancel(eq(tag), eq(NO_INTERNET.eventId)); - - // Network disconnects - mManager.clearNotification(id); - verify(mNotificationManager, times(1)).cancel(eq(tag), eq(SIGN_IN.eventId)); - } - - @Test - public void testOngoingSignInNotification() { - doReturn(true).when(mResources).getBoolean(R.bool.config_ongoingSignInNotification); - final int id = 101; - final String tag = NetworkNotificationManager.tagFor(id); - - // Show first NO_INTERNET - assertNotification(NO_INTERNET, false /* ongoing */); - - // Captive portal detection triggers SIGN_IN a bit later, clearing the previous NO_INTERNET - assertNotification(SIGN_IN, true /* ongoing */); - verify(mNotificationManager, times(1)).cancel(eq(tag), eq(NO_INTERNET.eventId)); - - // Network disconnects - mManager.clearNotification(id); - verify(mNotificationManager, times(1)).cancel(eq(tag), eq(SIGN_IN.eventId)); - } - - @Test - public void testDuplicatedNotificationsSignInThenNoInternet() { - final int id = 101; - final String tag = NetworkNotificationManager.tagFor(id); - - // Show first SIGN_IN - mManager.showNotification(id, SIGN_IN, mWifiNai, mCellNai, null, false); - verify(mNotificationManager, times(1)).notify(eq(tag), eq(SIGN_IN.eventId), any()); - reset(mNotificationManager); - - // NO_INTERNET arrives after, but is ignored. - mManager.showNotification(id, NO_INTERNET, mWifiNai, mCellNai, null, false); - verify(mNotificationManager, never()).cancel(any(), anyInt()); - verify(mNotificationManager, never()).notify(any(), anyInt(), any()); - - // Network disconnects - mManager.clearNotification(id); - verify(mNotificationManager, times(1)).cancel(eq(tag), eq(SIGN_IN.eventId)); - } - - @Test - public void testClearNotificationByType() { - final int id = 101; - final String tag = NetworkNotificationManager.tagFor(id); - - // clearNotification(int id, NotificationType notifyType) will check if given type is equal - // to previous type or not. If they are equal then clear the notification; if they are not - // equal then return. - mManager.showNotification(id, NO_INTERNET, mWifiNai, mCellNai, null, false); - verify(mNotificationManager, times(1)).notify(eq(tag), eq(NO_INTERNET.eventId), any()); - - // Previous notification is NO_INTERNET and given type is NO_INTERNET too. The notification - // should be cleared. - mManager.clearNotification(id, NO_INTERNET); - verify(mNotificationManager, times(1)).cancel(eq(tag), eq(NO_INTERNET.eventId)); - - // SIGN_IN is popped-up. - mManager.showNotification(id, SIGN_IN, mWifiNai, mCellNai, null, false); - verify(mNotificationManager, times(1)).notify(eq(tag), eq(SIGN_IN.eventId), any()); - - // The notification type is not matching previous one, PARTIAL_CONNECTIVITY won't be - // cleared. - mManager.clearNotification(id, PARTIAL_CONNECTIVITY); - verify(mNotificationManager, never()).cancel(eq(tag), eq(PARTIAL_CONNECTIVITY.eventId)); - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/NetworkOfferTest.kt b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/NetworkOfferTest.kt deleted file mode 100644 index 409f8c3099351..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/NetworkOfferTest.kt +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity - -import android.net.INetworkOfferCallback -import android.net.NetworkCapabilities -import android.net.NetworkRequest -import android.net.NetworkScore.KEEP_CONNECTED_NONE -import androidx.test.filters.SmallTest -import androidx.test.runner.AndroidJUnit4 -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.ArgumentMatchers.eq -import org.mockito.Mockito.mock -import org.mockito.Mockito.verify -import kotlin.test.assertFalse -import kotlin.test.assertTrue - -const val POLICY_NONE = 0L - -@RunWith(AndroidJUnit4::class) -@SmallTest -class NetworkOfferTest { - val mockCallback = mock(INetworkOfferCallback::class.java) - - @Test - fun testOfferNeededUnneeded() { - val score = FullScore(50, POLICY_NONE, KEEP_CONNECTED_NONE) - val offer = NetworkOffer(score, NetworkCapabilities.Builder().build(), mockCallback, - 1 /* providerId */) - val request1 = mock(NetworkRequest::class.java) - val request2 = mock(NetworkRequest::class.java) - offer.onNetworkNeeded(request1) - verify(mockCallback).onNetworkNeeded(eq(request1)) - assertTrue(offer.neededFor(request1)) - assertFalse(offer.neededFor(request2)) - - offer.onNetworkNeeded(request2) - verify(mockCallback).onNetworkNeeded(eq(request2)) - assertTrue(offer.neededFor(request1)) - assertTrue(offer.neededFor(request2)) - - // Note that the framework never calls onNetworkNeeded multiple times with the same - // request without calling onNetworkUnneeded first. It would be incorrect usage and the - // behavior would be undefined, so there is nothing to test. - - offer.onNetworkUnneeded(request1) - verify(mockCallback).onNetworkUnneeded(eq(request1)) - assertFalse(offer.neededFor(request1)) - assertTrue(offer.neededFor(request2)) - - offer.onNetworkUnneeded(request2) - verify(mockCallback).onNetworkUnneeded(eq(request2)) - assertFalse(offer.neededFor(request1)) - assertFalse(offer.neededFor(request2)) - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/NetworkRankerTest.kt b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/NetworkRankerTest.kt deleted file mode 100644 index 4408958734404..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/NetworkRankerTest.kt +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity - -import android.net.NetworkCapabilities -import android.net.NetworkCapabilities.TRANSPORT_CELLULAR -import android.net.NetworkCapabilities.TRANSPORT_WIFI -import android.net.NetworkScore.KEEP_CONNECTED_NONE -import android.net.NetworkScore.POLICY_EXITING -import android.net.NetworkScore.POLICY_TRANSPORT_PRIMARY -import android.net.NetworkScore.POLICY_YIELD_TO_BAD_WIFI -import android.os.Build -import androidx.test.filters.SmallTest -import com.android.server.connectivity.FullScore.POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD -import com.android.server.connectivity.FullScore.POLICY_IS_VALIDATED -import com.android.testutils.DevSdkIgnoreRule -import com.android.testutils.DevSdkIgnoreRunner -import org.junit.Test -import org.junit.runner.RunWith -import kotlin.test.assertEquals - -private fun score(vararg policies: Int) = FullScore(0, - policies.fold(0L) { acc, e -> acc or (1L shl e) }, KEEP_CONNECTED_NONE) -private fun caps(transport: Int) = NetworkCapabilities.Builder().addTransportType(transport).build() - -@SmallTest -@RunWith(DevSdkIgnoreRunner::class) -@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R) -class NetworkRankerTest { - private val mRanker = NetworkRanker() - - private class TestScore(private val sc: FullScore, private val nc: NetworkCapabilities) - : NetworkRanker.Scoreable { - override fun getScore() = sc - override fun getCapsNoCopy(): NetworkCapabilities = nc - } - - @Test - fun testYieldToBadWiFiOneCell() { - // Only cell, it wins - val winner = TestScore(score(POLICY_YIELD_TO_BAD_WIFI, POLICY_IS_VALIDATED), - caps(TRANSPORT_CELLULAR)) - val scores = listOf(winner) - assertEquals(winner, mRanker.getBestNetworkByPolicy(scores, null)) - } - - @Test - fun testYieldToBadWiFiOneCellOneBadWiFi() { - // Bad wifi wins against yielding validated cell - val winner = TestScore(score(POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD), - caps(TRANSPORT_WIFI)) - val scores = listOf( - winner, - TestScore(score(POLICY_YIELD_TO_BAD_WIFI, POLICY_IS_VALIDATED), - caps(TRANSPORT_CELLULAR)) - ) - assertEquals(winner, mRanker.getBestNetworkByPolicy(scores, null)) - } - - @Test - fun testYieldToBadWiFiOneCellTwoBadWiFi() { - // Bad wifi wins against yielding validated cell. Prefer the one that's primary. - val winner = TestScore(score(POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD, - POLICY_TRANSPORT_PRIMARY), caps(TRANSPORT_WIFI)) - val scores = listOf( - winner, - TestScore(score(POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD), - caps(TRANSPORT_WIFI)), - TestScore(score(POLICY_YIELD_TO_BAD_WIFI, POLICY_IS_VALIDATED), - caps(TRANSPORT_CELLULAR)) - ) - assertEquals(winner, mRanker.getBestNetworkByPolicy(scores, null)) - } - - @Test - fun testYieldToBadWiFiOneCellTwoBadWiFiOneNotAvoided() { - // Bad wifi ever validated wins against bad wifi that never was validated (or was - // avoided when bad). - val winner = TestScore(score(POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD), - caps(TRANSPORT_WIFI)) - val scores = listOf( - winner, - TestScore(score(), caps(TRANSPORT_WIFI)), - TestScore(score(POLICY_YIELD_TO_BAD_WIFI, POLICY_IS_VALIDATED), - caps(TRANSPORT_CELLULAR)) - ) - assertEquals(winner, mRanker.getBestNetworkByPolicy(scores, null)) - } - - @Test - fun testYieldToBadWiFiOneCellOneBadWiFiOneGoodWiFi() { - // Good wifi wins - val winner = TestScore(score(POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD, - POLICY_IS_VALIDATED), caps(TRANSPORT_WIFI)) - val scores = listOf( - winner, - TestScore(score(POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD, - POLICY_TRANSPORT_PRIMARY), caps(TRANSPORT_WIFI)), - TestScore(score(POLICY_YIELD_TO_BAD_WIFI, POLICY_IS_VALIDATED), - caps(TRANSPORT_CELLULAR)) - ) - assertEquals(winner, mRanker.getBestNetworkByPolicy(scores, null)) - } - - @Test - fun testYieldToBadWiFiTwoCellsOneBadWiFi() { - // Cell that doesn't yield wins over cell that yields and bad wifi - val winner = TestScore(score(POLICY_IS_VALIDATED), caps(TRANSPORT_CELLULAR)) - val scores = listOf( - winner, - TestScore(score(POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD, - POLICY_TRANSPORT_PRIMARY), caps(TRANSPORT_WIFI)), - TestScore(score(POLICY_YIELD_TO_BAD_WIFI, POLICY_IS_VALIDATED), - caps(TRANSPORT_CELLULAR)) - ) - assertEquals(winner, mRanker.getBestNetworkByPolicy(scores, null)) - } - - @Test - fun testYieldToBadWiFiTwoCellsOneBadWiFiOneGoodWiFi() { - // Good wifi wins over cell that doesn't yield and cell that yields - val winner = TestScore(score(POLICY_IS_VALIDATED), caps(TRANSPORT_WIFI)) - val scores = listOf( - winner, - TestScore(score(POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD, - POLICY_TRANSPORT_PRIMARY), caps(TRANSPORT_WIFI)), - TestScore(score(POLICY_IS_VALIDATED), caps(TRANSPORT_CELLULAR)), - TestScore(score(POLICY_YIELD_TO_BAD_WIFI, POLICY_IS_VALIDATED), - caps(TRANSPORT_CELLULAR)) - ) - assertEquals(winner, mRanker.getBestNetworkByPolicy(scores, null)) - } - - @Test - fun testYieldToBadWiFiOneExitingGoodWiFi() { - // Yielding cell wins over good exiting wifi - val winner = TestScore(score(POLICY_YIELD_TO_BAD_WIFI, POLICY_IS_VALIDATED), - caps(TRANSPORT_CELLULAR)) - val scores = listOf( - winner, - TestScore(score(POLICY_IS_VALIDATED, POLICY_EXITING), caps(TRANSPORT_WIFI)) - ) - assertEquals(winner, mRanker.getBestNetworkByPolicy(scores, null)) - } - - @Test - fun testYieldToBadWiFiOneExitingBadWiFi() { - // Yielding cell wins over bad exiting wifi - val winner = TestScore(score(POLICY_YIELD_TO_BAD_WIFI, POLICY_IS_VALIDATED), - caps(TRANSPORT_CELLULAR)) - val scores = listOf( - winner, - TestScore(score(POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD, - POLICY_EXITING), caps(TRANSPORT_WIFI)) - ) - assertEquals(winner, mRanker.getBestNetworkByPolicy(scores, null)) - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java deleted file mode 100644 index c75618f43cdeb..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java +++ /dev/null @@ -1,1001 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.server.connectivity; - -import static android.Manifest.permission.CHANGE_NETWORK_STATE; -import static android.Manifest.permission.CHANGE_WIFI_STATE; -import static android.Manifest.permission.CONNECTIVITY_INTERNAL; -import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS; -import static android.Manifest.permission.INTERNET; -import static android.Manifest.permission.NETWORK_STACK; -import static android.Manifest.permission.UPDATE_DEVICE_STATS; -import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_OEM; -import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRODUCT; -import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_VENDOR; -import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; -import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_REQUIRED; -import static android.content.pm.PackageManager.GET_PERMISSIONS; -import static android.content.pm.PackageManager.MATCH_ANY_USER; -import static android.net.ConnectivitySettingsManager.APPS_ALLOWED_ON_RESTRICTED_NETWORKS; -import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; -import static android.os.Process.SYSTEM_UID; - -import static com.android.server.connectivity.PermissionMonitor.NETWORK; -import static com.android.server.connectivity.PermissionMonitor.SYSTEM; - -import static junit.framework.Assert.fail; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.AdditionalMatchers.aryEq; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.database.ContentObserver; -import android.net.INetd; -import android.net.UidRange; -import android.net.Uri; -import android.os.Build; -import android.os.SystemConfigManager; -import android.os.UserHandle; -import android.os.UserManager; -import android.util.ArraySet; -import android.util.SparseIntArray; - -import androidx.test.InstrumentationRegistry; -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.AdditionalAnswers; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.invocation.InvocationOnMock; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Set; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class PermissionMonitorTest { - private static final UserHandle MOCK_USER1 = UserHandle.of(0); - private static final UserHandle MOCK_USER2 = UserHandle.of(1); - private static final int MOCK_UID1 = 10001; - private static final int MOCK_UID2 = 10086; - private static final int SYSTEM_UID1 = 1000; - private static final int SYSTEM_UID2 = 1008; - private static final int VPN_UID = 10002; - private static final String REAL_SYSTEM_PACKAGE_NAME = "android"; - private static final String MOCK_PACKAGE1 = "appName1"; - private static final String MOCK_PACKAGE2 = "appName2"; - private static final String SYSTEM_PACKAGE1 = "sysName1"; - private static final String SYSTEM_PACKAGE2 = "sysName2"; - private static final String PARTITION_SYSTEM = "system"; - private static final String PARTITION_OEM = "oem"; - private static final String PARTITION_PRODUCT = "product"; - private static final String PARTITION_VENDOR = "vendor"; - private static final int VERSION_P = Build.VERSION_CODES.P; - private static final int VERSION_Q = Build.VERSION_CODES.Q; - - @Mock private Context mContext; - @Mock private PackageManager mPackageManager; - @Mock private INetd mNetdService; - @Mock private UserManager mUserManager; - @Mock private PermissionMonitor.Dependencies mDeps; - @Mock private SystemConfigManager mSystemConfigManager; - - private PermissionMonitor mPermissionMonitor; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - when(mContext.getPackageManager()).thenReturn(mPackageManager); - when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager); - when(mUserManager.getUserHandles(eq(true))).thenReturn( - Arrays.asList(new UserHandle[] { MOCK_USER1, MOCK_USER2 })); - when(mContext.getSystemServiceName(SystemConfigManager.class)) - .thenReturn(Context.SYSTEM_CONFIG_SERVICE); - when(mContext.getSystemService(Context.SYSTEM_CONFIG_SERVICE)) - .thenReturn(mSystemConfigManager); - when(mSystemConfigManager.getSystemPermissionUids(anyString())).thenReturn(new int[0]); - final Context asUserCtx = mock(Context.class, AdditionalAnswers.delegatesTo(mContext)); - doReturn(UserHandle.ALL).when(asUserCtx).getUser(); - when(mContext.createContextAsUser(eq(UserHandle.ALL), anyInt())).thenReturn(asUserCtx); - when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn(new ArraySet<>()); - - mPermissionMonitor = spy(new PermissionMonitor(mContext, mNetdService, mDeps)); - - when(mPackageManager.getInstalledPackages(anyInt())).thenReturn(/* empty app list */ null); - mPermissionMonitor.startMonitoring(); - } - - private boolean hasRestrictedNetworkPermission(String partition, int targetSdkVersion, int uid, - String... permissions) { - return hasRestrictedNetworkPermission( - partition, targetSdkVersion, "" /* packageName */, uid, permissions); - } - - private boolean hasRestrictedNetworkPermission(String partition, int targetSdkVersion, - String packageName, int uid, String... permissions) { - final PackageInfo packageInfo = - packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, permissions, partition); - packageInfo.packageName = packageName; - packageInfo.applicationInfo.targetSdkVersion = targetSdkVersion; - packageInfo.applicationInfo.uid = uid; - return mPermissionMonitor.hasRestrictedNetworkPermission(packageInfo); - } - - private static PackageInfo systemPackageInfoWithPermissions(String... permissions) { - return packageInfoWithPermissions( - REQUESTED_PERMISSION_GRANTED, permissions, PARTITION_SYSTEM); - } - - private static PackageInfo vendorPackageInfoWithPermissions(String... permissions) { - return packageInfoWithPermissions( - REQUESTED_PERMISSION_GRANTED, permissions, PARTITION_VENDOR); - } - - private static PackageInfo packageInfoWithPermissions(int permissionsFlags, - String[] permissions, String partition) { - int[] requestedPermissionsFlags = new int[permissions.length]; - for (int i = 0; i < permissions.length; i++) { - requestedPermissionsFlags[i] = permissionsFlags; - } - final PackageInfo packageInfo = new PackageInfo(); - packageInfo.requestedPermissions = permissions; - packageInfo.applicationInfo = new ApplicationInfo(); - packageInfo.requestedPermissionsFlags = requestedPermissionsFlags; - int privateFlags = 0; - switch (partition) { - case PARTITION_OEM: - privateFlags = PRIVATE_FLAG_OEM; - break; - case PARTITION_PRODUCT: - privateFlags = PRIVATE_FLAG_PRODUCT; - break; - case PARTITION_VENDOR: - privateFlags = PRIVATE_FLAG_VENDOR; - break; - } - packageInfo.applicationInfo.privateFlags = privateFlags; - return packageInfo; - } - - private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid, - UserHandle user) { - final PackageInfo pkgInfo; - if (hasSystemPermission) { - pkgInfo = systemPackageInfoWithPermissions( - CHANGE_NETWORK_STATE, NETWORK_STACK, CONNECTIVITY_USE_RESTRICTED_NETWORKS); - } else { - pkgInfo = packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, new String[] {}, ""); - } - pkgInfo.applicationInfo.uid = user.getUid(UserHandle.getAppId(uid)); - return pkgInfo; - } - - @Test - public void testHasPermission() { - PackageInfo app = systemPackageInfoWithPermissions(); - assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE)); - assertFalse(mPermissionMonitor.hasPermission(app, NETWORK_STACK)); - assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); - assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_INTERNAL)); - - app = systemPackageInfoWithPermissions(CHANGE_NETWORK_STATE, NETWORK_STACK); - assertTrue(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE)); - assertTrue(mPermissionMonitor.hasPermission(app, NETWORK_STACK)); - assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); - assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_INTERNAL)); - - app = systemPackageInfoWithPermissions( - CONNECTIVITY_USE_RESTRICTED_NETWORKS, CONNECTIVITY_INTERNAL); - assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE)); - assertFalse(mPermissionMonitor.hasPermission(app, NETWORK_STACK)); - assertTrue(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); - assertTrue(mPermissionMonitor.hasPermission(app, CONNECTIVITY_INTERNAL)); - - app = packageInfoWithPermissions(REQUESTED_PERMISSION_REQUIRED, new String[] { - CONNECTIVITY_USE_RESTRICTED_NETWORKS, CONNECTIVITY_INTERNAL, NETWORK_STACK }, - PARTITION_SYSTEM); - assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE)); - assertFalse(mPermissionMonitor.hasPermission(app, NETWORK_STACK)); - assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); - assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_INTERNAL)); - - app = systemPackageInfoWithPermissions(CHANGE_NETWORK_STATE); - app.requestedPermissions = null; - assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE)); - - app = systemPackageInfoWithPermissions(CHANGE_NETWORK_STATE); - app.requestedPermissionsFlags = null; - assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE)); - } - - @Test - public void testIsVendorApp() { - PackageInfo app = systemPackageInfoWithPermissions(); - assertFalse(mPermissionMonitor.isVendorApp(app.applicationInfo)); - app = packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, - new String[] {}, PARTITION_OEM); - assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo)); - app = packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, - new String[] {}, PARTITION_PRODUCT); - assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo)); - app = vendorPackageInfoWithPermissions(); - assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo)); - } - - @Test - public void testHasNetworkPermission() { - PackageInfo app = systemPackageInfoWithPermissions(); - assertFalse(mPermissionMonitor.hasNetworkPermission(app)); - app = systemPackageInfoWithPermissions(CHANGE_NETWORK_STATE); - assertTrue(mPermissionMonitor.hasNetworkPermission(app)); - app = systemPackageInfoWithPermissions(NETWORK_STACK); - assertFalse(mPermissionMonitor.hasNetworkPermission(app)); - app = systemPackageInfoWithPermissions(CONNECTIVITY_USE_RESTRICTED_NETWORKS); - assertFalse(mPermissionMonitor.hasNetworkPermission(app)); - app = systemPackageInfoWithPermissions(CONNECTIVITY_INTERNAL); - assertFalse(mPermissionMonitor.hasNetworkPermission(app)); - } - - @Test - public void testHasRestrictedNetworkPermission() { - assertFalse(hasRestrictedNetworkPermission(PARTITION_SYSTEM, VERSION_P, MOCK_UID1)); - assertFalse(hasRestrictedNetworkPermission( - PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CHANGE_NETWORK_STATE)); - assertTrue(hasRestrictedNetworkPermission( - PARTITION_SYSTEM, VERSION_P, MOCK_UID1, NETWORK_STACK)); - assertFalse(hasRestrictedNetworkPermission( - PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CONNECTIVITY_INTERNAL)); - assertTrue(hasRestrictedNetworkPermission( - PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); - assertFalse(hasRestrictedNetworkPermission( - PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CHANGE_WIFI_STATE)); - assertTrue(hasRestrictedNetworkPermission( - PARTITION_SYSTEM, VERSION_P, MOCK_UID1, PERMISSION_MAINLINE_NETWORK_STACK)); - - assertFalse(hasRestrictedNetworkPermission(PARTITION_SYSTEM, VERSION_Q, MOCK_UID1)); - assertFalse(hasRestrictedNetworkPermission( - PARTITION_SYSTEM, VERSION_Q, MOCK_UID1, CONNECTIVITY_INTERNAL)); - } - - @Test - public void testHasRestrictedNetworkPermissionSystemUid() { - doReturn(VERSION_P).when(mDeps).getDeviceFirstSdkInt(); - assertTrue(hasRestrictedNetworkPermission(PARTITION_SYSTEM, VERSION_P, SYSTEM_UID)); - assertTrue(hasRestrictedNetworkPermission( - PARTITION_SYSTEM, VERSION_P, SYSTEM_UID, CONNECTIVITY_INTERNAL)); - assertTrue(hasRestrictedNetworkPermission( - PARTITION_SYSTEM, VERSION_P, SYSTEM_UID, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); - - doReturn(VERSION_Q).when(mDeps).getDeviceFirstSdkInt(); - assertFalse(hasRestrictedNetworkPermission(PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID)); - assertFalse(hasRestrictedNetworkPermission( - PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID, CONNECTIVITY_INTERNAL)); - assertTrue(hasRestrictedNetworkPermission( - PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); - } - - @Test - public void testHasRestrictedNetworkPermissionVendorApp() { - assertTrue(hasRestrictedNetworkPermission(PARTITION_VENDOR, VERSION_P, MOCK_UID1)); - assertTrue(hasRestrictedNetworkPermission( - PARTITION_VENDOR, VERSION_P, MOCK_UID1, CHANGE_NETWORK_STATE)); - assertTrue(hasRestrictedNetworkPermission( - PARTITION_VENDOR, VERSION_P, MOCK_UID1, NETWORK_STACK)); - assertTrue(hasRestrictedNetworkPermission( - PARTITION_VENDOR, VERSION_P, MOCK_UID1, CONNECTIVITY_INTERNAL)); - assertTrue(hasRestrictedNetworkPermission( - PARTITION_VENDOR, VERSION_P, MOCK_UID1, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); - assertTrue(hasRestrictedNetworkPermission( - PARTITION_VENDOR, VERSION_P, MOCK_UID1, CHANGE_WIFI_STATE)); - - assertFalse(hasRestrictedNetworkPermission(PARTITION_VENDOR, VERSION_Q, MOCK_UID1)); - assertFalse(hasRestrictedNetworkPermission( - PARTITION_VENDOR, VERSION_Q, MOCK_UID1, CONNECTIVITY_INTERNAL)); - assertFalse(hasRestrictedNetworkPermission( - PARTITION_VENDOR, VERSION_Q, MOCK_UID1, CHANGE_NETWORK_STATE)); - } - - @Test - public void testHasRestrictedNetworkPermissionAppAllowedOnRestrictedNetworks() { - mPermissionMonitor.updateAppsAllowedOnRestrictedNetworks( - new ArraySet<>(new String[] { MOCK_PACKAGE1 })); - assertTrue(hasRestrictedNetworkPermission( - PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE1, MOCK_UID1)); - assertTrue(hasRestrictedNetworkPermission( - PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE1, MOCK_UID1, CHANGE_NETWORK_STATE)); - assertTrue(hasRestrictedNetworkPermission( - PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE1, MOCK_UID1, CONNECTIVITY_INTERNAL)); - - assertFalse(hasRestrictedNetworkPermission( - PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE2, MOCK_UID1)); - assertFalse(hasRestrictedNetworkPermission( - PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE2, MOCK_UID1, CHANGE_NETWORK_STATE)); - assertFalse(hasRestrictedNetworkPermission( - PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE2, MOCK_UID1, CONNECTIVITY_INTERNAL)); - - } - - private boolean wouldBeCarryoverPackage(String partition, int targetSdkVersion, int uid) { - final PackageInfo packageInfo = packageInfoWithPermissions( - REQUESTED_PERMISSION_GRANTED, new String[] {}, partition); - packageInfo.applicationInfo.targetSdkVersion = targetSdkVersion; - packageInfo.applicationInfo.uid = uid; - return mPermissionMonitor.isCarryoverPackage(packageInfo.applicationInfo); - } - - @Test - public void testIsCarryoverPackage() { - doReturn(VERSION_P).when(mDeps).getDeviceFirstSdkInt(); - assertTrue(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_P, SYSTEM_UID)); - assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_P, SYSTEM_UID)); - assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_P, MOCK_UID1)); - assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_P, MOCK_UID1)); - assertTrue(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID)); - assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_Q, SYSTEM_UID)); - assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_Q, MOCK_UID1)); - assertFalse(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_Q, MOCK_UID1)); - - doReturn(VERSION_Q).when(mDeps).getDeviceFirstSdkInt(); - assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_P, SYSTEM_UID)); - assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_P, SYSTEM_UID)); - assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_P, MOCK_UID1)); - assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_P, MOCK_UID1)); - assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID)); - assertFalse(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_Q, SYSTEM_UID)); - assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_Q, MOCK_UID1)); - assertFalse(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_Q, MOCK_UID1)); - - assertFalse(wouldBeCarryoverPackage(PARTITION_OEM, VERSION_Q, SYSTEM_UID)); - assertFalse(wouldBeCarryoverPackage(PARTITION_PRODUCT, VERSION_Q, SYSTEM_UID)); - assertFalse(wouldBeCarryoverPackage(PARTITION_OEM, VERSION_Q, MOCK_UID1)); - assertFalse(wouldBeCarryoverPackage(PARTITION_PRODUCT, VERSION_Q, MOCK_UID1)); - } - - private boolean wouldBeAppAllowedOnRestrictedNetworks(String packageName) { - final PackageInfo packageInfo = new PackageInfo(); - packageInfo.packageName = packageName; - return mPermissionMonitor.isAppAllowedOnRestrictedNetworks(packageInfo); - } - - @Test - public void testIsAppAllowedOnRestrictedNetworks() { - mPermissionMonitor.updateAppsAllowedOnRestrictedNetworks(new ArraySet<>()); - assertFalse(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE1)); - assertFalse(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE2)); - - mPermissionMonitor.updateAppsAllowedOnRestrictedNetworks( - new ArraySet<>(new String[] { MOCK_PACKAGE1 })); - assertTrue(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE1)); - assertFalse(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE2)); - - mPermissionMonitor.updateAppsAllowedOnRestrictedNetworks( - new ArraySet<>(new String[] { MOCK_PACKAGE2 })); - assertFalse(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE1)); - assertTrue(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE2)); - - mPermissionMonitor.updateAppsAllowedOnRestrictedNetworks( - new ArraySet<>(new String[] { "com.android.test" })); - assertFalse(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE1)); - assertFalse(wouldBeAppAllowedOnRestrictedNetworks(MOCK_PACKAGE2)); - } - - private void assertBackgroundPermission(boolean hasPermission, String name, int uid, - String... permissions) throws Exception { - when(mPackageManager.getPackageInfo(eq(name), anyInt())) - .thenReturn(packageInfoWithPermissions( - REQUESTED_PERMISSION_GRANTED, permissions, PARTITION_SYSTEM)); - mPermissionMonitor.onPackageAdded(name, uid); - assertEquals(hasPermission, mPermissionMonitor.hasUseBackgroundNetworksPermission(uid)); - } - - @Test - public void testHasUseBackgroundNetworksPermission() throws Exception { - assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(SYSTEM_UID)); - assertBackgroundPermission(false, SYSTEM_PACKAGE1, SYSTEM_UID); - assertBackgroundPermission(false, SYSTEM_PACKAGE1, SYSTEM_UID, CONNECTIVITY_INTERNAL); - assertBackgroundPermission(true, SYSTEM_PACKAGE1, SYSTEM_UID, CHANGE_NETWORK_STATE); - assertBackgroundPermission(true, SYSTEM_PACKAGE1, SYSTEM_UID, NETWORK_STACK); - - assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID1)); - assertBackgroundPermission(false, MOCK_PACKAGE1, MOCK_UID1); - assertBackgroundPermission(true, MOCK_PACKAGE1, MOCK_UID1, - CONNECTIVITY_USE_RESTRICTED_NETWORKS); - - assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID2)); - assertBackgroundPermission(false, MOCK_PACKAGE2, MOCK_UID2); - assertBackgroundPermission(false, MOCK_PACKAGE2, MOCK_UID2, - CONNECTIVITY_INTERNAL); - assertBackgroundPermission(true, MOCK_PACKAGE2, MOCK_UID2, NETWORK_STACK); - } - - private class NetdMonitor { - private final HashMap mApps = new HashMap<>(); - - NetdMonitor(INetd mockNetd) throws Exception { - // Add hook to verify and track result of setPermission. - doAnswer((InvocationOnMock invocation) -> { - final Object[] args = invocation.getArguments(); - final Boolean isSystem = args[0].equals(INetd.PERMISSION_SYSTEM); - for (final int uid : (int[]) args[1]) { - // TODO: Currently, permission monitor will send duplicate commands for each uid - // corresponding to each user. Need to fix that and uncomment below test. - // if (mApps.containsKey(uid) && mApps.get(uid) == isSystem) { - // fail("uid " + uid + " is already set to " + isSystem); - // } - mApps.put(uid, isSystem); - } - return null; - }).when(mockNetd).networkSetPermissionForUser(anyInt(), any(int[].class)); - - // Add hook to verify and track result of clearPermission. - doAnswer((InvocationOnMock invocation) -> { - final Object[] args = invocation.getArguments(); - for (final int uid : (int[]) args[0]) { - // TODO: Currently, permission monitor will send duplicate commands for each uid - // corresponding to each user. Need to fix that and uncomment below test. - // if (!mApps.containsKey(uid)) { - // fail("uid " + uid + " does not exist."); - // } - mApps.remove(uid); - } - return null; - }).when(mockNetd).networkClearPermissionForUser(any(int[].class)); - } - - public void expectPermission(Boolean permission, UserHandle[] users, int[] apps) { - for (final UserHandle user : users) { - for (final int app : apps) { - final int uid = user.getUid(app); - if (!mApps.containsKey(uid)) { - fail("uid " + uid + " does not exist."); - } - if (mApps.get(uid) != permission) { - fail("uid " + uid + " has wrong permission: " + permission); - } - } - } - } - - public void expectNoPermission(UserHandle[] users, int[] apps) { - for (final UserHandle user : users) { - for (final int app : apps) { - final int uid = user.getUid(app); - if (mApps.containsKey(uid)) { - fail("uid " + uid + " has listed permissions, expected none."); - } - } - } - } - } - - @Test - public void testUserAndPackageAddRemove() throws Exception { - final NetdMonitor mNetdMonitor = new NetdMonitor(mNetdService); - - // MOCK_UID1: MOCK_PACKAGE1 only has network permission. - // SYSTEM_UID: SYSTEM_PACKAGE1 has system permission. - // SYSTEM_UID: SYSTEM_PACKAGE2 only has network permission. - doReturn(SYSTEM).when(mPermissionMonitor).highestPermissionForUid(eq(SYSTEM), anyString()); - doReturn(SYSTEM).when(mPermissionMonitor).highestPermissionForUid(any(), - eq(SYSTEM_PACKAGE1)); - doReturn(NETWORK).when(mPermissionMonitor).highestPermissionForUid(any(), - eq(SYSTEM_PACKAGE2)); - doReturn(NETWORK).when(mPermissionMonitor).highestPermissionForUid(any(), - eq(MOCK_PACKAGE1)); - - // Add SYSTEM_PACKAGE2, expect only have network permission. - mPermissionMonitor.onUserAdded(MOCK_USER1); - addPackageForUsers(new UserHandle[]{MOCK_USER1}, SYSTEM_PACKAGE2, SYSTEM_UID); - mNetdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1}, new int[]{SYSTEM_UID}); - - // Add SYSTEM_PACKAGE1, expect permission escalate. - addPackageForUsers(new UserHandle[]{MOCK_USER1}, SYSTEM_PACKAGE1, SYSTEM_UID); - mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{SYSTEM_UID}); - - mPermissionMonitor.onUserAdded(MOCK_USER2); - mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2}, - new int[]{SYSTEM_UID}); - - addPackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_PACKAGE1, MOCK_UID1); - mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2}, - new int[]{SYSTEM_UID}); - mNetdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1, MOCK_USER2}, - new int[]{MOCK_UID1}); - - // Remove MOCK_UID1, expect no permission left for all user. - mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1); - removePackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_PACKAGE1, MOCK_UID1); - mNetdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1, MOCK_USER2}, - new int[]{MOCK_UID1}); - - // Remove SYSTEM_PACKAGE1, expect permission downgrade. - when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{SYSTEM_PACKAGE2}); - removePackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2}, - SYSTEM_PACKAGE1, SYSTEM_UID); - mNetdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1, MOCK_USER2}, - new int[]{SYSTEM_UID}); - - mPermissionMonitor.onUserRemoved(MOCK_USER1); - mNetdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER2}, new int[]{SYSTEM_UID}); - - // Remove all packages, expect no permission left. - when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{}); - removePackageForUsers(new UserHandle[]{MOCK_USER2}, SYSTEM_PACKAGE2, SYSTEM_UID); - mNetdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1, MOCK_USER2}, - new int[]{SYSTEM_UID, MOCK_UID1}); - - // Remove last user, expect no redundant clearPermission is invoked. - mPermissionMonitor.onUserRemoved(MOCK_USER2); - mNetdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1, MOCK_USER2}, - new int[]{SYSTEM_UID, MOCK_UID1}); - } - - @Test - public void testUidFilteringDuringVpnConnectDisconnectAndUidUpdates() throws Exception { - when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn( - Arrays.asList(new PackageInfo[] { - buildPackageInfo(true /* hasSystemPermission */, SYSTEM_UID1, MOCK_USER1), - buildPackageInfo(false /* hasSystemPermission */, MOCK_UID1, MOCK_USER1), - buildPackageInfo(false /* hasSystemPermission */, MOCK_UID2, MOCK_USER1), - buildPackageInfo(false /* hasSystemPermission */, VPN_UID, MOCK_USER1) - })); - when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE1), - eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn( - buildPackageInfo(false /* hasSystemPermission */, MOCK_UID1, MOCK_USER1)); - mPermissionMonitor.startMonitoring(); - // Every app on user 0 except MOCK_UID2 are under VPN. - final Set vpnRange1 = new HashSet<>(Arrays.asList(new UidRange[] { - new UidRange(0, MOCK_UID2 - 1), - new UidRange(MOCK_UID2 + 1, UserHandle.PER_USER_RANGE - 1)})); - final Set vpnRange2 = Collections.singleton(new UidRange(MOCK_UID2, MOCK_UID2)); - - // When VPN is connected, expect a rule to be set up for user app MOCK_UID1 - mPermissionMonitor.onVpnUidRangesAdded("tun0", vpnRange1, VPN_UID); - verify(mNetdService).firewallAddUidInterfaceRules(eq("tun0"), - aryEq(new int[] {MOCK_UID1})); - - reset(mNetdService); - - // When MOCK_UID1 package is uninstalled and reinstalled, expect Netd to be updated - mPermissionMonitor.onPackageRemoved( - MOCK_PACKAGE1, MOCK_USER1.getUid(MOCK_UID1)); - verify(mNetdService).firewallRemoveUidInterfaceRules(aryEq(new int[] {MOCK_UID1})); - mPermissionMonitor.onPackageAdded(MOCK_PACKAGE1, MOCK_USER1.getUid(MOCK_UID1)); - verify(mNetdService).firewallAddUidInterfaceRules(eq("tun0"), - aryEq(new int[] {MOCK_UID1})); - - reset(mNetdService); - - // During VPN uid update (vpnRange1 -> vpnRange2), ConnectivityService first deletes the - // old UID rules then adds the new ones. Expect netd to be updated - mPermissionMonitor.onVpnUidRangesRemoved("tun0", vpnRange1, VPN_UID); - verify(mNetdService).firewallRemoveUidInterfaceRules(aryEq(new int[] {MOCK_UID1})); - mPermissionMonitor.onVpnUidRangesAdded("tun0", vpnRange2, VPN_UID); - verify(mNetdService).firewallAddUidInterfaceRules(eq("tun0"), - aryEq(new int[] {MOCK_UID2})); - - reset(mNetdService); - - // When VPN is disconnected, expect rules to be torn down - mPermissionMonitor.onVpnUidRangesRemoved("tun0", vpnRange2, VPN_UID); - verify(mNetdService).firewallRemoveUidInterfaceRules(aryEq(new int[] {MOCK_UID2})); - assertNull(mPermissionMonitor.getVpnUidRanges("tun0")); - } - - @Test - public void testUidFilteringDuringPackageInstallAndUninstall() throws Exception { - when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn( - Arrays.asList(new PackageInfo[] { - buildPackageInfo(true /* hasSystemPermission */, SYSTEM_UID1, MOCK_USER1), - buildPackageInfo(false /* hasSystemPermission */, VPN_UID, MOCK_USER1) - })); - when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE1), - eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn( - buildPackageInfo(false /* hasSystemPermission */, MOCK_UID1, MOCK_USER1)); - - mPermissionMonitor.startMonitoring(); - final Set vpnRange = Collections.singleton(UidRange.createForUser(MOCK_USER1)); - mPermissionMonitor.onVpnUidRangesAdded("tun0", vpnRange, VPN_UID); - - // Newly-installed package should have uid rules added - mPermissionMonitor.onPackageAdded(MOCK_PACKAGE1, MOCK_USER1.getUid(MOCK_UID1)); - verify(mNetdService).firewallAddUidInterfaceRules(eq("tun0"), - aryEq(new int[] {MOCK_UID1})); - - // Removed package should have its uid rules removed - mPermissionMonitor.onPackageRemoved( - MOCK_PACKAGE1, MOCK_USER1.getUid(MOCK_UID1)); - verify(mNetdService).firewallRemoveUidInterfaceRules(aryEq(new int[] {MOCK_UID1})); - } - - - // Normal package add/remove operations will trigger multiple intent for uids corresponding to - // each user. To simulate generic package operations, the onPackageAdded/Removed will need to be - // called multiple times with the uid corresponding to each user. - private void addPackageForUsers(UserHandle[] users, String packageName, int uid) { - for (final UserHandle user : users) { - mPermissionMonitor.onPackageAdded(packageName, user.getUid(uid)); - } - } - - private void removePackageForUsers(UserHandle[] users, String packageName, int uid) { - for (final UserHandle user : users) { - mPermissionMonitor.onPackageRemoved(packageName, user.getUid(uid)); - } - } - - private class NetdServiceMonitor { - private final HashMap mPermissions = new HashMap<>(); - - NetdServiceMonitor(INetd mockNetdService) throws Exception { - // Add hook to verify and track result of setPermission. - doAnswer((InvocationOnMock invocation) -> { - final Object[] args = invocation.getArguments(); - final int permission = (int) args[0]; - for (final int uid : (int[]) args[1]) { - mPermissions.put(uid, permission); - } - return null; - }).when(mockNetdService).trafficSetNetPermForUids(anyInt(), any(int[].class)); - } - - public void expectPermission(int permission, int[] apps) { - for (final int app : apps) { - if (!mPermissions.containsKey(app)) { - fail("uid " + app + " does not exist."); - } - if (mPermissions.get(app) != permission) { - fail("uid " + app + " has wrong permission: " + mPermissions.get(app)); - } - } - } - } - - @Test - public void testPackagePermissionUpdate() throws Exception { - final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); - // MOCK_UID1: MOCK_PACKAGE1 only has internet permission. - // MOCK_UID2: MOCK_PACKAGE2 does not have any permission. - // SYSTEM_UID1: SYSTEM_PACKAGE1 has internet permission and update device stats permission. - // SYSTEM_UID2: SYSTEM_PACKAGE2 has only update device stats permission. - - SparseIntArray netdPermissionsAppIds = new SparseIntArray(); - netdPermissionsAppIds.put(MOCK_UID1, INetd.PERMISSION_INTERNET); - netdPermissionsAppIds.put(MOCK_UID2, INetd.PERMISSION_NONE); - netdPermissionsAppIds.put(SYSTEM_UID1, INetd.PERMISSION_INTERNET - | INetd.PERMISSION_UPDATE_DEVICE_STATS); - netdPermissionsAppIds.put(SYSTEM_UID2, INetd.PERMISSION_UPDATE_DEVICE_STATS); - - // Send the permission information to netd, expect permission updated. - mPermissionMonitor.sendPackagePermissionsToNetd(netdPermissionsAppIds); - - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, - new int[]{MOCK_UID1}); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_NONE, new int[]{MOCK_UID2}); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET - | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{SYSTEM_UID1}); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_UPDATE_DEVICE_STATS, - new int[]{SYSTEM_UID2}); - - // Update permission of MOCK_UID1, expect new permission show up. - mPermissionMonitor.sendPackagePermissionsForUid(MOCK_UID1, - INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET - | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); - - // Change permissions of SYSTEM_UID2, expect new permission show up and old permission - // revoked. - mPermissionMonitor.sendPackagePermissionsForUid(SYSTEM_UID2, - INetd.PERMISSION_INTERNET); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{SYSTEM_UID2}); - - // Revoke permission from SYSTEM_UID1, expect no permission stored. - mPermissionMonitor.sendPackagePermissionsForUid(SYSTEM_UID1, INetd.PERMISSION_NONE); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_NONE, new int[]{SYSTEM_UID1}); - } - - private PackageInfo setPackagePermissions(String packageName, int uid, String[] permissions) - throws Exception { - PackageInfo packageInfo = packageInfoWithPermissions( - REQUESTED_PERMISSION_GRANTED, permissions, PARTITION_SYSTEM); - when(mPackageManager.getPackageInfo(eq(packageName), anyInt())).thenReturn(packageInfo); - when(mPackageManager.getPackagesForUid(eq(uid))).thenReturn(new String[]{packageName}); - return packageInfo; - } - - private PackageInfo addPackage(String packageName, int uid, String[] permissions) - throws Exception { - PackageInfo packageInfo = setPackagePermissions(packageName, uid, permissions); - mPermissionMonitor.onPackageAdded(packageName, uid); - return packageInfo; - } - - @Test - public void testPackageInstall() throws Exception { - final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); - - addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS}); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET - | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); - - addPackage(MOCK_PACKAGE2, MOCK_UID2, new String[] {INTERNET}); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID2}); - } - - @Test - public void testPackageInstallSharedUid() throws Exception { - final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); - - PackageInfo packageInfo1 = addPackage(MOCK_PACKAGE1, MOCK_UID1, - new String[] {INTERNET, UPDATE_DEVICE_STATS}); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET - | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); - - // Install another package with the same uid and no permissions should not cause the UID to - // lose permissions. - PackageInfo packageInfo2 = systemPackageInfoWithPermissions(); - when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE2), anyInt())).thenReturn(packageInfo2); - when(mPackageManager.getPackagesForUid(MOCK_UID1)) - .thenReturn(new String[]{MOCK_PACKAGE1, MOCK_PACKAGE2}); - mPermissionMonitor.onPackageAdded(MOCK_PACKAGE2, MOCK_UID1); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET - | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); - } - - @Test - public void testPackageUninstallBasic() throws Exception { - final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); - - addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS}); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET - | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); - - when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{}); - mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_UNINSTALLED, new int[]{MOCK_UID1}); - } - - @Test - public void testPackageRemoveThenAdd() throws Exception { - final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); - - addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS}); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET - | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); - - when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{}); - mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_UNINSTALLED, new int[]{MOCK_UID1}); - - addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET}); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID1}); - } - - @Test - public void testPackageUpdate() throws Exception { - final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); - - addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {}); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_NONE, new int[]{MOCK_UID1}); - - addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET}); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID1}); - } - - @Test - public void testPackageUninstallWithMultiplePackages() throws Exception { - final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); - - addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS}); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET - | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); - - // Mock another package with the same uid but different permissions. - PackageInfo packageInfo2 = systemPackageInfoWithPermissions(INTERNET); - when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE2), anyInt())).thenReturn(packageInfo2); - when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{ - MOCK_PACKAGE2}); - - mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID1}); - } - - @Test - public void testRealSystemPermission() throws Exception { - // Use the real context as this test must ensure the *real* system package holds the - // necessary permission. - final Context realContext = InstrumentationRegistry.getContext(); - final PermissionMonitor monitor = new PermissionMonitor(realContext, mNetdService); - final PackageManager manager = realContext.getPackageManager(); - final PackageInfo systemInfo = manager.getPackageInfo(REAL_SYSTEM_PACKAGE_NAME, - GET_PERMISSIONS | MATCH_ANY_USER); - assertTrue(monitor.hasPermission(systemInfo, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); - } - - @Test - public void testUpdateUidPermissionsFromSystemConfig() throws Exception { - final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); - when(mPackageManager.getInstalledPackages(anyInt())).thenReturn(new ArrayList<>()); - when(mSystemConfigManager.getSystemPermissionUids(eq(INTERNET))) - .thenReturn(new int[]{ MOCK_UID1, MOCK_UID2 }); - when(mSystemConfigManager.getSystemPermissionUids(eq(UPDATE_DEVICE_STATS))) - .thenReturn(new int[]{ MOCK_UID2 }); - - mPermissionMonitor.startMonitoring(); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{ MOCK_UID1 }); - mNetdServiceMonitor.expectPermission( - INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS, - new int[]{ MOCK_UID2 }); - } - - @Test - public void testIntentReceiver() throws Exception { - final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); - final ArgumentCaptor receiverCaptor = - ArgumentCaptor.forClass(BroadcastReceiver.class); - verify(mContext, times(1)).registerReceiver(receiverCaptor.capture(), any(), any(), any()); - final BroadcastReceiver receiver = receiverCaptor.getValue(); - - // Verify receiving PACKAGE_ADDED intent. - final Intent addedIntent = new Intent(Intent.ACTION_PACKAGE_ADDED, - Uri.fromParts("package", MOCK_PACKAGE1, null /* fragment */)); - addedIntent.putExtra(Intent.EXTRA_UID, MOCK_UID1); - setPackagePermissions(MOCK_PACKAGE1, MOCK_UID1, - new String[] { INTERNET, UPDATE_DEVICE_STATS }); - receiver.onReceive(mContext, addedIntent); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET - | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[] { MOCK_UID1 }); - - // Verify receiving PACKAGE_REMOVED intent. - when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(null); - final Intent removedIntent = new Intent(Intent.ACTION_PACKAGE_REMOVED, - Uri.fromParts("package", MOCK_PACKAGE1, null /* fragment */)); - removedIntent.putExtra(Intent.EXTRA_UID, MOCK_UID1); - receiver.onReceive(mContext, removedIntent); - mNetdServiceMonitor.expectPermission(INetd.PERMISSION_UNINSTALLED, new int[] { MOCK_UID1 }); - } - - @Test - public void testAppsAllowedOnRestrictedNetworksChanged() throws Exception { - final NetdMonitor mNetdMonitor = new NetdMonitor(mNetdService); - final ArgumentCaptor captor = - ArgumentCaptor.forClass(ContentObserver.class); - verify(mDeps, times(1)).registerContentObserver(any(), - argThat(uri -> uri.getEncodedPath().contains(APPS_ALLOWED_ON_RESTRICTED_NETWORKS)), - anyBoolean(), captor.capture()); - final ContentObserver contentObserver = captor.getValue(); - - mPermissionMonitor.onUserAdded(MOCK_USER1); - // Prepare PackageInfo for MOCK_PACKAGE1 - final PackageInfo packageInfo = buildPackageInfo( - false /* hasSystemPermission */, MOCK_UID1, MOCK_USER1); - packageInfo.packageName = MOCK_PACKAGE1; - when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE1), anyInt())).thenReturn(packageInfo); - when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{MOCK_PACKAGE1}); - // Prepare PackageInfo for MOCK_PACKAGE2 - final PackageInfo packageInfo2 = buildPackageInfo( - false /* hasSystemPermission */, MOCK_UID2, MOCK_USER1); - packageInfo2.packageName = MOCK_PACKAGE2; - when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE2), anyInt())).thenReturn(packageInfo2); - when(mPackageManager.getPackagesForUid(MOCK_UID2)).thenReturn(new String[]{MOCK_PACKAGE2}); - - // MOCK_PACKAGE1 is listed in setting that allow to use restricted networks, MOCK_UID1 - // should have SYSTEM permission. - when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn( - new ArraySet<>(new String[] { MOCK_PACKAGE1 })); - contentObserver.onChange(true /* selfChange */); - mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1}); - mNetdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID2}); - - // MOCK_PACKAGE2 is listed in setting that allow to use restricted networks, MOCK_UID2 - // should have SYSTEM permission but MOCK_UID1 should revoke permission. - when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn( - new ArraySet<>(new String[] { MOCK_PACKAGE2 })); - contentObserver.onChange(true /* selfChange */); - mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID2}); - mNetdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1}); - - // No app lists in setting, should revoke permission from all uids. - when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn(new ArraySet<>()); - contentObserver.onChange(true /* selfChange */); - mNetdMonitor.expectNoPermission( - new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1, MOCK_UID2}); - } - - @Test - public void testAppsAllowedOnRestrictedNetworksChangedWithSharedUid() throws Exception { - final NetdMonitor mNetdMonitor = new NetdMonitor(mNetdService); - final ArgumentCaptor captor = - ArgumentCaptor.forClass(ContentObserver.class); - verify(mDeps, times(1)).registerContentObserver(any(), - argThat(uri -> uri.getEncodedPath().contains(APPS_ALLOWED_ON_RESTRICTED_NETWORKS)), - anyBoolean(), captor.capture()); - final ContentObserver contentObserver = captor.getValue(); - - mPermissionMonitor.onUserAdded(MOCK_USER1); - // Prepare PackageInfo for MOCK_PACKAGE1 and MOCK_PACKAGE2 with shared uid MOCK_UID1. - final PackageInfo packageInfo = systemPackageInfoWithPermissions(CHANGE_NETWORK_STATE); - packageInfo.applicationInfo.uid = MOCK_USER1.getUid(MOCK_UID1); - packageInfo.packageName = MOCK_PACKAGE1; - final PackageInfo packageInfo2 = buildPackageInfo( - false /* hasSystemPermission */, MOCK_UID1, MOCK_USER1); - packageInfo2.packageName = MOCK_PACKAGE2; - when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE1), anyInt())).thenReturn(packageInfo); - when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE2), anyInt())).thenReturn(packageInfo2); - when(mPackageManager.getPackagesForUid(MOCK_UID1)) - .thenReturn(new String[]{MOCK_PACKAGE1, MOCK_PACKAGE2}); - - // MOCK_PACKAGE1 have CHANGE_NETWORK_STATE, MOCK_UID1 should have NETWORK permission. - addPackageForUsers(new UserHandle[]{MOCK_USER1}, MOCK_PACKAGE1, MOCK_UID1); - mNetdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1}); - - // MOCK_PACKAGE2 is listed in setting that allow to use restricted networks, MOCK_UID1 - // should upgrade to SYSTEM permission. - when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn( - new ArraySet<>(new String[] { MOCK_PACKAGE2 })); - contentObserver.onChange(true /* selfChange */); - mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1}); - - // MOCK_PACKAGE1 is listed in setting that allow to use restricted networks, MOCK_UID1 - // should still have SYSTEM permission. - when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn( - new ArraySet<>(new String[] { MOCK_PACKAGE1 })); - contentObserver.onChange(true /* selfChange */); - mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1}); - - // No app lists in setting, MOCK_UID1 should downgrade to NETWORK permission. - when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn(new ArraySet<>()); - contentObserver.onChange(true /* selfChange */); - mNetdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1}); - - // MOCK_PACKAGE1 removed, should revoke permission from MOCK_UID1. - when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{MOCK_PACKAGE2}); - removePackageForUsers(new UserHandle[]{MOCK_USER1}, MOCK_PACKAGE1, MOCK_UID1); - mNetdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1}); - } -} \ No newline at end of file diff --git a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/VpnTest.java b/packages/Connectivity/tests/unit/java/com/android/server/connectivity/VpnTest.java deleted file mode 100644 index b725b826b14f0..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/connectivity/VpnTest.java +++ /dev/null @@ -1,1283 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.connectivity; - -import static android.content.pm.UserInfo.FLAG_ADMIN; -import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE; -import static android.content.pm.UserInfo.FLAG_PRIMARY; -import static android.content.pm.UserInfo.FLAG_RESTRICTED; -import static android.net.ConnectivityManager.NetworkCallback; -import static android.net.INetd.IF_STATE_DOWN; -import static android.net.INetd.IF_STATE_UP; -import static android.os.UserHandle.PER_USER_RANGE; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.timeout; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.annotation.NonNull; -import android.annotation.UserIdInt; -import android.app.AppOpsManager; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.pm.ServiceInfo; -import android.content.pm.UserInfo; -import android.content.res.Resources; -import android.net.ConnectivityManager; -import android.net.INetd; -import android.net.Ikev2VpnProfile; -import android.net.InetAddresses; -import android.net.InterfaceConfigurationParcel; -import android.net.IpPrefix; -import android.net.IpSecManager; -import android.net.IpSecTunnelInterfaceResponse; -import android.net.LinkProperties; -import android.net.LocalSocket; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.NetworkInfo.DetailedState; -import android.net.RouteInfo; -import android.net.UidRangeParcel; -import android.net.VpnManager; -import android.net.VpnService; -import android.net.VpnTransportInfo; -import android.net.ipsec.ike.IkeSessionCallback; -import android.net.ipsec.ike.exceptions.IkeProtocolException; -import android.os.Build.VERSION_CODES; -import android.os.Bundle; -import android.os.ConditionVariable; -import android.os.INetworkManagementService; -import android.os.Process; -import android.os.UserHandle; -import android.os.UserManager; -import android.os.test.TestLooper; -import android.provider.Settings; -import android.security.Credentials; -import android.util.ArrayMap; -import android.util.ArraySet; -import android.util.Range; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.internal.R; -import com.android.internal.net.LegacyVpnInfo; -import com.android.internal.net.VpnConfig; -import com.android.internal.net.VpnProfile; -import com.android.server.IpSecService; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.AdditionalAnswers; -import org.mockito.Answers; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.net.Inet4Address; -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; -import java.util.stream.Stream; - -/** - * Tests for {@link Vpn}. - * - * Build, install and run with: - * runtest frameworks-net -c com.android.server.connectivity.VpnTest - */ -@RunWith(AndroidJUnit4.class) -@SmallTest -public class VpnTest { - private static final String TAG = "VpnTest"; - - // Mock users - static final UserInfo primaryUser = new UserInfo(27, "Primary", FLAG_ADMIN | FLAG_PRIMARY); - static final UserInfo secondaryUser = new UserInfo(15, "Secondary", FLAG_ADMIN); - static final UserInfo restrictedProfileA = new UserInfo(40, "RestrictedA", FLAG_RESTRICTED); - static final UserInfo restrictedProfileB = new UserInfo(42, "RestrictedB", FLAG_RESTRICTED); - static final UserInfo managedProfileA = new UserInfo(45, "ManagedA", FLAG_MANAGED_PROFILE); - static { - restrictedProfileA.restrictedProfileParentId = primaryUser.id; - restrictedProfileB.restrictedProfileParentId = secondaryUser.id; - managedProfileA.profileGroupId = primaryUser.id; - } - - static final Network EGRESS_NETWORK = new Network(101); - static final String EGRESS_IFACE = "wlan0"; - static final String TEST_VPN_PKG = "com.testvpn.vpn"; - private static final String TEST_VPN_SERVER = "1.2.3.4"; - private static final String TEST_VPN_IDENTITY = "identity"; - private static final byte[] TEST_VPN_PSK = "psk".getBytes(); - - private static final Network TEST_NETWORK = new Network(Integer.MAX_VALUE); - private static final String TEST_IFACE_NAME = "TEST_IFACE"; - private static final int TEST_TUNNEL_RESOURCE_ID = 0x2345; - private static final long TEST_TIMEOUT_MS = 500L; - - /** - * Names and UIDs for some fake packages. Important points: - * - UID is ordered increasing. - * - One pair of packages have consecutive UIDs. - */ - static final String[] PKGS = {"com.example", "org.example", "net.example", "web.vpn"}; - static final int[] PKG_UIDS = {66, 77, 78, 400}; - - // Mock packages - static final Map mPackages = new ArrayMap<>(); - static { - for (int i = 0; i < PKGS.length; i++) { - mPackages.put(PKGS[i], PKG_UIDS[i]); - } - } - private static final Range PRI_USER_RANGE = uidRangeForUser(primaryUser.id); - - @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext; - @Mock private UserManager mUserManager; - @Mock private PackageManager mPackageManager; - @Mock private INetworkManagementService mNetService; - @Mock private INetd mNetd; - @Mock private AppOpsManager mAppOps; - @Mock private NotificationManager mNotificationManager; - @Mock private Vpn.SystemServices mSystemServices; - @Mock private Vpn.Ikev2SessionCreator mIkev2SessionCreator; - @Mock private ConnectivityManager mConnectivityManager; - @Mock private IpSecService mIpSecService; - @Mock private VpnProfileStore mVpnProfileStore; - private final VpnProfile mVpnProfile; - - private IpSecManager mIpSecManager; - - public VpnTest() throws Exception { - // Build an actual VPN profile that is capable of being converted to and from an - // Ikev2VpnProfile - final Ikev2VpnProfile.Builder builder = - new Ikev2VpnProfile.Builder(TEST_VPN_SERVER, TEST_VPN_IDENTITY); - builder.setAuthPsk(TEST_VPN_PSK); - mVpnProfile = builder.build().toVpnProfile(); - } - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - mIpSecManager = new IpSecManager(mContext, mIpSecService); - - when(mContext.getPackageManager()).thenReturn(mPackageManager); - setMockedPackages(mPackages); - - when(mContext.getPackageName()).thenReturn(TEST_VPN_PKG); - when(mContext.getOpPackageName()).thenReturn(TEST_VPN_PKG); - when(mContext.getSystemServiceName(UserManager.class)) - .thenReturn(Context.USER_SERVICE); - when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager); - when(mContext.getSystemService(eq(Context.APP_OPS_SERVICE))).thenReturn(mAppOps); - when(mContext.getSystemServiceName(NotificationManager.class)) - .thenReturn(Context.NOTIFICATION_SERVICE); - when(mContext.getSystemService(eq(Context.NOTIFICATION_SERVICE))) - .thenReturn(mNotificationManager); - when(mContext.getSystemService(eq(Context.CONNECTIVITY_SERVICE))) - .thenReturn(mConnectivityManager); - when(mContext.getSystemServiceName(eq(ConnectivityManager.class))) - .thenReturn(Context.CONNECTIVITY_SERVICE); - when(mContext.getSystemService(eq(Context.IPSEC_SERVICE))).thenReturn(mIpSecManager); - when(mContext.getString(R.string.config_customVpnAlwaysOnDisconnectedDialogComponent)) - .thenReturn(Resources.getSystem().getString( - R.string.config_customVpnAlwaysOnDisconnectedDialogComponent)); - when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS)) - .thenReturn(true); - - // Used by {@link Notification.Builder} - ApplicationInfo applicationInfo = new ApplicationInfo(); - applicationInfo.targetSdkVersion = VERSION_CODES.CUR_DEVELOPMENT; - when(mContext.getApplicationInfo()).thenReturn(applicationInfo); - when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) - .thenReturn(applicationInfo); - - doNothing().when(mNetService).registerObserver(any()); - - // Deny all appops by default. - when(mAppOps.noteOpNoThrow(anyString(), anyInt(), anyString(), any(), any())) - .thenReturn(AppOpsManager.MODE_IGNORED); - - // Setup IpSecService - final IpSecTunnelInterfaceResponse tunnelResp = - new IpSecTunnelInterfaceResponse( - IpSecManager.Status.OK, TEST_TUNNEL_RESOURCE_ID, TEST_IFACE_NAME); - when(mIpSecService.createTunnelInterface(any(), any(), any(), any(), any())) - .thenReturn(tunnelResp); - } - - private Set> rangeSet(Range ... ranges) { - final Set> range = new ArraySet<>(); - for (Range r : ranges) range.add(r); - - return range; - } - - private static Range uidRangeForUser(int userId) { - return new Range(userId * PER_USER_RANGE, (userId + 1) * PER_USER_RANGE - 1); - } - - private Range uidRange(int start, int stop) { - return new Range(start, stop); - } - - @Test - public void testRestrictedProfilesAreAddedToVpn() { - setMockedUsers(primaryUser, secondaryUser, restrictedProfileA, restrictedProfileB); - - final Vpn vpn = createVpn(primaryUser.id); - - // Assume the user can have restricted profiles. - doReturn(true).when(mUserManager).canHaveRestrictedProfile(); - final Set> ranges = - vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, null, null); - - assertEquals(rangeSet(PRI_USER_RANGE, uidRangeForUser(restrictedProfileA.id)), ranges); - } - - @Test - public void testManagedProfilesAreNotAddedToVpn() { - setMockedUsers(primaryUser, managedProfileA); - - final Vpn vpn = createVpn(primaryUser.id); - final Set> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, - null, null); - - assertEquals(rangeSet(PRI_USER_RANGE), ranges); - } - - @Test - public void testAddUserToVpnOnlyAddsOneUser() { - setMockedUsers(primaryUser, restrictedProfileA, managedProfileA); - - final Vpn vpn = createVpn(primaryUser.id); - final Set> ranges = new ArraySet<>(); - vpn.addUserToRanges(ranges, primaryUser.id, null, null); - - assertEquals(rangeSet(PRI_USER_RANGE), ranges); - } - - @Test - public void testUidAllowAndDenylist() throws Exception { - final Vpn vpn = createVpn(primaryUser.id); - final Range user = PRI_USER_RANGE; - final int userStart = user.getLower(); - final int userStop = user.getUpper(); - final String[] packages = {PKGS[0], PKGS[1], PKGS[2]}; - - // Allowed list - final Set> allow = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, - Arrays.asList(packages), null /* disallowedApplications */); - assertEquals(rangeSet( - uidRange(userStart + PKG_UIDS[0], userStart + PKG_UIDS[0]), - uidRange(userStart + PKG_UIDS[1], userStart + PKG_UIDS[2])), - allow); - - // Denied list - final Set> disallow = - vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, - null /* allowedApplications */, Arrays.asList(packages)); - assertEquals(rangeSet( - uidRange(userStart, userStart + PKG_UIDS[0] - 1), - uidRange(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1), - /* Empty range between UIDS[1] and UIDS[2], should be excluded, */ - uidRange(userStart + PKG_UIDS[2] + 1, userStop)), - disallow); - } - - @Test - public void testGetAlwaysAndOnGetLockDown() throws Exception { - final Vpn vpn = createVpn(primaryUser.id); - - // Default state. - assertFalse(vpn.getAlwaysOn()); - assertFalse(vpn.getLockdown()); - - // Set always-on without lockdown. - assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, Collections.emptyList())); - assertTrue(vpn.getAlwaysOn()); - assertFalse(vpn.getLockdown()); - - // Set always-on with lockdown. - assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, Collections.emptyList())); - assertTrue(vpn.getAlwaysOn()); - assertTrue(vpn.getLockdown()); - - // Remove always-on configuration. - assertTrue(vpn.setAlwaysOnPackage(null, false, Collections.emptyList())); - assertFalse(vpn.getAlwaysOn()); - assertFalse(vpn.getLockdown()); - } - - @Test - public void testLockdownChangingPackage() throws Exception { - final Vpn vpn = createVpn(primaryUser.id); - final Range user = PRI_USER_RANGE; - final int userStart = user.getLower(); - final int userStop = user.getUpper(); - // Set always-on without lockdown. - assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, null)); - - // Set always-on with lockdown. - assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, null)); - verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { - new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1), - new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop) - })); - - // Switch to another app. - assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null)); - verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { - new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1), - new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop) - })); - verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { - new UidRangeParcel(userStart, userStart + PKG_UIDS[3] - 1), - new UidRangeParcel(userStart + PKG_UIDS[3] + 1, userStop) - })); - } - - @Test - public void testLockdownAllowlist() throws Exception { - final Vpn vpn = createVpn(primaryUser.id); - final Range user = PRI_USER_RANGE; - final int userStart = user.getLower(); - final int userStop = user.getUpper(); - // Set always-on with lockdown and allow app PKGS[2] from lockdown. - assertTrue(vpn.setAlwaysOnPackage( - PKGS[1], true, Collections.singletonList(PKGS[2]))); - verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { - new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1), - new UidRangeParcel(userStart + PKG_UIDS[2] + 1, userStop) - })); - // Change allowed app list to PKGS[3]. - assertTrue(vpn.setAlwaysOnPackage( - PKGS[1], true, Collections.singletonList(PKGS[3]))); - verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { - new UidRangeParcel(userStart + PKG_UIDS[2] + 1, userStop) - })); - verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { - new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStart + PKG_UIDS[3] - 1), - new UidRangeParcel(userStart + PKG_UIDS[3] + 1, userStop) - })); - - // Change the VPN app. - assertTrue(vpn.setAlwaysOnPackage( - PKGS[0], true, Collections.singletonList(PKGS[3]))); - verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { - new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1), - new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStart + PKG_UIDS[3] - 1) - })); - verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { - new UidRangeParcel(userStart, userStart + PKG_UIDS[0] - 1), - new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[3] - 1) - })); - - // Remove the list of allowed packages. - assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null)); - verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { - new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[3] - 1), - new UidRangeParcel(userStart + PKG_UIDS[3] + 1, userStop) - })); - verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { - new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStop), - })); - - // Add the list of allowed packages. - assertTrue(vpn.setAlwaysOnPackage( - PKGS[0], true, Collections.singletonList(PKGS[1]))); - verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { - new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStop) - })); - verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { - new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1), - new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop) - })); - - // Try allowing a package with a comma, should be rejected. - assertFalse(vpn.setAlwaysOnPackage( - PKGS[0], true, Collections.singletonList("a.b,c.d"))); - - // Pass a non-existent packages in the allowlist, they (and only they) should be ignored. - // allowed package should change from PGKS[1] to PKGS[2]. - assertTrue(vpn.setAlwaysOnPackage( - PKGS[0], true, Arrays.asList("com.foo.app", PKGS[2], "com.bar.app"))); - verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { - new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1), - new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop) - })); - verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { - new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[2] - 1), - new UidRangeParcel(userStart + PKG_UIDS[2] + 1, userStop) - })); - } - - @Test - public void testLockdownRuleRepeatability() throws Exception { - final Vpn vpn = createVpn(primaryUser.id); - final UidRangeParcel[] primaryUserRangeParcel = new UidRangeParcel[] { - new UidRangeParcel(PRI_USER_RANGE.getLower(), PRI_USER_RANGE.getUpper())}; - // Given legacy lockdown is already enabled, - vpn.setLockdown(true); - verify(mConnectivityManager, times(1)).setRequireVpnForUids(true, - toRanges(primaryUserRangeParcel)); - - // Enabling legacy lockdown twice should do nothing. - vpn.setLockdown(true); - verify(mConnectivityManager, times(1)).setRequireVpnForUids(anyBoolean(), any()); - - // And disabling should remove the rules exactly once. - vpn.setLockdown(false); - verify(mConnectivityManager, times(1)).setRequireVpnForUids(false, - toRanges(primaryUserRangeParcel)); - - // Removing the lockdown again should have no effect. - vpn.setLockdown(false); - verify(mConnectivityManager, times(2)).setRequireVpnForUids(anyBoolean(), any()); - } - - private ArrayList> toRanges(UidRangeParcel[] ranges) { - ArrayList> rangesArray = new ArrayList<>(ranges.length); - for (int i = 0; i < ranges.length; i++) { - rangesArray.add(new Range<>(ranges[i].start, ranges[i].stop)); - } - return rangesArray; - } - - @Test - public void testLockdownRuleReversibility() throws Exception { - final Vpn vpn = createVpn(primaryUser.id); - final UidRangeParcel[] entireUser = { - new UidRangeParcel(PRI_USER_RANGE.getLower(), PRI_USER_RANGE.getUpper()) - }; - final UidRangeParcel[] exceptPkg0 = { - new UidRangeParcel(entireUser[0].start, entireUser[0].start + PKG_UIDS[0] - 1), - new UidRangeParcel(entireUser[0].start + PKG_UIDS[0] + 1, entireUser[0].stop) - }; - - final InOrder order = inOrder(mConnectivityManager); - - // Given lockdown is enabled with no package (legacy VPN), - vpn.setLockdown(true); - order.verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(entireUser)); - - // When a new VPN package is set the rules should change to cover that package. - vpn.prepare(null, PKGS[0], VpnManager.TYPE_VPN_SERVICE); - order.verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(entireUser)); - order.verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(exceptPkg0)); - - // When that VPN package is unset, everything should be undone again in reverse. - vpn.prepare(null, VpnConfig.LEGACY_VPN, VpnManager.TYPE_VPN_SERVICE); - order.verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(exceptPkg0)); - order.verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(entireUser)); - } - - @Test - public void testIsAlwaysOnPackageSupported() throws Exception { - final Vpn vpn = createVpn(primaryUser.id); - - ApplicationInfo appInfo = new ApplicationInfo(); - when(mPackageManager.getApplicationInfoAsUser(eq(PKGS[0]), anyInt(), eq(primaryUser.id))) - .thenReturn(appInfo); - - ServiceInfo svcInfo = new ServiceInfo(); - ResolveInfo resInfo = new ResolveInfo(); - resInfo.serviceInfo = svcInfo; - when(mPackageManager.queryIntentServicesAsUser(any(), eq(PackageManager.GET_META_DATA), - eq(primaryUser.id))) - .thenReturn(Collections.singletonList(resInfo)); - - // null package name should return false - assertFalse(vpn.isAlwaysOnPackageSupported(null)); - - // Pre-N apps are not supported - appInfo.targetSdkVersion = VERSION_CODES.M; - assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0])); - - // N+ apps are supported by default - appInfo.targetSdkVersion = VERSION_CODES.N; - assertTrue(vpn.isAlwaysOnPackageSupported(PKGS[0])); - - // Apps that opt out explicitly are not supported - appInfo.targetSdkVersion = VERSION_CODES.CUR_DEVELOPMENT; - Bundle metaData = new Bundle(); - metaData.putBoolean(VpnService.SERVICE_META_DATA_SUPPORTS_ALWAYS_ON, false); - svcInfo.metaData = metaData; - assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0])); - } - - @Test - public void testNotificationShownForAlwaysOnApp() throws Exception { - final UserHandle userHandle = UserHandle.of(primaryUser.id); - final Vpn vpn = createVpn(primaryUser.id); - setMockedUsers(primaryUser); - - final InOrder order = inOrder(mNotificationManager); - - // Don't show a notification for regular disconnected states. - vpn.updateState(DetailedState.DISCONNECTED, TAG); - order.verify(mNotificationManager, atLeastOnce()).cancel(anyString(), anyInt()); - - // Start showing a notification for disconnected once always-on. - vpn.setAlwaysOnPackage(PKGS[0], false, null); - order.verify(mNotificationManager).notify(anyString(), anyInt(), any()); - - // Stop showing the notification once connected. - vpn.updateState(DetailedState.CONNECTED, TAG); - order.verify(mNotificationManager).cancel(anyString(), anyInt()); - - // Show the notification if we disconnect again. - vpn.updateState(DetailedState.DISCONNECTED, TAG); - order.verify(mNotificationManager).notify(anyString(), anyInt(), any()); - - // Notification should be cleared after unsetting always-on package. - vpn.setAlwaysOnPackage(null, false, null); - order.verify(mNotificationManager).cancel(anyString(), anyInt()); - } - - /** - * The profile name should NOT change between releases for backwards compatibility - * - *

      If this is changed between releases, the {@link Vpn#getVpnProfilePrivileged()} method MUST - * be updated to ensure backward compatibility. - */ - @Test - public void testGetProfileNameForPackage() throws Exception { - final Vpn vpn = createVpn(primaryUser.id); - setMockedUsers(primaryUser); - - final String expected = Credentials.PLATFORM_VPN + primaryUser.id + "_" + TEST_VPN_PKG; - assertEquals(expected, vpn.getProfileNameForPackage(TEST_VPN_PKG)); - } - - private Vpn createVpnAndSetupUidChecks(String... grantedOps) throws Exception { - return createVpnAndSetupUidChecks(primaryUser, grantedOps); - } - - private Vpn createVpnAndSetupUidChecks(UserInfo user, String... grantedOps) throws Exception { - final Vpn vpn = createVpn(user.id); - setMockedUsers(user); - - when(mPackageManager.getPackageUidAsUser(eq(TEST_VPN_PKG), anyInt())) - .thenReturn(Process.myUid()); - - for (final String opStr : grantedOps) { - when(mAppOps.noteOpNoThrow(opStr, Process.myUid(), TEST_VPN_PKG, - null /* attributionTag */, null /* message */)) - .thenReturn(AppOpsManager.MODE_ALLOWED); - } - - return vpn; - } - - private void checkProvisionVpnProfile(Vpn vpn, boolean expectedResult, String... checkedOps) { - assertEquals(expectedResult, vpn.provisionVpnProfile(TEST_VPN_PKG, mVpnProfile)); - - // The profile should always be stored, whether or not consent has been previously granted. - verify(mVpnProfileStore) - .put( - eq(vpn.getProfileNameForPackage(TEST_VPN_PKG)), - eq(mVpnProfile.encode())); - - for (final String checkedOpStr : checkedOps) { - verify(mAppOps).noteOpNoThrow(checkedOpStr, Process.myUid(), TEST_VPN_PKG, - null /* attributionTag */, null /* message */); - } - } - - @Test - public void testProvisionVpnProfileNoIpsecTunnels() throws Exception { - when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS)) - .thenReturn(false); - final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); - - try { - checkProvisionVpnProfile( - vpn, true /* expectedResult */, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); - fail("Expected exception due to missing feature"); - } catch (UnsupportedOperationException expected) { - } - } - - @Test - public void testProvisionVpnProfilePreconsented() throws Exception { - final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); - - checkProvisionVpnProfile( - vpn, true /* expectedResult */, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); - } - - @Test - public void testProvisionVpnProfileNotPreconsented() throws Exception { - final Vpn vpn = createVpnAndSetupUidChecks(); - - // Expect that both the ACTIVATE_VPN and ACTIVATE_PLATFORM_VPN were tried, but the caller - // had neither. - checkProvisionVpnProfile(vpn, false /* expectedResult */, - AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN, AppOpsManager.OPSTR_ACTIVATE_VPN); - } - - @Test - public void testProvisionVpnProfileVpnServicePreconsented() throws Exception { - final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_VPN); - - checkProvisionVpnProfile(vpn, true /* expectedResult */, AppOpsManager.OPSTR_ACTIVATE_VPN); - } - - @Test - public void testProvisionVpnProfileTooLarge() throws Exception { - final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); - - final VpnProfile bigProfile = new VpnProfile(""); - bigProfile.name = new String(new byte[Vpn.MAX_VPN_PROFILE_SIZE_BYTES + 1]); - - try { - vpn.provisionVpnProfile(TEST_VPN_PKG, bigProfile); - fail("Expected IAE due to profile size"); - } catch (IllegalArgumentException expected) { - } - } - - @Test - public void testProvisionVpnProfileRestrictedUser() throws Exception { - final Vpn vpn = - createVpnAndSetupUidChecks( - restrictedProfileA, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); - - try { - vpn.provisionVpnProfile(TEST_VPN_PKG, mVpnProfile); - fail("Expected SecurityException due to restricted user"); - } catch (SecurityException expected) { - } - } - - @Test - public void testDeleteVpnProfile() throws Exception { - final Vpn vpn = createVpnAndSetupUidChecks(); - - vpn.deleteVpnProfile(TEST_VPN_PKG); - - verify(mVpnProfileStore) - .remove(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG))); - } - - @Test - public void testDeleteVpnProfileRestrictedUser() throws Exception { - final Vpn vpn = - createVpnAndSetupUidChecks( - restrictedProfileA, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); - - try { - vpn.deleteVpnProfile(TEST_VPN_PKG); - fail("Expected SecurityException due to restricted user"); - } catch (SecurityException expected) { - } - } - - @Test - public void testGetVpnProfilePrivileged() throws Exception { - final Vpn vpn = createVpnAndSetupUidChecks(); - - when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) - .thenReturn(new VpnProfile("").encode()); - - vpn.getVpnProfilePrivileged(TEST_VPN_PKG); - - verify(mVpnProfileStore).get(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG))); - } - - @Test - public void testStartVpnProfile() throws Exception { - final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); - - when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) - .thenReturn(mVpnProfile.encode()); - - vpn.startVpnProfile(TEST_VPN_PKG); - - verify(mVpnProfileStore).get(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG))); - verify(mAppOps) - .noteOpNoThrow( - eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN), - eq(Process.myUid()), - eq(TEST_VPN_PKG), - eq(null) /* attributionTag */, - eq(null) /* message */); - } - - @Test - public void testStartVpnProfileVpnServicePreconsented() throws Exception { - final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_VPN); - - when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) - .thenReturn(mVpnProfile.encode()); - - vpn.startVpnProfile(TEST_VPN_PKG); - - // Verify that the the ACTIVATE_VPN appop was checked, but no error was thrown. - verify(mAppOps).noteOpNoThrow(AppOpsManager.OPSTR_ACTIVATE_VPN, Process.myUid(), - TEST_VPN_PKG, null /* attributionTag */, null /* message */); - } - - @Test - public void testStartVpnProfileNotConsented() throws Exception { - final Vpn vpn = createVpnAndSetupUidChecks(); - - try { - vpn.startVpnProfile(TEST_VPN_PKG); - fail("Expected failure due to no user consent"); - } catch (SecurityException expected) { - } - - // Verify both appops were checked. - verify(mAppOps) - .noteOpNoThrow( - eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN), - eq(Process.myUid()), - eq(TEST_VPN_PKG), - eq(null) /* attributionTag */, - eq(null) /* message */); - verify(mAppOps).noteOpNoThrow(AppOpsManager.OPSTR_ACTIVATE_VPN, Process.myUid(), - TEST_VPN_PKG, null /* attributionTag */, null /* message */); - - // Keystore should never have been accessed. - verify(mVpnProfileStore, never()).get(any()); - } - - @Test - public void testStartVpnProfileMissingProfile() throws Exception { - final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); - - when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))).thenReturn(null); - - try { - vpn.startVpnProfile(TEST_VPN_PKG); - fail("Expected failure due to missing profile"); - } catch (IllegalArgumentException expected) { - } - - verify(mVpnProfileStore).get(vpn.getProfileNameForPackage(TEST_VPN_PKG)); - verify(mAppOps) - .noteOpNoThrow( - eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN), - eq(Process.myUid()), - eq(TEST_VPN_PKG), - eq(null) /* attributionTag */, - eq(null) /* message */); - } - - @Test - public void testStartVpnProfileRestrictedUser() throws Exception { - final Vpn vpn = - createVpnAndSetupUidChecks( - restrictedProfileA, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); - - try { - vpn.startVpnProfile(TEST_VPN_PKG); - fail("Expected SecurityException due to restricted user"); - } catch (SecurityException expected) { - } - } - - @Test - public void testStopVpnProfileRestrictedUser() throws Exception { - final Vpn vpn = - createVpnAndSetupUidChecks( - restrictedProfileA, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); - - try { - vpn.stopVpnProfile(TEST_VPN_PKG); - fail("Expected SecurityException due to restricted user"); - } catch (SecurityException expected) { - } - } - - @Test - public void testSetPackageAuthorizationVpnService() throws Exception { - final Vpn vpn = createVpnAndSetupUidChecks(); - - assertTrue(vpn.setPackageAuthorization(TEST_VPN_PKG, VpnManager.TYPE_VPN_SERVICE)); - verify(mAppOps) - .setMode( - eq(AppOpsManager.OPSTR_ACTIVATE_VPN), - eq(Process.myUid()), - eq(TEST_VPN_PKG), - eq(AppOpsManager.MODE_ALLOWED)); - } - - @Test - public void testSetPackageAuthorizationPlatformVpn() throws Exception { - final Vpn vpn = createVpnAndSetupUidChecks(); - - assertTrue(vpn.setPackageAuthorization(TEST_VPN_PKG, VpnManager.TYPE_VPN_PLATFORM)); - verify(mAppOps) - .setMode( - eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN), - eq(Process.myUid()), - eq(TEST_VPN_PKG), - eq(AppOpsManager.MODE_ALLOWED)); - } - - @Test - public void testSetPackageAuthorizationRevokeAuthorization() throws Exception { - final Vpn vpn = createVpnAndSetupUidChecks(); - - assertTrue(vpn.setPackageAuthorization(TEST_VPN_PKG, VpnManager.TYPE_VPN_NONE)); - verify(mAppOps) - .setMode( - eq(AppOpsManager.OPSTR_ACTIVATE_VPN), - eq(Process.myUid()), - eq(TEST_VPN_PKG), - eq(AppOpsManager.MODE_IGNORED)); - verify(mAppOps) - .setMode( - eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN), - eq(Process.myUid()), - eq(TEST_VPN_PKG), - eq(AppOpsManager.MODE_IGNORED)); - } - - private NetworkCallback triggerOnAvailableAndGetCallback() throws Exception { - final ArgumentCaptor networkCallbackCaptor = - ArgumentCaptor.forClass(NetworkCallback.class); - verify(mConnectivityManager, timeout(TEST_TIMEOUT_MS)) - .requestNetwork(any(), networkCallbackCaptor.capture()); - - // onAvailable() will trigger onDefaultNetworkChanged(), so NetdUtils#setInterfaceUp will be - // invoked. Set the return value of INetd#interfaceGetCfg to prevent NullPointerException. - final InterfaceConfigurationParcel config = new InterfaceConfigurationParcel(); - config.flags = new String[] {IF_STATE_DOWN}; - when(mNetd.interfaceGetCfg(anyString())).thenReturn(config); - final NetworkCallback cb = networkCallbackCaptor.getValue(); - cb.onAvailable(TEST_NETWORK); - return cb; - } - - private void verifyInterfaceSetCfgWithFlags(String flag) throws Exception { - // Add a timeout for waiting for interfaceSetCfg to be called. - verify(mNetd, timeout(TEST_TIMEOUT_MS)).interfaceSetCfg(argThat( - config -> Arrays.asList(config.flags).contains(flag))); - } - - @Test - public void testStartPlatformVpnAuthenticationFailed() throws Exception { - final ArgumentCaptor captor = - ArgumentCaptor.forClass(IkeSessionCallback.class); - final IkeProtocolException exception = mock(IkeProtocolException.class); - when(exception.getErrorType()) - .thenReturn(IkeProtocolException.ERROR_TYPE_AUTHENTICATION_FAILED); - - final Vpn vpn = startLegacyVpn(createVpn(primaryUser.id), (mVpnProfile)); - final NetworkCallback cb = triggerOnAvailableAndGetCallback(); - - verifyInterfaceSetCfgWithFlags(IF_STATE_UP); - - // Wait for createIkeSession() to be called before proceeding in order to ensure consistent - // state - verify(mIkev2SessionCreator, timeout(TEST_TIMEOUT_MS)) - .createIkeSession(any(), any(), any(), any(), captor.capture(), any()); - final IkeSessionCallback ikeCb = captor.getValue(); - ikeCb.onClosedExceptionally(exception); - - verify(mConnectivityManager, timeout(TEST_TIMEOUT_MS)).unregisterNetworkCallback(eq(cb)); - assertEquals(LegacyVpnInfo.STATE_FAILED, vpn.getLegacyVpnInfo().state); - } - - @Test - public void testStartPlatformVpnIllegalArgumentExceptionInSetup() throws Exception { - when(mIkev2SessionCreator.createIkeSession(any(), any(), any(), any(), any(), any())) - .thenThrow(new IllegalArgumentException()); - final Vpn vpn = startLegacyVpn(createVpn(primaryUser.id), mVpnProfile); - final NetworkCallback cb = triggerOnAvailableAndGetCallback(); - - verifyInterfaceSetCfgWithFlags(IF_STATE_UP); - - // Wait for createIkeSession() to be called before proceeding in order to ensure consistent - // state - verify(mConnectivityManager, timeout(TEST_TIMEOUT_MS)).unregisterNetworkCallback(eq(cb)); - assertEquals(LegacyVpnInfo.STATE_FAILED, vpn.getLegacyVpnInfo().state); - } - - private void setAndVerifyAlwaysOnPackage(Vpn vpn, int uid, boolean lockdownEnabled) { - assertTrue(vpn.setAlwaysOnPackage(TEST_VPN_PKG, lockdownEnabled, null)); - - verify(mVpnProfileStore).get(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG))); - verify(mAppOps).setMode( - eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN), eq(uid), eq(TEST_VPN_PKG), - eq(AppOpsManager.MODE_ALLOWED)); - - verify(mSystemServices).settingsSecurePutStringForUser( - eq(Settings.Secure.ALWAYS_ON_VPN_APP), eq(TEST_VPN_PKG), eq(primaryUser.id)); - verify(mSystemServices).settingsSecurePutIntForUser( - eq(Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN), eq(lockdownEnabled ? 1 : 0), - eq(primaryUser.id)); - verify(mSystemServices).settingsSecurePutStringForUser( - eq(Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST), eq(""), eq(primaryUser.id)); - } - - @Test - public void testSetAndStartAlwaysOnVpn() throws Exception { - final Vpn vpn = createVpn(primaryUser.id); - setMockedUsers(primaryUser); - - // UID checks must return a different UID; otherwise it'll be treated as already prepared. - final int uid = Process.myUid() + 1; - when(mPackageManager.getPackageUidAsUser(eq(TEST_VPN_PKG), anyInt())) - .thenReturn(uid); - when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) - .thenReturn(mVpnProfile.encode()); - - setAndVerifyAlwaysOnPackage(vpn, uid, false); - assertTrue(vpn.startAlwaysOnVpn()); - - // TODO: Test the Ikev2VpnRunner started up properly. Relies on utility methods added in - // a subsequent CL. - } - - private Vpn startLegacyVpn(final Vpn vpn, final VpnProfile vpnProfile) throws Exception { - setMockedUsers(primaryUser); - - // Dummy egress interface - final LinkProperties lp = new LinkProperties(); - lp.setInterfaceName(EGRESS_IFACE); - - final RouteInfo defaultRoute = new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), - InetAddresses.parseNumericAddress("192.0.2.0"), EGRESS_IFACE); - lp.addRoute(defaultRoute); - - vpn.startLegacyVpn(vpnProfile, EGRESS_NETWORK, lp); - return vpn; - } - - @Test - public void testStartPlatformVpn() throws Exception { - startLegacyVpn(createVpn(primaryUser.id), mVpnProfile); - // TODO: Test the Ikev2VpnRunner started up properly. Relies on utility methods added in - // a subsequent patch. - } - - @Test - public void testStartRacoonNumericAddress() throws Exception { - startRacoon("1.2.3.4", "1.2.3.4"); - } - - @Test - public void testStartRacoonHostname() throws Exception { - startRacoon("hostname", "5.6.7.8"); // address returned by deps.resolve - } - - private void assertTransportInfoMatches(NetworkCapabilities nc, int type) { - assertNotNull(nc); - VpnTransportInfo ti = (VpnTransportInfo) nc.getTransportInfo(); - assertNotNull(ti); - assertEquals(type, ti.getType()); - } - - public void startRacoon(final String serverAddr, final String expectedAddr) - throws Exception { - final ConditionVariable legacyRunnerReady = new ConditionVariable(); - final VpnProfile profile = new VpnProfile("testProfile" /* key */); - profile.type = VpnProfile.TYPE_L2TP_IPSEC_PSK; - profile.name = "testProfileName"; - profile.username = "userName"; - profile.password = "thePassword"; - profile.server = serverAddr; - profile.ipsecIdentifier = "id"; - profile.ipsecSecret = "secret"; - profile.l2tpSecret = "l2tpsecret"; - - when(mConnectivityManager.getAllNetworks()) - .thenReturn(new Network[] { new Network(101) }); - - when(mConnectivityManager.registerNetworkAgent(any(), any(), any(), any(), - any(), any(), anyInt())).thenAnswer(invocation -> { - // The runner has registered an agent and is now ready. - legacyRunnerReady.open(); - return new Network(102); - }); - final Vpn vpn = startLegacyVpn(createVpn(primaryUser.id), profile); - final TestDeps deps = (TestDeps) vpn.mDeps; - try { - // udppsk and 1701 are the values for TYPE_L2TP_IPSEC_PSK - assertArrayEquals( - new String[] { EGRESS_IFACE, expectedAddr, "udppsk", - profile.ipsecIdentifier, profile.ipsecSecret, "1701" }, - deps.racoonArgs.get(10, TimeUnit.SECONDS)); - // literal values are hardcoded in Vpn.java for mtpd args - assertArrayEquals( - new String[] { EGRESS_IFACE, "l2tp", expectedAddr, "1701", profile.l2tpSecret, - "name", profile.username, "password", profile.password, - "linkname", "vpn", "refuse-eap", "nodefaultroute", "usepeerdns", - "idle", "1800", "mtu", "1270", "mru", "1270" }, - deps.mtpdArgs.get(10, TimeUnit.SECONDS)); - - // Now wait for the runner to be ready before testing for the route. - ArgumentCaptor lpCaptor = ArgumentCaptor.forClass(LinkProperties.class); - ArgumentCaptor ncCaptor = - ArgumentCaptor.forClass(NetworkCapabilities.class); - verify(mConnectivityManager, timeout(10_000)).registerNetworkAgent(any(), any(), - lpCaptor.capture(), ncCaptor.capture(), any(), any(), anyInt()); - - // In this test the expected address is always v4 so /32. - // Note that the interface needs to be specified because RouteInfo objects stored in - // LinkProperties objects always acquire the LinkProperties' interface. - final RouteInfo expectedRoute = new RouteInfo(new IpPrefix(expectedAddr + "/32"), - null, EGRESS_IFACE, RouteInfo.RTN_THROW); - final List actualRoutes = lpCaptor.getValue().getRoutes(); - assertTrue("Expected throw route (" + expectedRoute + ") not found in " + actualRoutes, - actualRoutes.contains(expectedRoute)); - - assertTransportInfoMatches(ncCaptor.getValue(), VpnManager.TYPE_VPN_LEGACY); - } finally { - // Now interrupt the thread, unblock the runner and clean up. - vpn.mVpnRunner.exitVpnRunner(); - deps.getStateFile().delete(); // set to delete on exit, but this deletes it earlier - vpn.mVpnRunner.join(10_000); // wait for up to 10s for the runner to die and cleanup - } - } - - private static final class TestDeps extends Vpn.Dependencies { - public final CompletableFuture racoonArgs = new CompletableFuture(); - public final CompletableFuture mtpdArgs = new CompletableFuture(); - public final File mStateFile; - - private final HashMap mRunningServices = new HashMap<>(); - - TestDeps() { - try { - mStateFile = File.createTempFile("vpnTest", ".tmp"); - mStateFile.deleteOnExit(); - } catch (final IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public boolean isCallerSystem() { - return true; - } - - @Override - public void startService(final String serviceName) { - mRunningServices.put(serviceName, true); - } - - @Override - public void stopService(final String serviceName) { - mRunningServices.put(serviceName, false); - } - - @Override - public boolean isServiceRunning(final String serviceName) { - return mRunningServices.getOrDefault(serviceName, false); - } - - @Override - public boolean isServiceStopped(final String serviceName) { - return !isServiceRunning(serviceName); - } - - @Override - public File getStateFile() { - return mStateFile; - } - - @Override - public PendingIntent getIntentForStatusPanel(Context context) { - return null; - } - - @Override - public void sendArgumentsToDaemon( - final String daemon, final LocalSocket socket, final String[] arguments, - final Vpn.RetryScheduler interruptChecker) throws IOException { - if ("racoon".equals(daemon)) { - racoonArgs.complete(arguments); - } else if ("mtpd".equals(daemon)) { - writeStateFile(arguments); - mtpdArgs.complete(arguments); - } else { - throw new UnsupportedOperationException("Unsupported daemon : " + daemon); - } - } - - private void writeStateFile(final String[] arguments) throws IOException { - mStateFile.delete(); - mStateFile.createNewFile(); - mStateFile.deleteOnExit(); - final BufferedWriter writer = new BufferedWriter( - new FileWriter(mStateFile, false /* append */)); - writer.write(EGRESS_IFACE); - writer.write("\n"); - // addresses - writer.write("10.0.0.1/24\n"); - // routes - writer.write("192.168.6.0/24\n"); - // dns servers - writer.write("192.168.6.1\n"); - // search domains - writer.write("vpn.searchdomains.com\n"); - // endpoint - intentionally empty - writer.write("\n"); - writer.flush(); - writer.close(); - } - - @Override - @NonNull - public InetAddress resolve(final String endpoint) { - try { - // If a numeric IP address, return it. - return InetAddress.parseNumericAddress(endpoint); - } catch (IllegalArgumentException e) { - // Otherwise, return some token IP to test for. - return InetAddress.parseNumericAddress("5.6.7.8"); - } - } - - @Override - public boolean isInterfacePresent(final Vpn vpn, final String iface) { - return true; - } - } - - /** - * Mock some methods of vpn object. - */ - private Vpn createVpn(@UserIdInt int userId) { - final Context asUserContext = mock(Context.class, AdditionalAnswers.delegatesTo(mContext)); - doReturn(UserHandle.of(userId)).when(asUserContext).getUser(); - when(mContext.createContextAsUser(eq(UserHandle.of(userId)), anyInt())) - .thenReturn(asUserContext); - final TestLooper testLooper = new TestLooper(); - final Vpn vpn = new Vpn(testLooper.getLooper(), mContext, new TestDeps(), mNetService, - mNetd, userId, mVpnProfileStore, mSystemServices, mIkev2SessionCreator); - verify(mConnectivityManager, times(1)).registerNetworkProvider(argThat( - provider -> provider.getName().contains("VpnNetworkProvider") - )); - return vpn; - } - - /** - * Populate {@link #mUserManager} with a list of fake users. - */ - private void setMockedUsers(UserInfo... users) { - final Map userMap = new ArrayMap<>(); - for (UserInfo user : users) { - userMap.put(user.id, user); - } - - /** - * @see UserManagerService#getUsers(boolean) - */ - doAnswer(invocation -> { - final ArrayList result = new ArrayList<>(users.length); - for (UserInfo ui : users) { - if (ui.isEnabled() && !ui.partial) { - result.add(ui); - } - } - return result; - }).when(mUserManager).getAliveUsers(); - - doAnswer(invocation -> { - final int id = (int) invocation.getArguments()[0]; - return userMap.get(id); - }).when(mUserManager).getUserInfo(anyInt()); - } - - /** - * Populate {@link #mPackageManager} with a fake packageName-to-UID mapping. - */ - private void setMockedPackages(final Map packages) { - try { - doAnswer(invocation -> { - final String appName = (String) invocation.getArguments()[0]; - final int userId = (int) invocation.getArguments()[1]; - Integer appId = packages.get(appName); - if (appId == null) throw new PackageManager.NameNotFoundException(appName); - return UserHandle.getUid(userId, appId); - }).when(mPackageManager).getPackageUidAsUser(anyString(), anyInt()); - } catch (Exception e) { - } - } - - private void setMockedNetworks(final Map networks) { - doAnswer(invocation -> { - final Network network = (Network) invocation.getArguments()[0]; - return networks.get(network); - }).when(mConnectivityManager).getNetworkCapabilities(any()); - } - - // Need multiple copies of this, but Java's Stream objects can't be reused or - // duplicated. - private Stream publicIpV4Routes() { - return Stream.of( - "0.0.0.0/5", "8.0.0.0/7", "11.0.0.0/8", "12.0.0.0/6", "16.0.0.0/4", - "32.0.0.0/3", "64.0.0.0/2", "128.0.0.0/3", "160.0.0.0/5", "168.0.0.0/6", - "172.0.0.0/12", "172.32.0.0/11", "172.64.0.0/10", "172.128.0.0/9", - "173.0.0.0/8", "174.0.0.0/7", "176.0.0.0/4", "192.0.0.0/9", "192.128.0.0/11", - "192.160.0.0/13", "192.169.0.0/16", "192.170.0.0/15", "192.172.0.0/14", - "192.176.0.0/12", "192.192.0.0/10", "193.0.0.0/8", "194.0.0.0/7", - "196.0.0.0/6", "200.0.0.0/5", "208.0.0.0/4"); - } - - private Stream publicIpV6Routes() { - return Stream.of( - "::/1", "8000::/2", "c000::/3", "e000::/4", "f000::/5", "f800::/6", - "fe00::/8", "2605:ef80:e:af1d::/64"); - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsAccessTest.java b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsAccessTest.java deleted file mode 100644 index 8b730af76951f..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsAccessTest.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.server.net; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.when; - -import android.Manifest; -import android.Manifest.permission; -import android.app.AppOpsManager; -import android.app.admin.DevicePolicyManagerInternal; -import android.content.Context; -import android.content.pm.PackageManager; -import android.telephony.TelephonyManager; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.server.LocalServices; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class NetworkStatsAccessTest { - private static final String TEST_PKG = "com.example.test"; - private static final int TEST_UID = 12345; - - @Mock private Context mContext; - @Mock private DevicePolicyManagerInternal mDpmi; - @Mock private TelephonyManager mTm; - @Mock private AppOpsManager mAppOps; - - // Hold the real service so we can restore it when tearing down the test. - private DevicePolicyManagerInternal mSystemDpmi; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - mSystemDpmi = LocalServices.getService(DevicePolicyManagerInternal.class); - LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); - LocalServices.addService(DevicePolicyManagerInternal.class, mDpmi); - - when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTm); - when(mContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOps); - } - - @After - public void tearDown() throws Exception { - LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); - LocalServices.addService(DevicePolicyManagerInternal.class, mSystemDpmi); - } - - @Test - public void testCheckAccessLevel_hasCarrierPrivileges() throws Exception { - setHasCarrierPrivileges(true); - setIsDeviceOwner(false); - setIsProfileOwner(false); - setHasAppOpsPermission(AppOpsManager.MODE_DEFAULT, false); - setHasReadHistoryPermission(false); - assertEquals(NetworkStatsAccess.Level.DEVICE, - NetworkStatsAccess.checkAccessLevel(mContext, TEST_UID, TEST_PKG)); - } - - @Test - public void testCheckAccessLevel_isDeviceOwner() throws Exception { - setHasCarrierPrivileges(false); - setIsDeviceOwner(true); - setIsProfileOwner(false); - setHasAppOpsPermission(AppOpsManager.MODE_DEFAULT, false); - setHasReadHistoryPermission(false); - assertEquals(NetworkStatsAccess.Level.DEVICE, - NetworkStatsAccess.checkAccessLevel(mContext, TEST_UID, TEST_PKG)); - } - - @Test - public void testCheckAccessLevel_isProfileOwner() throws Exception { - setHasCarrierPrivileges(false); - setIsDeviceOwner(false); - setIsProfileOwner(true); - setHasAppOpsPermission(AppOpsManager.MODE_DEFAULT, false); - setHasReadHistoryPermission(false); - assertEquals(NetworkStatsAccess.Level.USER, - NetworkStatsAccess.checkAccessLevel(mContext, TEST_UID, TEST_PKG)); - } - - @Test - public void testCheckAccessLevel_hasAppOpsBitAllowed() throws Exception { - setHasCarrierPrivileges(false); - setIsDeviceOwner(false); - setIsProfileOwner(true); - setHasAppOpsPermission(AppOpsManager.MODE_ALLOWED, false); - setHasReadHistoryPermission(false); - assertEquals(NetworkStatsAccess.Level.DEVICESUMMARY, - NetworkStatsAccess.checkAccessLevel(mContext, TEST_UID, TEST_PKG)); - } - - @Test - public void testCheckAccessLevel_hasAppOpsBitDefault_grantedPermission() throws Exception { - setHasCarrierPrivileges(false); - setIsDeviceOwner(false); - setIsProfileOwner(true); - setHasAppOpsPermission(AppOpsManager.MODE_DEFAULT, true); - setHasReadHistoryPermission(false); - assertEquals(NetworkStatsAccess.Level.DEVICESUMMARY, - NetworkStatsAccess.checkAccessLevel(mContext, TEST_UID, TEST_PKG)); - } - - @Test - public void testCheckAccessLevel_hasReadHistoryPermission() throws Exception { - setHasCarrierPrivileges(false); - setIsDeviceOwner(false); - setIsProfileOwner(true); - setHasAppOpsPermission(AppOpsManager.MODE_DEFAULT, false); - setHasReadHistoryPermission(true); - assertEquals(NetworkStatsAccess.Level.DEVICESUMMARY, - NetworkStatsAccess.checkAccessLevel(mContext, TEST_UID, TEST_PKG)); - } - - @Test - public void testCheckAccessLevel_deniedAppOpsBit() throws Exception { - setHasCarrierPrivileges(false); - setIsDeviceOwner(false); - setIsProfileOwner(false); - setHasAppOpsPermission(AppOpsManager.MODE_ERRORED, true); - setHasReadHistoryPermission(false); - assertEquals(NetworkStatsAccess.Level.DEFAULT, - NetworkStatsAccess.checkAccessLevel(mContext, TEST_UID, TEST_PKG)); - } - - @Test - public void testCheckAccessLevel_deniedAppOpsBit_deniedPermission() throws Exception { - setHasCarrierPrivileges(false); - setIsDeviceOwner(false); - setIsProfileOwner(false); - setHasAppOpsPermission(AppOpsManager.MODE_DEFAULT, false); - setHasReadHistoryPermission(false); - assertEquals(NetworkStatsAccess.Level.DEFAULT, - NetworkStatsAccess.checkAccessLevel(mContext, TEST_UID, TEST_PKG)); - } - - private void setHasCarrierPrivileges(boolean hasPrivileges) { - when(mTm.checkCarrierPrivilegesForPackageAnyPhone(TEST_PKG)).thenReturn( - hasPrivileges ? TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS - : TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS); - } - - private void setIsDeviceOwner(boolean isOwner) { - when(mDpmi.isActiveDeviceOwner(TEST_UID)).thenReturn(isOwner); - } - - private void setIsProfileOwner(boolean isOwner) { - when(mDpmi.isActiveProfileOwner(TEST_UID)).thenReturn(isOwner); - } - - private void setHasAppOpsPermission(int appOpsMode, boolean hasPermission) { - when(mAppOps.noteOp(AppOpsManager.OP_GET_USAGE_STATS, TEST_UID, TEST_PKG)) - .thenReturn(appOpsMode); - when(mContext.checkCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS)).thenReturn( - hasPermission ? PackageManager.PERMISSION_GRANTED - : PackageManager.PERMISSION_DENIED); - } - - private void setHasReadHistoryPermission(boolean hasPermission) { - when(mContext.checkCallingOrSelfPermission(permission.READ_NETWORK_USAGE_HISTORY)) - .thenReturn(hasPermission ? PackageManager.PERMISSION_GRANTED - : PackageManager.PERMISSION_DENIED); - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsBaseTest.java b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsBaseTest.java deleted file mode 100644 index a058a466a4ff0..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsBaseTest.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.net; - -import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; -import static android.net.NetworkStats.DEFAULT_NETWORK_NO; -import static android.net.NetworkStats.DEFAULT_NETWORK_YES; -import static android.net.NetworkStats.METERED_ALL; -import static android.net.NetworkStats.METERED_NO; -import static android.net.NetworkStats.METERED_YES; -import static android.net.NetworkStats.ROAMING_ALL; -import static android.net.NetworkStats.ROAMING_NO; -import static android.net.NetworkStats.ROAMING_YES; -import static android.net.NetworkStats.SET_ALL; -import static android.net.NetworkStats.SET_DEFAULT; -import static android.net.NetworkStats.SET_FOREGROUND; -import static android.net.NetworkStats.TAG_NONE; - -import static org.junit.Assert.assertEquals; - -import android.net.NetworkStats; -import android.net.UnderlyingNetworkInfo; - -import java.util.Arrays; - -/** Superclass with utilities for NetworkStats(Service|Factory)Test */ -abstract class NetworkStatsBaseTest { - static final String TEST_IFACE = "test0"; - static final String TEST_IFACE2 = "test1"; - static final String TUN_IFACE = "test_nss_tun0"; - static final String TUN_IFACE2 = "test_nss_tun1"; - - static final int UID_RED = 1001; - static final int UID_BLUE = 1002; - static final int UID_GREEN = 1003; - static final int UID_VPN = 1004; - - void assertValues(NetworkStats stats, String iface, int uid, long rxBytes, - long rxPackets, long txBytes, long txPackets) { - assertValues( - stats, iface, uid, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, - rxBytes, rxPackets, txBytes, txPackets, 0); - } - - void assertValues(NetworkStats stats, String iface, int uid, int set, int tag, - int metered, int roaming, int defaultNetwork, long rxBytes, long rxPackets, - long txBytes, long txPackets, long operations) { - final NetworkStats.Entry entry = new NetworkStats.Entry(); - final int[] sets; - if (set == SET_ALL) { - sets = new int[] {SET_ALL, SET_DEFAULT, SET_FOREGROUND}; - } else { - sets = new int[] {set}; - } - - final int[] roamings; - if (roaming == ROAMING_ALL) { - roamings = new int[] {ROAMING_ALL, ROAMING_YES, ROAMING_NO}; - } else { - roamings = new int[] {roaming}; - } - - final int[] meterings; - if (metered == METERED_ALL) { - meterings = new int[] {METERED_ALL, METERED_YES, METERED_NO}; - } else { - meterings = new int[] {metered}; - } - - final int[] defaultNetworks; - if (defaultNetwork == DEFAULT_NETWORK_ALL) { - defaultNetworks = - new int[] {DEFAULT_NETWORK_ALL, DEFAULT_NETWORK_YES, DEFAULT_NETWORK_NO}; - } else { - defaultNetworks = new int[] {defaultNetwork}; - } - - for (int s : sets) { - for (int r : roamings) { - for (int m : meterings) { - for (int d : defaultNetworks) { - final int i = stats.findIndex(iface, uid, s, tag, m, r, d); - if (i != -1) { - entry.add(stats.getValues(i, null)); - } - } - } - } - } - - assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); - assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets); - assertEquals("unexpected txBytes", txBytes, entry.txBytes); - assertEquals("unexpected txPackets", txPackets, entry.txPackets); - assertEquals("unexpected operations", operations, entry.operations); - } - - static UnderlyingNetworkInfo createVpnInfo(String[] underlyingIfaces) { - return createVpnInfo(TUN_IFACE, underlyingIfaces); - } - - static UnderlyingNetworkInfo createVpnInfo(String vpnIface, String[] underlyingIfaces) { - return new UnderlyingNetworkInfo(UID_VPN, vpnIface, Arrays.asList(underlyingIfaces)); - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsCollectionTest.java b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsCollectionTest.java deleted file mode 100644 index 505ff9b6a34bf..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsCollectionTest.java +++ /dev/null @@ -1,594 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.net; - -import static android.net.ConnectivityManager.TYPE_MOBILE; -import static android.net.NetworkIdentity.OEM_NONE; -import static android.net.NetworkStats.SET_ALL; -import static android.net.NetworkStats.SET_DEFAULT; -import static android.net.NetworkStats.TAG_NONE; -import static android.net.NetworkStats.UID_ALL; -import static android.net.NetworkStatsHistory.FIELD_ALL; -import static android.net.NetworkTemplate.buildTemplateMobileAll; -import static android.os.Process.myUid; -import static android.text.format.DateUtils.HOUR_IN_MILLIS; -import static android.text.format.DateUtils.MINUTE_IN_MILLIS; - -import static com.android.internal.net.NetworkUtilsInternal.multiplySafeByRational; -import static com.android.testutils.MiscAsserts.assertThrows; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; - -import android.content.res.Resources; -import android.net.ConnectivityManager; -import android.net.NetworkIdentity; -import android.net.NetworkStats; -import android.net.NetworkStatsHistory; -import android.net.NetworkTemplate; -import android.os.Process; -import android.os.UserHandle; -import android.telephony.SubscriptionPlan; -import android.telephony.TelephonyManager; -import android.text.format.DateUtils; -import android.util.RecurrenceRule; - -import androidx.test.InstrumentationRegistry; -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.frameworks.tests.net.R; - -import libcore.io.IoUtils; -import libcore.io.Streams; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.InputStream; -import java.io.OutputStream; -import java.time.Clock; -import java.time.Instant; -import java.time.ZoneId; -import java.time.ZonedDateTime; -import java.util.ArrayList; -import java.util.List; - -/** - * Tests for {@link NetworkStatsCollection}. - */ -@RunWith(AndroidJUnit4.class) -@SmallTest -public class NetworkStatsCollectionTest { - - private static final String TEST_FILE = "test.bin"; - private static final String TEST_IMSI = "310260000000000"; - - private static final long TIME_A = 1326088800000L; // UTC: Monday 9th January 2012 06:00:00 AM - private static final long TIME_B = 1326110400000L; // UTC: Monday 9th January 2012 12:00:00 PM - private static final long TIME_C = 1326132000000L; // UTC: Monday 9th January 2012 06:00:00 PM - - private static Clock sOriginalClock; - - @Before - public void setUp() throws Exception { - sOriginalClock = RecurrenceRule.sClock; - // ignore any device overlay while testing - NetworkTemplate.forceAllNetworkTypes(); - } - - @After - public void tearDown() throws Exception { - RecurrenceRule.sClock = sOriginalClock; - NetworkTemplate.resetForceAllNetworkTypes(); - } - - private void setClock(Instant instant) { - RecurrenceRule.sClock = Clock.fixed(instant, ZoneId.systemDefault()); - } - - @Test - public void testReadLegacyNetwork() throws Exception { - final File testFile = - new File(InstrumentationRegistry.getContext().getFilesDir(), TEST_FILE); - stageFile(R.raw.netstats_v1, testFile); - - final NetworkStatsCollection collection = new NetworkStatsCollection(30 * MINUTE_IN_MILLIS); - collection.readLegacyNetwork(testFile); - - // verify that history read correctly - assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI), - 636016770L, 709306L, 88038768L, 518836L, NetworkStatsAccess.Level.DEVICE); - - // now export into a unified format - final ByteArrayOutputStream bos = new ByteArrayOutputStream(); - collection.write(bos); - - // clear structure completely - collection.reset(); - assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI), - 0L, 0L, 0L, 0L, NetworkStatsAccess.Level.DEVICE); - - // and read back into structure, verifying that totals are same - collection.read(new ByteArrayInputStream(bos.toByteArray())); - assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI), - 636016770L, 709306L, 88038768L, 518836L, NetworkStatsAccess.Level.DEVICE); - } - - @Test - public void testReadLegacyUid() throws Exception { - final File testFile = - new File(InstrumentationRegistry.getContext().getFilesDir(), TEST_FILE); - stageFile(R.raw.netstats_uid_v4, testFile); - - final NetworkStatsCollection collection = new NetworkStatsCollection(30 * MINUTE_IN_MILLIS); - collection.readLegacyUid(testFile, false); - - // verify that history read correctly - assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI), - 637076152L, 711413L, 88343717L, 521022L, NetworkStatsAccess.Level.DEVICE); - - // now export into a unified format - final ByteArrayOutputStream bos = new ByteArrayOutputStream(); - collection.write(bos); - - // clear structure completely - collection.reset(); - assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI), - 0L, 0L, 0L, 0L, NetworkStatsAccess.Level.DEVICE); - - // and read back into structure, verifying that totals are same - collection.read(new ByteArrayInputStream(bos.toByteArray())); - assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI), - 637076152L, 711413L, 88343717L, 521022L, NetworkStatsAccess.Level.DEVICE); - } - - @Test - public void testReadLegacyUidTags() throws Exception { - final File testFile = - new File(InstrumentationRegistry.getContext().getFilesDir(), TEST_FILE); - stageFile(R.raw.netstats_uid_v4, testFile); - - final NetworkStatsCollection collection = new NetworkStatsCollection(30 * MINUTE_IN_MILLIS); - collection.readLegacyUid(testFile, true); - - // verify that history read correctly - assertSummaryTotalIncludingTags(collection, buildTemplateMobileAll(TEST_IMSI), - 77017831L, 100995L, 35436758L, 92344L); - - // now export into a unified format - final ByteArrayOutputStream bos = new ByteArrayOutputStream(); - collection.write(bos); - - // clear structure completely - collection.reset(); - assertSummaryTotalIncludingTags(collection, buildTemplateMobileAll(TEST_IMSI), - 0L, 0L, 0L, 0L); - - // and read back into structure, verifying that totals are same - collection.read(new ByteArrayInputStream(bos.toByteArray())); - assertSummaryTotalIncludingTags(collection, buildTemplateMobileAll(TEST_IMSI), - 77017831L, 100995L, 35436758L, 92344L); - } - - @Test - public void testStartEndAtomicBuckets() throws Exception { - final NetworkStatsCollection collection = new NetworkStatsCollection(HOUR_IN_MILLIS); - - // record empty data straddling between buckets - final NetworkStats.Entry entry = new NetworkStats.Entry(); - entry.rxBytes = 32; - collection.recordData(null, UID_ALL, SET_DEFAULT, TAG_NONE, 30 * MINUTE_IN_MILLIS, - 90 * MINUTE_IN_MILLIS, entry); - - // assert that we report boundary in atomic buckets - assertEquals(0, collection.getStartMillis()); - assertEquals(2 * HOUR_IN_MILLIS, collection.getEndMillis()); - } - - @Test - public void testAccessLevels() throws Exception { - final NetworkStatsCollection collection = new NetworkStatsCollection(HOUR_IN_MILLIS); - final NetworkStats.Entry entry = new NetworkStats.Entry(); - final NetworkIdentitySet identSet = new NetworkIdentitySet(); - identSet.add(new NetworkIdentity(TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, - TEST_IMSI, null, false, true, true, OEM_NONE)); - - int myUid = Process.myUid(); - int otherUidInSameUser = Process.myUid() + 1; - int uidInDifferentUser = Process.myUid() + UserHandle.PER_USER_RANGE; - - // Record one entry for the current UID. - entry.rxBytes = 32; - collection.recordData(identSet, myUid, SET_DEFAULT, TAG_NONE, 0, 60 * MINUTE_IN_MILLIS, - entry); - - // Record one entry for another UID in this user. - entry.rxBytes = 64; - collection.recordData(identSet, otherUidInSameUser, SET_DEFAULT, TAG_NONE, 0, - 60 * MINUTE_IN_MILLIS, entry); - - // Record one entry for the system UID. - entry.rxBytes = 128; - collection.recordData(identSet, Process.SYSTEM_UID, SET_DEFAULT, TAG_NONE, 0, - 60 * MINUTE_IN_MILLIS, entry); - - // Record one entry for a UID in a different user. - entry.rxBytes = 256; - collection.recordData(identSet, uidInDifferentUser, SET_DEFAULT, TAG_NONE, 0, - 60 * MINUTE_IN_MILLIS, entry); - - // Verify the set of relevant UIDs for each access level. - assertArrayEquals(new int[] { myUid }, - collection.getRelevantUids(NetworkStatsAccess.Level.DEFAULT)); - assertArrayEquals(new int[] { Process.SYSTEM_UID, myUid, otherUidInSameUser }, - collection.getRelevantUids(NetworkStatsAccess.Level.USER)); - assertArrayEquals( - new int[] { Process.SYSTEM_UID, myUid, otherUidInSameUser, uidInDifferentUser }, - collection.getRelevantUids(NetworkStatsAccess.Level.DEVICE)); - - // Verify security check in getHistory. - assertNotNull(collection.getHistory(buildTemplateMobileAll(TEST_IMSI), null, myUid, SET_DEFAULT, - TAG_NONE, 0, 0L, 0L, NetworkStatsAccess.Level.DEFAULT, myUid)); - try { - collection.getHistory(buildTemplateMobileAll(TEST_IMSI), null, otherUidInSameUser, - SET_DEFAULT, TAG_NONE, 0, 0L, 0L, NetworkStatsAccess.Level.DEFAULT, myUid); - fail("Should have thrown SecurityException for accessing different UID"); - } catch (SecurityException e) { - // expected - } - - // Verify appropriate aggregation in getSummary. - assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI), 32, 0, 0, 0, - NetworkStatsAccess.Level.DEFAULT); - assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI), 32 + 64 + 128, 0, 0, 0, - NetworkStatsAccess.Level.USER); - assertSummaryTotal(collection, buildTemplateMobileAll(TEST_IMSI), 32 + 64 + 128 + 256, 0, 0, - 0, NetworkStatsAccess.Level.DEVICE); - } - - @Test - public void testAugmentPlan() throws Exception { - final File testFile = - new File(InstrumentationRegistry.getContext().getFilesDir(), TEST_FILE); - stageFile(R.raw.netstats_v1, testFile); - - final NetworkStatsCollection emptyCollection = new NetworkStatsCollection(30 * MINUTE_IN_MILLIS); - final NetworkStatsCollection collection = new NetworkStatsCollection(30 * MINUTE_IN_MILLIS); - collection.readLegacyNetwork(testFile); - - // We're in the future, but not that far off - setClock(Instant.parse("2012-06-01T00:00:00.00Z")); - - // Test a bunch of plans that should result in no augmentation - final List plans = new ArrayList<>(); - - // No plan - plans.add(null); - // No usage anchor - plans.add(SubscriptionPlan.Builder - .createRecurringMonthly(ZonedDateTime.parse("2011-01-14T00:00:00.00Z")).build()); - // Usage anchor far in past - plans.add(SubscriptionPlan.Builder - .createRecurringMonthly(ZonedDateTime.parse("2011-01-14T00:00:00.00Z")) - .setDataUsage(1000L, TIME_A - DateUtils.YEAR_IN_MILLIS).build()); - // Usage anchor far in future - plans.add(SubscriptionPlan.Builder - .createRecurringMonthly(ZonedDateTime.parse("2011-01-14T00:00:00.00Z")) - .setDataUsage(1000L, TIME_A + DateUtils.YEAR_IN_MILLIS).build()); - // Usage anchor near but outside cycle - plans.add(SubscriptionPlan.Builder - .createNonrecurring(ZonedDateTime.parse("2012-01-09T09:00:00.00Z"), - ZonedDateTime.parse("2012-01-09T15:00:00.00Z")) - .setDataUsage(1000L, TIME_C).build()); - - for (SubscriptionPlan plan : plans) { - int i; - NetworkStatsHistory history; - - // Empty collection should be untouched - history = getHistory(emptyCollection, plan, TIME_A, TIME_C); - assertEquals(0L, history.getTotalBytes()); - - // Normal collection should be untouched - history = getHistory(collection, plan, TIME_A, TIME_C); i = 0; - assertEntry(100647, 197, 23649, 185, history.getValues(i++, null)); - assertEntry(100647, 196, 23648, 185, history.getValues(i++, null)); - assertEntry(18323, 76, 15032, 76, history.getValues(i++, null)); - assertEntry(18322, 75, 15031, 75, history.getValues(i++, null)); - assertEntry(527798, 761, 78570, 652, history.getValues(i++, null)); - assertEntry(527797, 760, 78570, 651, history.getValues(i++, null)); - assertEntry(10747, 50, 16839, 55, history.getValues(i++, null)); - assertEntry(10747, 49, 16837, 54, history.getValues(i++, null)); - assertEntry(89191, 151, 18021, 140, history.getValues(i++, null)); - assertEntry(89190, 150, 18020, 139, history.getValues(i++, null)); - assertEntry(3821, 23, 4525, 26, history.getValues(i++, null)); - assertEntry(3820, 21, 4524, 26, history.getValues(i++, null)); - assertEntry(91686, 159, 18576, 146, history.getValues(i++, null)); - assertEntry(91685, 159, 18574, 146, history.getValues(i++, null)); - assertEntry(8289, 36, 6864, 39, history.getValues(i++, null)); - assertEntry(8289, 34, 6862, 37, history.getValues(i++, null)); - assertEntry(113914, 174, 18364, 157, history.getValues(i++, null)); - assertEntry(113913, 173, 18364, 157, history.getValues(i++, null)); - assertEntry(11378, 49, 9261, 50, history.getValues(i++, null)); - assertEntry(11377, 48, 9261, 48, history.getValues(i++, null)); - assertEntry(201766, 328, 41808, 291, history.getValues(i++, null)); - assertEntry(201764, 328, 41807, 290, history.getValues(i++, null)); - assertEntry(106106, 219, 39918, 202, history.getValues(i++, null)); - assertEntry(106105, 216, 39916, 200, history.getValues(i++, null)); - assertEquals(history.size(), i); - - // Slice from middle should be untouched - history = getHistory(collection, plan, TIME_B - HOUR_IN_MILLIS, - TIME_B + HOUR_IN_MILLIS); i = 0; - assertEntry(3821, 23, 4525, 26, history.getValues(i++, null)); - assertEntry(3820, 21, 4524, 26, history.getValues(i++, null)); - assertEntry(91686, 159, 18576, 146, history.getValues(i++, null)); - assertEntry(91685, 159, 18574, 146, history.getValues(i++, null)); - assertEquals(history.size(), i); - } - - // Lower anchor in the middle of plan - { - int i; - NetworkStatsHistory history; - - final SubscriptionPlan plan = SubscriptionPlan.Builder - .createNonrecurring(ZonedDateTime.parse("2012-01-09T09:00:00.00Z"), - ZonedDateTime.parse("2012-01-09T15:00:00.00Z")) - .setDataUsage(200000L, TIME_B).build(); - - // Empty collection should be augmented - history = getHistory(emptyCollection, plan, TIME_A, TIME_C); - assertEquals(200000L, history.getTotalBytes()); - - // Normal collection should be augmented - history = getHistory(collection, plan, TIME_A, TIME_C); i = 0; - assertEntry(100647, 197, 23649, 185, history.getValues(i++, null)); - assertEntry(100647, 196, 23648, 185, history.getValues(i++, null)); - assertEntry(18323, 76, 15032, 76, history.getValues(i++, null)); - assertEntry(18322, 75, 15031, 75, history.getValues(i++, null)); - assertEntry(527798, 761, 78570, 652, history.getValues(i++, null)); - assertEntry(527797, 760, 78570, 651, history.getValues(i++, null)); - // Cycle point; start data normalization - assertEntry(7507, 0, 11763, 0, history.getValues(i++, null)); - assertEntry(7507, 0, 11762, 0, history.getValues(i++, null)); - assertEntry(62309, 0, 12589, 0, history.getValues(i++, null)); - assertEntry(62309, 0, 12588, 0, history.getValues(i++, null)); - assertEntry(2669, 0, 3161, 0, history.getValues(i++, null)); - assertEntry(2668, 0, 3160, 0, history.getValues(i++, null)); - // Anchor point; end data normalization - assertEntry(91686, 159, 18576, 146, history.getValues(i++, null)); - assertEntry(91685, 159, 18574, 146, history.getValues(i++, null)); - assertEntry(8289, 36, 6864, 39, history.getValues(i++, null)); - assertEntry(8289, 34, 6862, 37, history.getValues(i++, null)); - assertEntry(113914, 174, 18364, 157, history.getValues(i++, null)); - assertEntry(113913, 173, 18364, 157, history.getValues(i++, null)); - // Cycle point - assertEntry(11378, 49, 9261, 50, history.getValues(i++, null)); - assertEntry(11377, 48, 9261, 48, history.getValues(i++, null)); - assertEntry(201766, 328, 41808, 291, history.getValues(i++, null)); - assertEntry(201764, 328, 41807, 290, history.getValues(i++, null)); - assertEntry(106106, 219, 39918, 202, history.getValues(i++, null)); - assertEntry(106105, 216, 39916, 200, history.getValues(i++, null)); - assertEquals(history.size(), i); - - // Slice from middle should be augmented - history = getHistory(collection, plan, TIME_B - HOUR_IN_MILLIS, - TIME_B + HOUR_IN_MILLIS); i = 0; - assertEntry(2669, 0, 3161, 0, history.getValues(i++, null)); - assertEntry(2668, 0, 3160, 0, history.getValues(i++, null)); - assertEntry(91686, 159, 18576, 146, history.getValues(i++, null)); - assertEntry(91685, 159, 18574, 146, history.getValues(i++, null)); - assertEquals(history.size(), i); - } - - // Higher anchor in the middle of plan - { - int i; - NetworkStatsHistory history; - - final SubscriptionPlan plan = SubscriptionPlan.Builder - .createNonrecurring(ZonedDateTime.parse("2012-01-09T09:00:00.00Z"), - ZonedDateTime.parse("2012-01-09T15:00:00.00Z")) - .setDataUsage(400000L, TIME_B + MINUTE_IN_MILLIS).build(); - - // Empty collection should be augmented - history = getHistory(emptyCollection, plan, TIME_A, TIME_C); - assertEquals(400000L, history.getTotalBytes()); - - // Normal collection should be augmented - history = getHistory(collection, plan, TIME_A, TIME_C); i = 0; - assertEntry(100647, 197, 23649, 185, history.getValues(i++, null)); - assertEntry(100647, 196, 23648, 185, history.getValues(i++, null)); - assertEntry(18323, 76, 15032, 76, history.getValues(i++, null)); - assertEntry(18322, 75, 15031, 75, history.getValues(i++, null)); - assertEntry(527798, 761, 78570, 652, history.getValues(i++, null)); - assertEntry(527797, 760, 78570, 651, history.getValues(i++, null)); - // Cycle point; start data normalization - assertEntry(15015, 0, 23527, 0, history.getValues(i++, null)); - assertEntry(15015, 0, 23524, 0, history.getValues(i++, null)); - assertEntry(124619, 0, 25179, 0, history.getValues(i++, null)); - assertEntry(124618, 0, 25177, 0, history.getValues(i++, null)); - assertEntry(5338, 0, 6322, 0, history.getValues(i++, null)); - assertEntry(5337, 0, 6320, 0, history.getValues(i++, null)); - // Anchor point; end data normalization - assertEntry(91686, 159, 18576, 146, history.getValues(i++, null)); - assertEntry(91685, 159, 18574, 146, history.getValues(i++, null)); - assertEntry(8289, 36, 6864, 39, history.getValues(i++, null)); - assertEntry(8289, 34, 6862, 37, history.getValues(i++, null)); - assertEntry(113914, 174, 18364, 157, history.getValues(i++, null)); - assertEntry(113913, 173, 18364, 157, history.getValues(i++, null)); - // Cycle point - assertEntry(11378, 49, 9261, 50, history.getValues(i++, null)); - assertEntry(11377, 48, 9261, 48, history.getValues(i++, null)); - assertEntry(201766, 328, 41808, 291, history.getValues(i++, null)); - assertEntry(201764, 328, 41807, 290, history.getValues(i++, null)); - assertEntry(106106, 219, 39918, 202, history.getValues(i++, null)); - assertEntry(106105, 216, 39916, 200, history.getValues(i++, null)); - - // Slice from middle should be augmented - history = getHistory(collection, plan, TIME_B - HOUR_IN_MILLIS, - TIME_B + HOUR_IN_MILLIS); i = 0; - assertEntry(5338, 0, 6322, 0, history.getValues(i++, null)); - assertEntry(5337, 0, 6320, 0, history.getValues(i++, null)); - assertEntry(91686, 159, 18576, 146, history.getValues(i++, null)); - assertEntry(91685, 159, 18574, 146, history.getValues(i++, null)); - assertEquals(history.size(), i); - } - } - - @Test - public void testAugmentPlanGigantic() throws Exception { - // We're in the future, but not that far off - setClock(Instant.parse("2012-06-01T00:00:00.00Z")); - - // Create a simple history with a ton of measured usage - final NetworkStatsCollection large = new NetworkStatsCollection(HOUR_IN_MILLIS); - final NetworkIdentitySet ident = new NetworkIdentitySet(); - ident.add(new NetworkIdentity(ConnectivityManager.TYPE_MOBILE, -1, TEST_IMSI, null, - false, true, true, OEM_NONE)); - large.recordData(ident, UID_ALL, SET_ALL, TAG_NONE, TIME_A, TIME_B, - new NetworkStats.Entry(12_730_893_164L, 1, 0, 0, 0)); - - // Verify untouched total - assertEquals(12_730_893_164L, getHistory(large, null, TIME_A, TIME_C).getTotalBytes()); - - // Verify anchor that might cause overflows - final SubscriptionPlan plan = SubscriptionPlan.Builder - .createRecurringMonthly(ZonedDateTime.parse("2012-01-09T00:00:00.00Z")) - .setDataUsage(4_939_212_390L, TIME_B).build(); - assertEquals(4_939_212_386L, getHistory(large, plan, TIME_A, TIME_C).getTotalBytes()); - } - - @Test - public void testRounding() throws Exception { - final NetworkStatsCollection coll = new NetworkStatsCollection(HOUR_IN_MILLIS); - - // Special values should remain unchanged - for (long time : new long[] { - Long.MIN_VALUE, Long.MAX_VALUE, SubscriptionPlan.TIME_UNKNOWN - }) { - assertEquals(time, coll.roundUp(time)); - assertEquals(time, coll.roundDown(time)); - } - - assertEquals(TIME_A, coll.roundUp(TIME_A)); - assertEquals(TIME_A, coll.roundDown(TIME_A)); - - assertEquals(TIME_A + HOUR_IN_MILLIS, coll.roundUp(TIME_A + 1)); - assertEquals(TIME_A, coll.roundDown(TIME_A + 1)); - - assertEquals(TIME_A, coll.roundUp(TIME_A - 1)); - assertEquals(TIME_A - HOUR_IN_MILLIS, coll.roundDown(TIME_A - 1)); - } - - @Test - public void testMultiplySafeRational() { - assertEquals(25, multiplySafeByRational(50, 1, 2)); - assertEquals(100, multiplySafeByRational(50, 2, 1)); - - assertEquals(-10, multiplySafeByRational(30, -1, 3)); - assertEquals(0, multiplySafeByRational(30, 0, 3)); - assertEquals(10, multiplySafeByRational(30, 1, 3)); - assertEquals(20, multiplySafeByRational(30, 2, 3)); - assertEquals(30, multiplySafeByRational(30, 3, 3)); - assertEquals(40, multiplySafeByRational(30, 4, 3)); - - assertEquals(100_000_000_000L, - multiplySafeByRational(300_000_000_000L, 10_000_000_000L, 30_000_000_000L)); - assertEquals(100_000_000_010L, - multiplySafeByRational(300_000_000_000L, 10_000_000_001L, 30_000_000_000L)); - assertEquals(823_202_048L, - multiplySafeByRational(4_939_212_288L, 2_121_815_528L, 12_730_893_165L)); - - assertThrows(ArithmeticException.class, () -> multiplySafeByRational(30, 3, 0)); - } - - /** - * Copy a {@link Resources#openRawResource(int)} into {@link File} for - * testing purposes. - */ - private void stageFile(int rawId, File file) throws Exception { - new File(file.getParent()).mkdirs(); - InputStream in = null; - OutputStream out = null; - try { - in = InstrumentationRegistry.getContext().getResources().openRawResource(rawId); - out = new FileOutputStream(file); - Streams.copy(in, out); - } finally { - IoUtils.closeQuietly(in); - IoUtils.closeQuietly(out); - } - } - - private static NetworkStatsHistory getHistory(NetworkStatsCollection collection, - SubscriptionPlan augmentPlan, long start, long end) { - return collection.getHistory(buildTemplateMobileAll(TEST_IMSI), augmentPlan, UID_ALL, - SET_ALL, TAG_NONE, FIELD_ALL, start, end, NetworkStatsAccess.Level.DEVICE, myUid()); - } - - private static void assertSummaryTotal(NetworkStatsCollection collection, - NetworkTemplate template, long rxBytes, long rxPackets, long txBytes, long txPackets, - @NetworkStatsAccess.Level int accessLevel) { - final NetworkStats.Entry actual = collection.getSummary( - template, Long.MIN_VALUE, Long.MAX_VALUE, accessLevel, myUid()) - .getTotal(null); - assertEntry(rxBytes, rxPackets, txBytes, txPackets, actual); - } - - private static void assertSummaryTotalIncludingTags(NetworkStatsCollection collection, - NetworkTemplate template, long rxBytes, long rxPackets, long txBytes, long txPackets) { - final NetworkStats.Entry actual = collection.getSummary( - template, Long.MIN_VALUE, Long.MAX_VALUE, NetworkStatsAccess.Level.DEVICE, myUid()) - .getTotalIncludingTags(null); - assertEntry(rxBytes, rxPackets, txBytes, txPackets, actual); - } - - private static void assertEntry(long rxBytes, long rxPackets, long txBytes, long txPackets, - NetworkStats.Entry actual) { - assertEntry(new NetworkStats.Entry(rxBytes, rxPackets, txBytes, txPackets, 0L), actual); - } - - private static void assertEntry(long rxBytes, long rxPackets, long txBytes, long txPackets, - NetworkStatsHistory.Entry actual) { - assertEntry(new NetworkStats.Entry(rxBytes, rxPackets, txBytes, txPackets, 0L), actual); - } - - private static void assertEntry(NetworkStats.Entry expected, - NetworkStatsHistory.Entry actual) { - assertEntry(expected, new NetworkStats.Entry(actual.rxBytes, actual.rxPackets, - actual.txBytes, actual.txPackets, 0L)); - } - - private static void assertEntry(NetworkStats.Entry expected, - NetworkStats.Entry actual) { - assertEquals("unexpected rxBytes", expected.rxBytes, actual.rxBytes); - assertEquals("unexpected rxPackets", expected.rxPackets, actual.rxPackets); - assertEquals("unexpected txBytes", expected.txBytes, actual.txBytes); - assertEquals("unexpected txPackets", expected.txPackets, actual.txPackets); - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java deleted file mode 100644 index f3ae9b051e7ca..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java +++ /dev/null @@ -1,578 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.net; - -import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; -import static android.net.NetworkStats.DEFAULT_NETWORK_NO; -import static android.net.NetworkStats.METERED_ALL; -import static android.net.NetworkStats.METERED_NO; -import static android.net.NetworkStats.ROAMING_ALL; -import static android.net.NetworkStats.ROAMING_NO; -import static android.net.NetworkStats.SET_ALL; -import static android.net.NetworkStats.SET_DEFAULT; -import static android.net.NetworkStats.SET_FOREGROUND; -import static android.net.NetworkStats.TAG_NONE; -import static android.net.NetworkStats.UID_ALL; - -import static com.android.server.NetworkManagementSocketTagger.kernelToTag; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import android.content.res.Resources; -import android.net.NetworkStats; -import android.net.TrafficStats; -import android.net.UnderlyingNetworkInfo; - -import androidx.test.InstrumentationRegistry; -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.frameworks.tests.net.R; - -import libcore.io.IoUtils; -import libcore.io.Streams; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.InputStream; -import java.io.OutputStream; - -/** Tests for {@link NetworkStatsFactory}. */ -@RunWith(AndroidJUnit4.class) -@SmallTest -public class NetworkStatsFactoryTest extends NetworkStatsBaseTest { - private static final String CLAT_PREFIX = "v4-"; - - private File mTestProc; - private NetworkStatsFactory mFactory; - - @Before - public void setUp() throws Exception { - mTestProc = new File(InstrumentationRegistry.getContext().getFilesDir(), "proc"); - if (mTestProc.exists()) { - IoUtils.deleteContents(mTestProc); - } - - // The libandroid_servers which have the native method is not available to - // applications. So in order to have a test support native library, the native code - // related to networkStatsFactory is compiled to a minimal native library and loaded here. - System.loadLibrary("networkstatsfactorytestjni"); - mFactory = new NetworkStatsFactory(mTestProc, false); - mFactory.updateUnderlyingNetworkInfos(new UnderlyingNetworkInfo[0]); - } - - @After - public void tearDown() throws Exception { - mFactory = null; - - if (mTestProc.exists()) { - IoUtils.deleteContents(mTestProc); - } - } - - @Test - public void testNetworkStatsDetail() throws Exception { - final NetworkStats stats = parseDetailedStats(R.raw.xt_qtaguid_typical); - - assertEquals(70, stats.size()); - assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, 18621L, 2898L); - assertStatsEntry(stats, "wlan0", 10011, SET_DEFAULT, 0x0, 35777L, 5718L); - assertStatsEntry(stats, "wlan0", 10021, SET_DEFAULT, 0x7fffff01, 562386L, 49228L); - assertStatsEntry(stats, "rmnet1", 10021, SET_DEFAULT, 0x30100000, 219110L, 227423L); - assertStatsEntry(stats, "rmnet2", 10001, SET_DEFAULT, 0x0, 1125899906842624L, 984L); - } - - @Test - public void testVpnRewriteTrafficThroughItself() throws Exception { - UnderlyingNetworkInfo[] underlyingNetworkInfos = - new UnderlyingNetworkInfo[] {createVpnInfo(new String[] {TEST_IFACE})}; - mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos); - - // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption - // overhead per packet): - // - // 1000 bytes (100 packets) were sent, and 2000 bytes (200 packets) were received by UID_RED - // over VPN. - // 500 bytes (50 packets) were sent, and 1000 bytes (100 packets) were received by UID_BLUE - // over VPN. - // - // VPN UID rewrites packets read from TUN back to TUN, plus some of its own traffic - - final NetworkStats tunStats = parseDetailedStats(R.raw.xt_qtaguid_vpn_rewrite_through_self); - - assertValues(tunStats, TUN_IFACE, UID_RED, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, - DEFAULT_NETWORK_ALL, 2000L, 200L, 1000L, 100L, 0); - assertValues(tunStats, TUN_IFACE, UID_BLUE, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, - DEFAULT_NETWORK_ALL, 1000L, 100L, 500L, 50L, 0); - assertValues(tunStats, TUN_IFACE, UID_VPN, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, - DEFAULT_NETWORK_ALL, 0L, 0L, 1600L, 160L, 0); - - assertValues(tunStats, TEST_IFACE, UID_RED, 2000L, 200L, 1000L, 100L); - assertValues(tunStats, TEST_IFACE, UID_BLUE, 1000L, 100L, 500L, 50L); - assertValues(tunStats, TEST_IFACE, UID_VPN, 300L, 0L, 260L, 26L); - } - - @Test - public void testVpnWithClat() throws Exception { - final UnderlyingNetworkInfo[] underlyingNetworkInfos = new UnderlyingNetworkInfo[] { - createVpnInfo(new String[] {CLAT_PREFIX + TEST_IFACE})}; - mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos); - mFactory.noteStackedIface(CLAT_PREFIX + TEST_IFACE, TEST_IFACE); - - // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption - // overhead per packet): - // 1000 bytes (100 packets) were sent, and 2000 bytes (200 packets) were received by UID_RED - // over VPN. - // 500 bytes (50 packets) were sent, and 1000 bytes (100 packets) were received by UID_BLUE - // over VPN. - // VPN sent 1650 bytes (150 packets), and received 3300 (300 packets) over v4-WiFi, and clat - // added 20 bytes per packet of extra overhead - // - // For 1650 bytes sent over v4-WiFi, 4650 bytes were actually sent over WiFi, which is - // expected to be split as follows: - // UID_RED: 1000 bytes, 100 packets - // UID_BLUE: 500 bytes, 50 packets - // UID_VPN: 3150 bytes, 0 packets - // - // For 3300 bytes received over v4-WiFi, 9300 bytes were actually sent over WiFi, which is - // expected to be split as follows: - // UID_RED: 2000 bytes, 200 packets - // UID_BLUE: 1000 bytes, 100 packets - // UID_VPN: 6300 bytes, 0 packets - final NetworkStats tunStats = parseDetailedStats(R.raw.xt_qtaguid_vpn_with_clat); - - assertValues(tunStats, CLAT_PREFIX + TEST_IFACE, UID_RED, 2000L, 200L, 1000, 100L); - assertValues(tunStats, CLAT_PREFIX + TEST_IFACE, UID_BLUE, 1000L, 100L, 500L, 50L); - assertValues(tunStats, CLAT_PREFIX + TEST_IFACE, UID_VPN, 6300L, 0L, 3150L, 0L); - } - - @Test - public void testVpnWithOneUnderlyingIface() throws Exception { - final UnderlyingNetworkInfo[] underlyingNetworkInfos = - new UnderlyingNetworkInfo[] {createVpnInfo(new String[] {TEST_IFACE})}; - mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos); - - // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption - // overhead per packet): - // 1000 bytes (100 packets) were sent, and 2000 bytes (200 packets) were received by UID_RED - // over VPN. - // 500 bytes (50 packets) were sent, and 1000 bytes (100 packets) were received by UID_BLUE - // over VPN. - // VPN sent 1650 bytes (150 packets), and received 3300 (300 packets) over WiFi. - // Of 1650 bytes sent over WiFi, expect 1000 bytes attributed to UID_RED, 500 bytes - // attributed to UID_BLUE, and 150 bytes attributed to UID_VPN. - // Of 3300 bytes received over WiFi, expect 2000 bytes attributed to UID_RED, 1000 bytes - // attributed to UID_BLUE, and 300 bytes attributed to UID_VPN. - final NetworkStats tunStats = parseDetailedStats(R.raw.xt_qtaguid_vpn_one_underlying); - - assertValues(tunStats, TEST_IFACE, UID_RED, 2000L, 200L, 1000L, 100L); - assertValues(tunStats, TEST_IFACE, UID_BLUE, 1000L, 100L, 500L, 50L); - assertValues(tunStats, TEST_IFACE, UID_VPN, 300L, 0L, 150L, 0L); - } - - @Test - public void testVpnWithOneUnderlyingIfaceAndOwnTraffic() throws Exception { - // WiFi network is connected and VPN is using WiFi (which has TEST_IFACE). - final UnderlyingNetworkInfo[] underlyingNetworkInfos = - new UnderlyingNetworkInfo[] {createVpnInfo(new String[] {TEST_IFACE})}; - mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos); - - // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption - // overhead per packet): - // 1000 bytes (100 packets) were sent, and 2000 bytes (200 packets) were received by UID_RED - // over VPN. - // 500 bytes (50 packets) were sent, and 1000 bytes (100 packets) were received by UID_BLUE - // over VPN. - // Additionally, the VPN sends 6000 bytes (600 packets) of its own traffic into the tun - // interface (passing that traffic to the VPN endpoint), and receives 5000 bytes (500 - // packets) from it. Including overhead that is 6600/5500 bytes. - // VPN sent 8250 bytes (750 packets), and received 8800 (800 packets) over WiFi. - // Of 8250 bytes sent over WiFi, expect 1000 bytes attributed to UID_RED, 500 bytes - // attributed to UID_BLUE, and 6750 bytes attributed to UID_VPN. - // Of 8800 bytes received over WiFi, expect 2000 bytes attributed to UID_RED, 1000 bytes - // attributed to UID_BLUE, and 5800 bytes attributed to UID_VPN. - final NetworkStats tunStats = - parseDetailedStats(R.raw.xt_qtaguid_vpn_one_underlying_own_traffic); - - assertValues(tunStats, TEST_IFACE, UID_RED, 2000L, 200L, 1000L, 100L); - assertValues(tunStats, TEST_IFACE, UID_BLUE, 1000L, 100L, 500L, 50L); - assertValues(tunStats, TEST_IFACE, UID_VPN, 5800L, 500L, 6750L, 600L); - } - - @Test - public void testVpnWithOneUnderlyingIface_withCompression() throws Exception { - // WiFi network is connected and VPN is using WiFi (which has TEST_IFACE). - final UnderlyingNetworkInfo[] underlyingNetworkInfos = - new UnderlyingNetworkInfo[] {createVpnInfo(new String[] {TEST_IFACE})}; - mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos); - - // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption - // overhead per packet): - // 1000 bytes (100 packets) were sent/received by UID_RED over VPN. - // 3000 bytes (300 packets) were sent/received by UID_BLUE over VPN. - // VPN sent/received 1000 bytes (100 packets) over WiFi. - // Of 1000 bytes over WiFi, expect 250 bytes attributed UID_RED and 750 bytes to UID_BLUE, - // with nothing attributed to UID_VPN for both rx/tx traffic. - final NetworkStats tunStats = - parseDetailedStats(R.raw.xt_qtaguid_vpn_one_underlying_compression); - - assertValues(tunStats, TEST_IFACE, UID_RED, 250L, 25L, 250L, 25L); - assertValues(tunStats, TEST_IFACE, UID_BLUE, 750L, 75L, 750L, 75L); - assertValues(tunStats, TEST_IFACE, UID_VPN, 0L, 0L, 0L, 0L); - } - - @Test - public void testVpnWithTwoUnderlyingIfaces_packetDuplication() throws Exception { - // WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and - // Cell (which has TEST_IFACE2) and has declared both of them in its underlying network set. - // Additionally, VPN is duplicating traffic across both WiFi and Cell. - final UnderlyingNetworkInfo[] underlyingNetworkInfos = - new UnderlyingNetworkInfo[] {createVpnInfo(new String[] {TEST_IFACE, TEST_IFACE2})}; - mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos); - - // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption - // overhead per packet): - // 1000 bytes (100 packets) were sent/received by UID_RED and UID_BLUE over VPN. - // VPN sent/received 4400 bytes (400 packets) over both WiFi and Cell (8800 bytes in total). - // Of 8800 bytes over WiFi/Cell, expect: - // - 500 bytes rx/tx each over WiFi/Cell attributed to both UID_RED and UID_BLUE. - // - 1200 bytes rx/tx each over WiFi/Cell for VPN_UID. - final NetworkStats tunStats = - parseDetailedStats(R.raw.xt_qtaguid_vpn_two_underlying_duplication); - - assertValues(tunStats, TEST_IFACE, UID_RED, 500L, 50L, 500L, 50L); - assertValues(tunStats, TEST_IFACE, UID_BLUE, 500L, 50L, 500L, 50L); - assertValues(tunStats, TEST_IFACE, UID_VPN, 1200L, 100L, 1200L, 100L); - assertValues(tunStats, TEST_IFACE2, UID_RED, 500L, 50L, 500L, 50L); - assertValues(tunStats, TEST_IFACE2, UID_BLUE, 500L, 50L, 500L, 50L); - assertValues(tunStats, TEST_IFACE2, UID_VPN, 1200L, 100L, 1200L, 100L); - } - - @Test - public void testConcurrentVpns() throws Exception { - // Assume two VPNs are connected on two different network interfaces. VPN1 is using - // TEST_IFACE and VPN2 is using TEST_IFACE2. - final UnderlyingNetworkInfo[] underlyingNetworkInfos = new UnderlyingNetworkInfo[] { - createVpnInfo(TUN_IFACE, new String[] {TEST_IFACE}), - createVpnInfo(TUN_IFACE2, new String[] {TEST_IFACE2})}; - mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos); - - // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption - // overhead per packet): - // 1000 bytes (100 packets) were sent, and 2000 bytes (200 packets) were received by UID_RED - // over VPN1. - // 700 bytes (70 packets) were sent, and 3000 bytes (300 packets) were received by UID_RED - // over VPN2. - // 500 bytes (50 packets) were sent, and 1000 bytes (100 packets) were received by UID_BLUE - // over VPN1. - // 250 bytes (25 packets) were sent, and 500 bytes (50 packets) were received by UID_BLUE - // over VPN2. - // VPN1 sent 1650 bytes (150 packets), and received 3300 (300 packets) over TEST_IFACE. - // Of 1650 bytes sent over WiFi, expect 1000 bytes attributed to UID_RED, 500 bytes - // attributed to UID_BLUE, and 150 bytes attributed to UID_VPN. - // Of 3300 bytes received over WiFi, expect 2000 bytes attributed to UID_RED, 1000 bytes - // attributed to UID_BLUE, and 300 bytes attributed to UID_VPN. - // VPN2 sent 1045 bytes (95 packets), and received 3850 (350 packets) over TEST_IFACE2. - // Of 1045 bytes sent over Cell, expect 700 bytes attributed to UID_RED, 250 bytes - // attributed to UID_BLUE, and 95 bytes attributed to UID_VPN. - // Of 3850 bytes received over Cell, expect 3000 bytes attributed to UID_RED, 500 bytes - // attributed to UID_BLUE, and 350 bytes attributed to UID_VPN. - final NetworkStats tunStats = - parseDetailedStats(R.raw.xt_qtaguid_vpn_one_underlying_two_vpn); - - assertValues(tunStats, TEST_IFACE, UID_RED, 2000L, 200L, 1000L, 100L); - assertValues(tunStats, TEST_IFACE, UID_BLUE, 1000L, 100L, 500L, 50L); - assertValues(tunStats, TEST_IFACE2, UID_RED, 3000L, 300L, 700L, 70L); - assertValues(tunStats, TEST_IFACE2, UID_BLUE, 500L, 50L, 250L, 25L); - assertValues(tunStats, TEST_IFACE, UID_VPN, 300L, 0L, 150L, 0L); - assertValues(tunStats, TEST_IFACE2, UID_VPN, 350L, 0L, 95L, 0L); - } - - @Test - public void testVpnWithTwoUnderlyingIfaces_splitTraffic() throws Exception { - // WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and - // Cell (which has TEST_IFACE2) and has declared both of them in its underlying network set. - // Additionally, VPN is arbitrarily splitting traffic across WiFi and Cell. - final UnderlyingNetworkInfo[] underlyingNetworkInfos = - new UnderlyingNetworkInfo[] {createVpnInfo(new String[] {TEST_IFACE, TEST_IFACE2})}; - mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos); - - // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption - // overhead per packet): - // 1000 bytes (100 packets) were sent, and 500 bytes (50 packets) received by UID_RED over - // VPN. - // VPN sent 660 bytes (60 packets) over WiFi and 440 bytes (40 packets) over Cell. - // And, it received 330 bytes (30 packets) over WiFi and 220 bytes (20 packets) over Cell. - // For UID_RED, expect 600 bytes attributed over WiFi and 400 bytes over Cell for sent (tx) - // traffic. For received (rx) traffic, expect 300 bytes over WiFi and 200 bytes over Cell. - // - // For UID_VPN, expect 60 bytes attributed over WiFi and 40 bytes over Cell for tx traffic. - // And, 30 bytes over WiFi and 20 bytes over Cell for rx traffic. - final NetworkStats tunStats = parseDetailedStats(R.raw.xt_qtaguid_vpn_two_underlying_split); - - assertValues(tunStats, TEST_IFACE, UID_RED, 300L, 30L, 600L, 60L); - assertValues(tunStats, TEST_IFACE, UID_VPN, 30L, 0L, 60L, 0L); - assertValues(tunStats, TEST_IFACE2, UID_RED, 200L, 20L, 400L, 40L); - assertValues(tunStats, TEST_IFACE2, UID_VPN, 20L, 0L, 40L, 0L); - } - - @Test - public void testVpnWithTwoUnderlyingIfaces_splitTrafficWithCompression() throws Exception { - // WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and - // Cell (which has TEST_IFACE2) and has declared both of them in its underlying network set. - // Additionally, VPN is arbitrarily splitting compressed traffic across WiFi and Cell. - final UnderlyingNetworkInfo[] underlyingNetworkInfos = - new UnderlyingNetworkInfo[] {createVpnInfo(new String[] {TEST_IFACE, TEST_IFACE2})}; - mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos); - - // create some traffic (assume 10 bytes of MTU for VPN interface: - // 1000 bytes (100 packets) were sent/received by UID_RED over VPN. - // VPN sent/received 600 bytes (60 packets) over WiFi and 200 bytes (20 packets) over Cell. - // For UID_RED, expect 600 bytes attributed over WiFi and 200 bytes over Cell for both - // rx/tx. - // UID_VPN gets nothing attributed to it (avoiding negative stats). - final NetworkStats tunStats = - parseDetailedStats(R.raw.xt_qtaguid_vpn_two_underlying_split_compression); - - assertValues(tunStats, TEST_IFACE, UID_RED, 600L, 60L, 600L, 60L); - assertValues(tunStats, TEST_IFACE, UID_VPN, 0L, 0L, 0L, 0L); - assertValues(tunStats, TEST_IFACE2, UID_RED, 200L, 20L, 200L, 20L); - assertValues(tunStats, TEST_IFACE2, UID_VPN, 0L, 0L, 0L, 0L); - } - - @Test - public void testVpnWithIncorrectUnderlyingIface() throws Exception { - // WiFi and Cell networks are connected and VPN is using Cell (which has TEST_IFACE2), - // but has declared only WiFi (TEST_IFACE) in its underlying network set. - final UnderlyingNetworkInfo[] underlyingNetworkInfos = - new UnderlyingNetworkInfo[] {createVpnInfo(new String[] {TEST_IFACE})}; - mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos); - - // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption - // overhead per packet): - // 1000 bytes (100 packets) were sent/received by UID_RED over VPN. - // VPN sent/received 1100 bytes (100 packets) over Cell. - // Of 1100 bytes over Cell, expect all of it attributed to UID_VPN for both rx/tx traffic. - final NetworkStats tunStats = parseDetailedStats(R.raw.xt_qtaguid_vpn_incorrect_iface); - - assertValues(tunStats, TEST_IFACE, UID_RED, 0L, 0L, 0L, 0L); - assertValues(tunStats, TEST_IFACE, UID_VPN, 0L, 0L, 0L, 0L); - assertValues(tunStats, TEST_IFACE2, UID_RED, 0L, 0L, 0L, 0L); - assertValues(tunStats, TEST_IFACE2, UID_VPN, 1100L, 100L, 1100L, 100L); - } - - @Test - public void testKernelTags() throws Exception { - assertEquals(0, kernelToTag("0x0000000000000000")); - assertEquals(0x32, kernelToTag("0x0000003200000000")); - assertEquals(2147483647, kernelToTag("0x7fffffff00000000")); - assertEquals(0, kernelToTag("0x0000000000000000")); - assertEquals(2147483136, kernelToTag("0x7FFFFE0000000000")); - - assertEquals(0, kernelToTag("0x0")); - assertEquals(0, kernelToTag("0xf00d")); - assertEquals(1, kernelToTag("0x100000000")); - assertEquals(14438007, kernelToTag("0xdc4e7700000000")); - assertEquals(TrafficStats.TAG_SYSTEM_DOWNLOAD, kernelToTag("0xffffff0100000000")); - } - - @Test - public void testNetworkStatsWithSet() throws Exception { - final NetworkStats stats = parseDetailedStats(R.raw.xt_qtaguid_typical); - assertEquals(70, stats.size()); - assertStatsEntry(stats, "rmnet1", 10021, SET_DEFAULT, 0x30100000, 219110L, 578L, 227423L, - 676L); - assertStatsEntry(stats, "rmnet1", 10021, SET_FOREGROUND, 0x30100000, 742L, 3L, 1265L, 3L); - } - - @Test - public void testNetworkStatsSingle() throws Exception { - stageFile(R.raw.xt_qtaguid_iface_typical, file("net/xt_qtaguid/iface_stat_all")); - - final NetworkStats stats = mFactory.readNetworkStatsSummaryDev(); - assertEquals(6, stats.size()); - assertStatsEntry(stats, "rmnet0", UID_ALL, SET_ALL, TAG_NONE, 2112L, 24L, 700L, 10L); - assertStatsEntry(stats, "test1", UID_ALL, SET_ALL, TAG_NONE, 6L, 8L, 10L, 12L); - assertStatsEntry(stats, "test2", UID_ALL, SET_ALL, TAG_NONE, 1L, 2L, 3L, 4L); - } - - @Test - public void testNetworkStatsXt() throws Exception { - stageFile(R.raw.xt_qtaguid_iface_fmt_typical, file("net/xt_qtaguid/iface_stat_fmt")); - - final NetworkStats stats = mFactory.readNetworkStatsSummaryXt(); - assertEquals(3, stats.size()); - assertStatsEntry(stats, "rmnet0", UID_ALL, SET_ALL, TAG_NONE, 6824L, 16L, 5692L, 10L); - assertStatsEntry(stats, "rmnet1", UID_ALL, SET_ALL, TAG_NONE, 11153922L, 8051L, 190226L, - 2468L); - assertStatsEntry(stats, "rmnet2", UID_ALL, SET_ALL, TAG_NONE, 4968L, 35L, 3081L, 39L); - } - - @Test - public void testDoubleClatAccountingSimple() throws Exception { - mFactory.noteStackedIface("v4-wlan0", "wlan0"); - - // xt_qtaguid_with_clat_simple is a synthetic file that simulates - // - 213 received 464xlat packets of size 200 bytes - // - 41 sent 464xlat packets of size 100 bytes - // - no other traffic on base interface for root uid. - NetworkStats stats = parseDetailedStats(R.raw.xt_qtaguid_with_clat_simple); - assertEquals(3, stats.size()); - - assertStatsEntry(stats, "v4-wlan0", 10060, SET_DEFAULT, 0x0, 46860L, 4920L); - assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, 0L, 0L); - } - - @Test - public void testDoubleClatAccounting() throws Exception { - mFactory.noteStackedIface("v4-wlan0", "wlan0"); - - NetworkStats stats = parseDetailedStats(R.raw.xt_qtaguid_with_clat); - assertEquals(42, stats.size()); - - assertStatsEntry(stats, "v4-wlan0", 0, SET_DEFAULT, 0x0, 356L, 276L); - assertStatsEntry(stats, "v4-wlan0", 1000, SET_DEFAULT, 0x0, 30812L, 2310L); - assertStatsEntry(stats, "v4-wlan0", 10102, SET_DEFAULT, 0x0, 10022L, 3330L); - assertStatsEntry(stats, "v4-wlan0", 10060, SET_DEFAULT, 0x0, 9532772L, 254112L); - assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, 0L, 0L); - assertStatsEntry(stats, "wlan0", 1000, SET_DEFAULT, 0x0, 6126L, 2013L); - assertStatsEntry(stats, "wlan0", 10013, SET_DEFAULT, 0x0, 0L, 144L); - assertStatsEntry(stats, "wlan0", 10018, SET_DEFAULT, 0x0, 5980263L, 167667L); - assertStatsEntry(stats, "wlan0", 10060, SET_DEFAULT, 0x0, 134356L, 8705L); - assertStatsEntry(stats, "wlan0", 10079, SET_DEFAULT, 0x0, 10926L, 1507L); - assertStatsEntry(stats, "wlan0", 10102, SET_DEFAULT, 0x0, 25038L, 8245L); - assertStatsEntry(stats, "wlan0", 10103, SET_DEFAULT, 0x0, 0L, 192L); - assertStatsEntry(stats, "dummy0", 0, SET_DEFAULT, 0x0, 0L, 168L); - assertStatsEntry(stats, "lo", 0, SET_DEFAULT, 0x0, 1288L, 1288L); - - assertNoStatsEntry(stats, "wlan0", 1029, SET_DEFAULT, 0x0); - } - - @Test - public void testDoubleClatAccounting100MBDownload() throws Exception { - // Downloading 100mb from an ipv4 only destination in a foreground activity - - long appRxBytesBefore = 328684029L; - long appRxBytesAfter = 439237478L; - assertEquals("App traffic should be ~100MB", 110553449, appRxBytesAfter - appRxBytesBefore); - - long rootRxBytes = 330187296L; - - mFactory.noteStackedIface("v4-wlan0", "wlan0"); - NetworkStats stats; - - // Stats snapshot before the download - stats = parseDetailedStats(R.raw.xt_qtaguid_with_clat_100mb_download_before); - assertStatsEntry(stats, "v4-wlan0", 10106, SET_FOREGROUND, 0x0, appRxBytesBefore, 5199872L); - assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, rootRxBytes, 0L); - - // Stats snapshot after the download - stats = parseDetailedStats(R.raw.xt_qtaguid_with_clat_100mb_download_after); - assertStatsEntry(stats, "v4-wlan0", 10106, SET_FOREGROUND, 0x0, appRxBytesAfter, 7867488L); - assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, rootRxBytes, 0L); - } - - /** - * Copy a {@link Resources#openRawResource(int)} into {@link File} for - * testing purposes. - */ - private void stageFile(int rawId, File file) throws Exception { - new File(file.getParent()).mkdirs(); - InputStream in = null; - OutputStream out = null; - try { - in = InstrumentationRegistry.getContext().getResources().openRawResource(rawId); - out = new FileOutputStream(file); - Streams.copy(in, out); - } finally { - IoUtils.closeQuietly(in); - IoUtils.closeQuietly(out); - } - } - - private void stageLong(long value, File file) throws Exception { - new File(file.getParent()).mkdirs(); - FileWriter out = null; - try { - out = new FileWriter(file); - out.write(Long.toString(value)); - } finally { - IoUtils.closeQuietly(out); - } - } - - private File file(String path) throws Exception { - return new File(mTestProc, path); - } - - private NetworkStats parseDetailedStats(int resourceId) throws Exception { - stageFile(resourceId, file("net/xt_qtaguid/stats")); - return mFactory.readNetworkStatsDetail(); - } - - private static void assertStatsEntry(NetworkStats stats, String iface, int uid, int set, - int tag, long rxBytes, long txBytes) { - final int i = stats.findIndex(iface, uid, set, tag, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO); - if (i < 0) { - fail(String.format("no NetworkStats for (iface: %s, uid: %d, set: %d, tag: %d)", - iface, uid, set, tag)); - } - final NetworkStats.Entry entry = stats.getValues(i, null); - assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); - assertEquals("unexpected txBytes", txBytes, entry.txBytes); - } - - private static void assertNoStatsEntry(NetworkStats stats, String iface, int uid, int set, - int tag) { - final int i = stats.findIndex(iface, uid, set, tag, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO); - if (i >= 0) { - fail("unexpected NetworkStats entry at " + i); - } - } - - private static void assertStatsEntry(NetworkStats stats, String iface, int uid, int set, - int tag, long rxBytes, long rxPackets, long txBytes, long txPackets) { - assertStatsEntry(stats, iface, uid, set, tag, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, - rxBytes, rxPackets, txBytes, txPackets); - } - - private static void assertStatsEntry(NetworkStats stats, String iface, int uid, int set, - int tag, int metered, int roaming, int defaultNetwork, long rxBytes, long rxPackets, - long txBytes, long txPackets) { - final int i = stats.findIndex(iface, uid, set, tag, metered, roaming, defaultNetwork); - - if (i < 0) { - fail(String.format("no NetworkStats for (iface: %s, uid: %d, set: %d, tag: %d, metered:" - + " %d, roaming: %d, defaultNetwork: %d)", - iface, uid, set, tag, metered, roaming, defaultNetwork)); - } - final NetworkStats.Entry entry = stats.getValues(i, null); - assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); - assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets); - assertEquals("unexpected txBytes", txBytes, entry.txBytes); - assertEquals("unexpected txPackets", txPackets, entry.txPackets); - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java deleted file mode 100644 index 9fa1c50423d92..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java +++ /dev/null @@ -1,447 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.net; - -import static android.net.ConnectivityManager.TYPE_MOBILE; -import static android.net.NetworkIdentity.OEM_NONE; -import static android.net.NetworkStats.DEFAULT_NETWORK_NO; -import static android.net.NetworkStats.DEFAULT_NETWORK_YES; -import static android.net.NetworkStats.METERED_NO; -import static android.net.NetworkStats.ROAMING_NO; -import static android.net.NetworkStats.SET_DEFAULT; -import static android.net.NetworkStats.TAG_NONE; -import static android.net.NetworkTemplate.buildTemplateMobileAll; -import static android.net.NetworkTemplate.buildTemplateWifiWildcard; -import static android.net.TrafficStats.MB_IN_BYTES; -import static android.text.format.DateUtils.MINUTE_IN_MILLIS; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyInt; - -import android.app.usage.NetworkStatsManager; -import android.net.DataUsageRequest; -import android.net.NetworkIdentity; -import android.net.NetworkStats; -import android.net.NetworkTemplate; -import android.os.ConditionVariable; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.Looper; -import android.os.Messenger; -import android.os.Process; -import android.os.UserHandle; -import android.telephony.TelephonyManager; -import android.util.ArrayMap; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.server.net.NetworkStatsServiceTest.LatchedHandler; -import com.android.testutils.HandlerUtils; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; - -import java.util.Objects; - -/** - * Tests for {@link NetworkStatsObservers}. - */ -@RunWith(AndroidJUnit4.class) -@SmallTest -public class NetworkStatsObserversTest { - private static final String TEST_IFACE = "test0"; - private static final String TEST_IFACE2 = "test1"; - private static final long TEST_START = 1194220800000L; - - private static final String IMSI_1 = "310004"; - private static final String IMSI_2 = "310260"; - private static final String TEST_SSID = "AndroidAP"; - - private static NetworkTemplate sTemplateWifi = buildTemplateWifiWildcard(); - private static NetworkTemplate sTemplateImsi1 = buildTemplateMobileAll(IMSI_1); - private static NetworkTemplate sTemplateImsi2 = buildTemplateMobileAll(IMSI_2); - - private static final int UID_RED = UserHandle.PER_USER_RANGE + 1; - private static final int UID_BLUE = UserHandle.PER_USER_RANGE + 2; - private static final int UID_GREEN = UserHandle.PER_USER_RANGE + 3; - private static final int UID_ANOTHER_USER = 2 * UserHandle.PER_USER_RANGE + 4; - - private static final long WAIT_TIMEOUT_MS = 500; - private static final long THRESHOLD_BYTES = 2 * MB_IN_BYTES; - private static final long BASE_BYTES = 7 * MB_IN_BYTES; - private static final int INVALID_TYPE = -1; - - private long mElapsedRealtime; - - private HandlerThread mObserverHandlerThread; - private Handler mObserverNoopHandler; - - private LatchedHandler mHandler; - - private NetworkStatsObservers mStatsObservers; - private Messenger mMessenger; - private ArrayMap mActiveIfaces; - private ArrayMap mActiveUidIfaces; - - @Mock private IBinder mockBinder; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - mObserverHandlerThread = new HandlerThread("HandlerThread"); - mObserverHandlerThread.start(); - final Looper observerLooper = mObserverHandlerThread.getLooper(); - mStatsObservers = new NetworkStatsObservers() { - @Override - protected Looper getHandlerLooperLocked() { - return observerLooper; - } - }; - - mHandler = new LatchedHandler(Looper.getMainLooper(), new ConditionVariable()); - mMessenger = new Messenger(mHandler); - - mActiveIfaces = new ArrayMap<>(); - mActiveUidIfaces = new ArrayMap<>(); - } - - @Test - public void testRegister_thresholdTooLow_setsDefaultThreshold() throws Exception { - long thresholdTooLowBytes = 1L; - DataUsageRequest inputRequest = new DataUsageRequest( - DataUsageRequest.REQUEST_ID_UNSET, sTemplateWifi, thresholdTooLowBytes); - - DataUsageRequest request = mStatsObservers.register(inputRequest, mMessenger, mockBinder, - Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE); - assertTrue(request.requestId > 0); - assertTrue(Objects.equals(sTemplateWifi, request.template)); - assertEquals(THRESHOLD_BYTES, request.thresholdInBytes); - } - - @Test - public void testRegister_highThreshold_accepted() throws Exception { - long highThresholdBytes = 2 * THRESHOLD_BYTES; - DataUsageRequest inputRequest = new DataUsageRequest( - DataUsageRequest.REQUEST_ID_UNSET, sTemplateWifi, highThresholdBytes); - - DataUsageRequest request = mStatsObservers.register(inputRequest, mMessenger, mockBinder, - Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE); - assertTrue(request.requestId > 0); - assertTrue(Objects.equals(sTemplateWifi, request.template)); - assertEquals(highThresholdBytes, request.thresholdInBytes); - } - - @Test - public void testRegister_twoRequests_twoIds() throws Exception { - DataUsageRequest inputRequest = new DataUsageRequest( - DataUsageRequest.REQUEST_ID_UNSET, sTemplateWifi, THRESHOLD_BYTES); - - DataUsageRequest request1 = mStatsObservers.register(inputRequest, mMessenger, mockBinder, - Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE); - assertTrue(request1.requestId > 0); - assertTrue(Objects.equals(sTemplateWifi, request1.template)); - assertEquals(THRESHOLD_BYTES, request1.thresholdInBytes); - - DataUsageRequest request2 = mStatsObservers.register(inputRequest, mMessenger, mockBinder, - Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE); - assertTrue(request2.requestId > request1.requestId); - assertTrue(Objects.equals(sTemplateWifi, request2.template)); - assertEquals(THRESHOLD_BYTES, request2.thresholdInBytes); - } - - @Test - public void testUnregister_unknownRequest_noop() throws Exception { - DataUsageRequest unknownRequest = new DataUsageRequest( - 123456 /* id */, sTemplateWifi, THRESHOLD_BYTES); - - mStatsObservers.unregister(unknownRequest, UID_RED); - } - - @Test - public void testUnregister_knownRequest_releasesCaller() throws Exception { - DataUsageRequest inputRequest = new DataUsageRequest( - DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES); - - DataUsageRequest request = mStatsObservers.register(inputRequest, mMessenger, mockBinder, - Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE); - assertTrue(request.requestId > 0); - assertTrue(Objects.equals(sTemplateImsi1, request.template)); - assertEquals(THRESHOLD_BYTES, request.thresholdInBytes); - Mockito.verify(mockBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); - - mStatsObservers.unregister(request, Process.SYSTEM_UID); - waitForObserverToIdle(); - - Mockito.verify(mockBinder).unlinkToDeath(any(IBinder.DeathRecipient.class), anyInt()); - } - - @Test - public void testUnregister_knownRequest_invalidUid_doesNotUnregister() throws Exception { - DataUsageRequest inputRequest = new DataUsageRequest( - DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES); - - DataUsageRequest request = mStatsObservers.register(inputRequest, mMessenger, mockBinder, - UID_RED, NetworkStatsAccess.Level.DEVICE); - assertTrue(request.requestId > 0); - assertTrue(Objects.equals(sTemplateImsi1, request.template)); - assertEquals(THRESHOLD_BYTES, request.thresholdInBytes); - Mockito.verify(mockBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); - - mStatsObservers.unregister(request, UID_BLUE); - waitForObserverToIdle(); - - Mockito.verifyZeroInteractions(mockBinder); - } - - private NetworkIdentitySet makeTestIdentSet() { - NetworkIdentitySet identSet = new NetworkIdentitySet(); - identSet.add(new NetworkIdentity( - TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, - IMSI_1, null /* networkId */, false /* roaming */, true /* metered */, - true /* defaultNetwork */, OEM_NONE)); - return identSet; - } - - @Test - public void testUpdateStats_initialSample_doesNotNotify() throws Exception { - DataUsageRequest inputRequest = new DataUsageRequest( - DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES); - - DataUsageRequest request = mStatsObservers.register(inputRequest, mMessenger, mockBinder, - Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE); - assertTrue(request.requestId > 0); - assertTrue(Objects.equals(sTemplateImsi1, request.template)); - assertEquals(THRESHOLD_BYTES, request.thresholdInBytes); - - NetworkIdentitySet identSet = makeTestIdentSet(); - mActiveIfaces.put(TEST_IFACE, identSet); - - // Baseline - NetworkStats xtSnapshot = new NetworkStats(TEST_START, 1 /* initialSize */) - .insertEntry(TEST_IFACE, BASE_BYTES, 8L, BASE_BYTES, 16L); - NetworkStats uidSnapshot = null; - - mStatsObservers.updateStats( - xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START); - waitForObserverToIdle(); - } - - @Test - public void testUpdateStats_belowThreshold_doesNotNotify() throws Exception { - DataUsageRequest inputRequest = new DataUsageRequest( - DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES); - - DataUsageRequest request = mStatsObservers.register(inputRequest, mMessenger, mockBinder, - Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE); - assertTrue(request.requestId > 0); - assertTrue(Objects.equals(sTemplateImsi1, request.template)); - assertEquals(THRESHOLD_BYTES, request.thresholdInBytes); - - NetworkIdentitySet identSet = makeTestIdentSet(); - mActiveIfaces.put(TEST_IFACE, identSet); - - // Baseline - NetworkStats xtSnapshot = new NetworkStats(TEST_START, 1 /* initialSize */) - .insertEntry(TEST_IFACE, BASE_BYTES, 8L, BASE_BYTES, 16L); - NetworkStats uidSnapshot = null; - mStatsObservers.updateStats( - xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START); - - // Delta - xtSnapshot = new NetworkStats(TEST_START, 1 /* initialSize */) - .insertEntry(TEST_IFACE, BASE_BYTES + 1024L, 10L, BASE_BYTES + 2048L, 20L); - mStatsObservers.updateStats( - xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START); - waitForObserverToIdle(); - } - - - @Test - public void testUpdateStats_deviceAccess_notifies() throws Exception { - DataUsageRequest inputRequest = new DataUsageRequest( - DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES); - - DataUsageRequest request = mStatsObservers.register(inputRequest, mMessenger, mockBinder, - Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE); - assertTrue(request.requestId > 0); - assertTrue(Objects.equals(sTemplateImsi1, request.template)); - assertEquals(THRESHOLD_BYTES, request.thresholdInBytes); - - NetworkIdentitySet identSet = makeTestIdentSet(); - mActiveIfaces.put(TEST_IFACE, identSet); - - // Baseline - NetworkStats xtSnapshot = new NetworkStats(TEST_START, 1 /* initialSize */) - .insertEntry(TEST_IFACE, BASE_BYTES, 8L, BASE_BYTES, 16L); - NetworkStats uidSnapshot = null; - mStatsObservers.updateStats( - xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START); - - // Delta - xtSnapshot = new NetworkStats(TEST_START + MINUTE_IN_MILLIS, 1 /* initialSize */) - .insertEntry(TEST_IFACE, BASE_BYTES + THRESHOLD_BYTES, 12L, - BASE_BYTES + THRESHOLD_BYTES, 22L); - mStatsObservers.updateStats( - xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START); - waitForObserverToIdle(); - assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, mHandler.lastMessageType); - } - - @Test - public void testUpdateStats_defaultAccess_notifiesSameUid() throws Exception { - DataUsageRequest inputRequest = new DataUsageRequest( - DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES); - - DataUsageRequest request = mStatsObservers.register(inputRequest, mMessenger, mockBinder, - UID_RED, NetworkStatsAccess.Level.DEFAULT); - assertTrue(request.requestId > 0); - assertTrue(Objects.equals(sTemplateImsi1, request.template)); - assertEquals(THRESHOLD_BYTES, request.thresholdInBytes); - - NetworkIdentitySet identSet = makeTestIdentSet(); - mActiveUidIfaces.put(TEST_IFACE, identSet); - - // Baseline - NetworkStats xtSnapshot = null; - NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L); - mStatsObservers.updateStats( - xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START); - - // Delta - uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, BASE_BYTES + THRESHOLD_BYTES, 2L, - BASE_BYTES + THRESHOLD_BYTES, 2L, 0L); - mStatsObservers.updateStats( - xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START); - waitForObserverToIdle(); - assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, mHandler.lastMessageType); - } - - @Test - public void testUpdateStats_defaultAccess_usageOtherUid_doesNotNotify() throws Exception { - DataUsageRequest inputRequest = new DataUsageRequest( - DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES); - - DataUsageRequest request = mStatsObservers.register(inputRequest, mMessenger, mockBinder, - UID_BLUE, NetworkStatsAccess.Level.DEFAULT); - assertTrue(request.requestId > 0); - assertTrue(Objects.equals(sTemplateImsi1, request.template)); - assertEquals(THRESHOLD_BYTES, request.thresholdInBytes); - - NetworkIdentitySet identSet = makeTestIdentSet(); - mActiveUidIfaces.put(TEST_IFACE, identSet); - - // Baseline - NetworkStats xtSnapshot = null; - NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L); - mStatsObservers.updateStats( - xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START); - - // Delta - uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, BASE_BYTES + THRESHOLD_BYTES, 2L, - BASE_BYTES + THRESHOLD_BYTES, 2L, 0L); - mStatsObservers.updateStats( - xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START); - waitForObserverToIdle(); - } - - @Test - public void testUpdateStats_userAccess_usageSameUser_notifies() throws Exception { - DataUsageRequest inputRequest = new DataUsageRequest( - DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES); - - DataUsageRequest request = mStatsObservers.register(inputRequest, mMessenger, mockBinder, - UID_BLUE, NetworkStatsAccess.Level.USER); - assertTrue(request.requestId > 0); - assertTrue(Objects.equals(sTemplateImsi1, request.template)); - assertEquals(THRESHOLD_BYTES, request.thresholdInBytes); - - NetworkIdentitySet identSet = makeTestIdentSet(); - mActiveUidIfaces.put(TEST_IFACE, identSet); - - // Baseline - NetworkStats xtSnapshot = null; - NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L); - mStatsObservers.updateStats( - xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START); - - // Delta - uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, BASE_BYTES + THRESHOLD_BYTES, 2L, - BASE_BYTES + THRESHOLD_BYTES, 2L, 0L); - mStatsObservers.updateStats( - xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START); - waitForObserverToIdle(); - assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, mHandler.lastMessageType); - } - - @Test - public void testUpdateStats_userAccess_usageAnotherUser_doesNotNotify() throws Exception { - DataUsageRequest inputRequest = new DataUsageRequest( - DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES); - - DataUsageRequest request = mStatsObservers.register(inputRequest, mMessenger, mockBinder, - UID_RED, NetworkStatsAccess.Level.USER); - assertTrue(request.requestId > 0); - assertTrue(Objects.equals(sTemplateImsi1, request.template)); - assertEquals(THRESHOLD_BYTES, request.thresholdInBytes); - - NetworkIdentitySet identSet = makeTestIdentSet(); - mActiveUidIfaces.put(TEST_IFACE, identSet); - - // Baseline - NetworkStats xtSnapshot = null; - NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */) - .insertEntry(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_YES, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L); - mStatsObservers.updateStats( - xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START); - - // Delta - uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */) - .insertEntry(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, METERED_NO, - ROAMING_NO, DEFAULT_NETWORK_NO, BASE_BYTES + THRESHOLD_BYTES, 2L, - BASE_BYTES + THRESHOLD_BYTES, 2L, 0L); - mStatsObservers.updateStats( - xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START); - waitForObserverToIdle(); - } - - private void waitForObserverToIdle() { - HandlerUtils.waitForIdle(mObserverHandlerThread, WAIT_TIMEOUT_MS); - HandlerUtils.waitForIdle(mHandler, WAIT_TIMEOUT_MS); - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java deleted file mode 100644 index c32c1d212494c..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java +++ /dev/null @@ -1,1812 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.net; - -import static android.content.Intent.ACTION_UID_REMOVED; -import static android.content.Intent.EXTRA_UID; -import static android.net.ConnectivityManager.TYPE_MOBILE; -import static android.net.ConnectivityManager.TYPE_WIFI; -import static android.net.NetworkIdentity.OEM_PAID; -import static android.net.NetworkIdentity.OEM_PRIVATE; -import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; -import static android.net.NetworkStats.DEFAULT_NETWORK_NO; -import static android.net.NetworkStats.DEFAULT_NETWORK_YES; -import static android.net.NetworkStats.IFACE_ALL; -import static android.net.NetworkStats.INTERFACES_ALL; -import static android.net.NetworkStats.METERED_ALL; -import static android.net.NetworkStats.METERED_NO; -import static android.net.NetworkStats.METERED_YES; -import static android.net.NetworkStats.ROAMING_ALL; -import static android.net.NetworkStats.ROAMING_NO; -import static android.net.NetworkStats.ROAMING_YES; -import static android.net.NetworkStats.SET_ALL; -import static android.net.NetworkStats.SET_DEFAULT; -import static android.net.NetworkStats.SET_FOREGROUND; -import static android.net.NetworkStats.STATS_PER_UID; -import static android.net.NetworkStats.TAG_ALL; -import static android.net.NetworkStats.TAG_NONE; -import static android.net.NetworkStats.UID_ALL; -import static android.net.NetworkStatsHistory.FIELD_ALL; -import static android.net.NetworkTemplate.MATCH_MOBILE_WILDCARD; -import static android.net.NetworkTemplate.NETWORK_TYPE_ALL; -import static android.net.NetworkTemplate.OEM_MANAGED_NO; -import static android.net.NetworkTemplate.OEM_MANAGED_YES; -import static android.net.NetworkTemplate.SUBSCRIBER_ID_MATCH_RULE_EXACT; -import static android.net.NetworkTemplate.buildTemplateMobileAll; -import static android.net.NetworkTemplate.buildTemplateMobileWithRatType; -import static android.net.NetworkTemplate.buildTemplateWifi; -import static android.net.NetworkTemplate.buildTemplateWifiWildcard; -import static android.net.TrafficStats.MB_IN_BYTES; -import static android.net.TrafficStats.UID_REMOVED; -import static android.net.TrafficStats.UID_TETHERING; -import static android.text.format.DateUtils.DAY_IN_MILLIS; -import static android.text.format.DateUtils.HOUR_IN_MILLIS; -import static android.text.format.DateUtils.MINUTE_IN_MILLIS; -import static android.text.format.DateUtils.WEEK_IN_MILLIS; - -import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_POLL; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.annotation.NonNull; -import android.app.AlarmManager; -import android.app.usage.NetworkStatsManager; -import android.content.Context; -import android.content.Intent; -import android.database.ContentObserver; -import android.net.DataUsageRequest; -import android.net.INetworkManagementEventObserver; -import android.net.INetworkStatsSession; -import android.net.LinkProperties; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.NetworkStateSnapshot; -import android.net.NetworkStats; -import android.net.NetworkStatsHistory; -import android.net.NetworkTemplate; -import android.net.TelephonyNetworkSpecifier; -import android.net.UnderlyingNetworkInfo; -import android.net.netstats.provider.INetworkStatsProviderCallback; -import android.os.ConditionVariable; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.INetworkManagementService; -import android.os.Looper; -import android.os.Message; -import android.os.Messenger; -import android.os.PowerManager; -import android.os.SimpleClock; -import android.provider.Settings; -import android.telephony.TelephonyManager; - -import androidx.test.InstrumentationRegistry; -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.internal.util.ArrayUtils; -import com.android.internal.util.test.BroadcastInterceptingContext; -import com.android.server.net.NetworkStatsService.NetworkStatsSettings; -import com.android.server.net.NetworkStatsService.NetworkStatsSettings.Config; -import com.android.testutils.HandlerUtils; -import com.android.testutils.TestableNetworkStatsProviderBinder; - -import libcore.io.IoUtils; - -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.io.File; -import java.time.Clock; -import java.time.ZoneOffset; -import java.util.Objects; -import java.util.concurrent.Executor; - -/** - * Tests for {@link NetworkStatsService}. - * - * TODO: This test used to be really brittle because it used Easymock - it uses Mockito now, but - * still uses the Easymock structure, which could be simplified. - */ -@RunWith(AndroidJUnit4.class) -@SmallTest -public class NetworkStatsServiceTest extends NetworkStatsBaseTest { - private static final String TAG = "NetworkStatsServiceTest"; - - private static final long TEST_START = 1194220800000L; - - private static final String IMSI_1 = "310004"; - private static final String IMSI_2 = "310260"; - private static final String TEST_SSID = "AndroidAP"; - - private static NetworkTemplate sTemplateWifi = buildTemplateWifi(TEST_SSID); - private static NetworkTemplate sTemplateCarrierWifi1 = - buildTemplateWifi(NetworkTemplate.WIFI_NETWORKID_ALL, IMSI_1); - private static NetworkTemplate sTemplateImsi1 = buildTemplateMobileAll(IMSI_1); - private static NetworkTemplate sTemplateImsi2 = buildTemplateMobileAll(IMSI_2); - - private static final Network WIFI_NETWORK = new Network(100); - private static final Network MOBILE_NETWORK = new Network(101); - private static final Network VPN_NETWORK = new Network(102); - - private static final Network[] NETWORKS_WIFI = new Network[]{ WIFI_NETWORK }; - private static final Network[] NETWORKS_MOBILE = new Network[]{ MOBILE_NETWORK }; - - private static final long WAIT_TIMEOUT = 2 * 1000; // 2 secs - private static final int INVALID_TYPE = -1; - - private long mElapsedRealtime; - - private File mStatsDir; - private MockContext mServiceContext; - private @Mock TelephonyManager mTelephonyManager; - private @Mock INetworkManagementService mNetManager; - private @Mock NetworkStatsFactory mStatsFactory; - private @Mock NetworkStatsSettings mSettings; - private @Mock IBinder mBinder; - private @Mock AlarmManager mAlarmManager; - @Mock - private NetworkStatsSubscriptionsMonitor mNetworkStatsSubscriptionsMonitor; - private HandlerThread mHandlerThread; - - private NetworkStatsService mService; - private INetworkStatsSession mSession; - private INetworkManagementEventObserver mNetworkObserver; - private ContentObserver mContentObserver; - private Handler mHandler; - - private class MockContext extends BroadcastInterceptingContext { - private final Context mBaseContext; - - MockContext(Context base) { - super(base); - mBaseContext = base; - } - - @Override - public Object getSystemService(String name) { - if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager; - return mBaseContext.getSystemService(name); - } - } - - private final Clock mClock = new SimpleClock(ZoneOffset.UTC) { - @Override - public long millis() { - return currentTimeMillis(); - } - }; - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - final Context context = InstrumentationRegistry.getContext(); - mServiceContext = new MockContext(context); - mStatsDir = context.getFilesDir(); - if (mStatsDir.exists()) { - IoUtils.deleteContents(mStatsDir); - } - - PowerManager powerManager = (PowerManager) mServiceContext.getSystemService( - Context.POWER_SERVICE); - PowerManager.WakeLock wakeLock = - powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); - - mHandlerThread = new HandlerThread("HandlerThread"); - final NetworkStatsService.Dependencies deps = makeDependencies(); - mService = new NetworkStatsService(mServiceContext, mNetManager, mAlarmManager, wakeLock, - mClock, mSettings, mStatsFactory, new NetworkStatsObservers(), mStatsDir, - getBaseDir(mStatsDir), deps); - - mElapsedRealtime = 0L; - - expectDefaultSettings(); - expectNetworkStatsUidDetail(buildEmptyStats()); - expectSystemReady(); - mService.systemReady(); - // Verify that system ready fetches realtime stats - verify(mStatsFactory).readNetworkStatsDetail(UID_ALL, INTERFACES_ALL, TAG_ALL); - // Wait for posting onChange() event to handler thread and verify that when system ready, - // start monitoring data usage per RAT type because the settings value is mock as false - // by default in expectSettings(). - waitForIdle(); - verify(mNetworkStatsSubscriptionsMonitor).start(); - reset(mNetworkStatsSubscriptionsMonitor); - - doReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS).when(mTelephonyManager) - .checkCarrierPrivilegesForPackageAnyPhone(anyString()); - - mSession = mService.openSession(); - assertNotNull("openSession() failed", mSession); - - // catch INetworkManagementEventObserver during systemReady() - ArgumentCaptor networkObserver = - ArgumentCaptor.forClass(INetworkManagementEventObserver.class); - verify(mNetManager).registerObserver(networkObserver.capture()); - mNetworkObserver = networkObserver.getValue(); - } - - @NonNull - private NetworkStatsService.Dependencies makeDependencies() { - return new NetworkStatsService.Dependencies() { - @Override - public HandlerThread makeHandlerThread() { - return mHandlerThread; - } - - @Override - public NetworkStatsSubscriptionsMonitor makeSubscriptionsMonitor( - @NonNull Context context, @NonNull Looper looper, @NonNull Executor executor, - @NonNull NetworkStatsService service) { - - return mNetworkStatsSubscriptionsMonitor; - } - - @Override - public ContentObserver makeContentObserver(Handler handler, - NetworkStatsSettings settings, NetworkStatsSubscriptionsMonitor monitor) { - mHandler = handler; - return mContentObserver = super.makeContentObserver(handler, settings, monitor); - } - - }; - } - - @After - public void tearDown() throws Exception { - IoUtils.deleteContents(mStatsDir); - - mServiceContext = null; - mStatsDir = null; - - mNetManager = null; - mSettings = null; - - mSession.close(); - mService = null; - - mHandlerThread.quitSafely(); - } - - private void initWifiStats(NetworkStateSnapshot snapshot) throws Exception { - // pretend that wifi network comes online; service should ask about full - // network state, and poll any existing interfaces before updating. - expectDefaultSettings(); - NetworkStateSnapshot[] states = new NetworkStateSnapshot[] {snapshot}; - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(buildEmptyStats()); - - mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states), - new UnderlyingNetworkInfo[0]); - } - - private void incrementWifiStats(long durationMillis, String iface, - long rxb, long rxp, long txb, long txp) throws Exception { - incrementCurrentTime(durationMillis); - expectDefaultSettings(); - expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) - .insertEntry(iface, rxb, rxp, txb, txp)); - expectNetworkStatsUidDetail(buildEmptyStats()); - forcePollAndWaitForIdle(); - } - - @Test - public void testNetworkStatsCarrierWifi() throws Exception { - initWifiStats(buildWifiState(true, TEST_IFACE, IMSI_1)); - // verify service has empty history for carrier merged wifi and non-carrier wifi - assertNetworkTotal(sTemplateCarrierWifi1, 0L, 0L, 0L, 0L, 0); - assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); - - // modify some number on wifi, and trigger poll event - incrementWifiStats(HOUR_IN_MILLIS, TEST_IFACE, 1024L, 1L, 2048L, 2L); - - // verify service recorded history - assertNetworkTotal(sTemplateCarrierWifi1, 1024L, 1L, 2048L, 2L, 0); - - // verify service recorded history for wifi with SSID filter - assertNetworkTotal(sTemplateWifi, 1024L, 1L, 2048L, 2L, 0); - - - // and bump forward again, with counters going higher. this is - // important, since polling should correctly subtract last snapshot. - incrementWifiStats(DAY_IN_MILLIS, TEST_IFACE, 4096L, 4L, 8192L, 8L); - - // verify service recorded history - assertNetworkTotal(sTemplateCarrierWifi1, 4096L, 4L, 8192L, 8L, 0); - // verify service recorded history for wifi with SSID filter - assertNetworkTotal(sTemplateWifi, 4096L, 4L, 8192L, 8L, 0); - } - - @Test - public void testNetworkStatsNonCarrierWifi() throws Exception { - initWifiStats(buildWifiState()); - - // verify service has empty history for wifi - assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); - // verify service has empty history for carrier merged wifi - assertNetworkTotal(sTemplateCarrierWifi1, 0L, 0L, 0L, 0L, 0); - - // modify some number on wifi, and trigger poll event - incrementWifiStats(HOUR_IN_MILLIS, TEST_IFACE, 1024L, 1L, 2048L, 2L); - - // verify service recorded history - assertNetworkTotal(sTemplateWifi, 1024L, 1L, 2048L, 2L, 0); - // verify service has empty history for carrier wifi since current network is non carrier - // wifi - assertNetworkTotal(sTemplateCarrierWifi1, 0L, 0L, 0L, 0L, 0); - - // and bump forward again, with counters going higher. this is - // important, since polling should correctly subtract last snapshot. - incrementWifiStats(DAY_IN_MILLIS, TEST_IFACE, 4096L, 4L, 8192L, 8L); - - // verify service recorded history - assertNetworkTotal(sTemplateWifi, 4096L, 4L, 8192L, 8L, 0); - // verify service has empty history for carrier wifi since current network is non carrier - // wifi - assertNetworkTotal(sTemplateCarrierWifi1, 0L, 0L, 0L, 0L, 0); - } - - @Test - public void testStatsRebootPersist() throws Exception { - assertStatsFilesExist(false); - - // pretend that wifi network comes online; service should ask about full - // network state, and poll any existing interfaces before updating. - expectDefaultSettings(); - NetworkStateSnapshot[] states = new NetworkStateSnapshot[] {buildWifiState()}; - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(buildEmptyStats()); - - mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states), - new UnderlyingNetworkInfo[0]); - - // verify service has empty history for wifi - assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); - - - // modify some number on wifi, and trigger poll event - incrementCurrentTime(HOUR_IN_MILLIS); - expectDefaultSettings(); - expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) - .insertEntry(TEST_IFACE, 1024L, 8L, 2048L, 16L)); - expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 2) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 0L) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 256L, 2L, 128L, 1L, 0L) - .insertEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 512L, 4L, 256L, 2L, 0L) - .insertEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 256L, 2L, 128L, 1L, 0L) - .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 0L)); - mService.setUidForeground(UID_RED, false); - mService.incrementOperationCount(UID_RED, 0xFAAD, 4); - mService.setUidForeground(UID_RED, true); - mService.incrementOperationCount(UID_RED, 0xFAAD, 6); - - forcePollAndWaitForIdle(); - - // verify service recorded history - assertNetworkTotal(sTemplateWifi, 1024L, 8L, 2048L, 16L, 0); - assertUidTotal(sTemplateWifi, UID_RED, 1024L, 8L, 512L, 4L, 10); - assertUidTotal(sTemplateWifi, UID_RED, SET_DEFAULT, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 512L, 4L, 256L, 2L, 4); - assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 512L, 4L, 256L, 2L, 6); - assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 1L, 128L, 1L, 0); - - - // graceful shutdown system, which should trigger persist of stats, and - // clear any values in memory. - expectDefaultSettings(); - mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SHUTDOWN)); - assertStatsFilesExist(true); - - // boot through serviceReady() again - expectDefaultSettings(); - expectNetworkStatsUidDetail(buildEmptyStats()); - expectSystemReady(); - - mService.systemReady(); - - // after systemReady(), we should have historical stats loaded again - assertNetworkTotal(sTemplateWifi, 1024L, 8L, 2048L, 16L, 0); - assertUidTotal(sTemplateWifi, UID_RED, 1024L, 8L, 512L, 4L, 10); - assertUidTotal(sTemplateWifi, UID_RED, SET_DEFAULT, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 512L, 4L, 256L, 2L, 4); - assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 512L, 4L, 256L, 2L, 6); - assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 1L, 128L, 1L, 0); - - } - - // TODO: simulate reboot to test bucket resize - @Test - @Ignore - public void testStatsBucketResize() throws Exception { - NetworkStatsHistory history = null; - - assertStatsFilesExist(false); - - // pretend that wifi network comes online; service should ask about full - // network state, and poll any existing interfaces before updating. - expectSettings(0L, HOUR_IN_MILLIS, WEEK_IN_MILLIS); - NetworkStateSnapshot[] states = new NetworkStateSnapshot[] {buildWifiState()}; - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(buildEmptyStats()); - - mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states), - new UnderlyingNetworkInfo[0]); - - // modify some number on wifi, and trigger poll event - incrementCurrentTime(2 * HOUR_IN_MILLIS); - expectSettings(0L, HOUR_IN_MILLIS, WEEK_IN_MILLIS); - expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) - .insertEntry(TEST_IFACE, 512L, 4L, 512L, 4L)); - expectNetworkStatsUidDetail(buildEmptyStats()); - forcePollAndWaitForIdle(); - - // verify service recorded history - history = mSession.getHistoryForNetwork(sTemplateWifi, FIELD_ALL); - assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 4L, 512L, 4L, 0); - assertEquals(HOUR_IN_MILLIS, history.getBucketDuration()); - assertEquals(2, history.size()); - - - // now change bucket duration setting and trigger another poll with - // exact same values, which should resize existing buckets. - expectSettings(0L, 30 * MINUTE_IN_MILLIS, WEEK_IN_MILLIS); - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(buildEmptyStats()); - forcePollAndWaitForIdle(); - - // verify identical stats, but spread across 4 buckets now - history = mSession.getHistoryForNetwork(sTemplateWifi, FIELD_ALL); - assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 4L, 512L, 4L, 0); - assertEquals(30 * MINUTE_IN_MILLIS, history.getBucketDuration()); - assertEquals(4, history.size()); - - } - - @Test - public void testUidStatsAcrossNetworks() throws Exception { - // pretend first mobile network comes online - expectDefaultSettings(); - NetworkStateSnapshot[] states = new NetworkStateSnapshot[] {buildMobile3gState(IMSI_1)}; - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(buildEmptyStats()); - - mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states), - new UnderlyingNetworkInfo[0]); - - // create some traffic on first network - incrementCurrentTime(HOUR_IN_MILLIS); - expectDefaultSettings(); - expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) - .insertEntry(TEST_IFACE, 2048L, 16L, 512L, 4L)); - expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L) - .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L)); - mService.incrementOperationCount(UID_RED, 0xF00D, 10); - - forcePollAndWaitForIdle(); - - // verify service recorded history - assertNetworkTotal(sTemplateImsi1, 2048L, 16L, 512L, 4L, 0); - assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); - assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 12L, 512L, 4L, 10); - assertUidTotal(sTemplateImsi1, UID_BLUE, 512L, 4L, 0L, 0L, 0); - - - // now switch networks; this also tests that we're okay with interfaces - // disappearing, to verify we don't count backwards. - incrementCurrentTime(HOUR_IN_MILLIS); - expectDefaultSettings(); - states = new NetworkStateSnapshot[] {buildMobile3gState(IMSI_2)}; - expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) - .insertEntry(TEST_IFACE, 2048L, 16L, 512L, 4L)); - expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L) - .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L)); - - mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states), - new UnderlyingNetworkInfo[0]); - forcePollAndWaitForIdle(); - - - // create traffic on second network - incrementCurrentTime(HOUR_IN_MILLIS); - expectDefaultSettings(); - expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) - .insertEntry(TEST_IFACE, 2176L, 17L, 1536L, 12L)); - expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L) - .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 640L, 5L, 1024L, 8L, 0L) - .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xFAAD, 128L, 1L, 1024L, 8L, 0L)); - mService.incrementOperationCount(UID_BLUE, 0xFAAD, 10); - - forcePollAndWaitForIdle(); - - // verify original history still intact - assertNetworkTotal(sTemplateImsi1, 2048L, 16L, 512L, 4L, 0); - assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 12L, 512L, 4L, 10); - assertUidTotal(sTemplateImsi1, UID_BLUE, 512L, 4L, 0L, 0L, 0); - - // and verify new history also recorded under different template, which - // verifies that we didn't cross the streams. - assertNetworkTotal(sTemplateImsi2, 128L, 1L, 1024L, 8L, 0); - assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); - assertUidTotal(sTemplateImsi2, UID_BLUE, 128L, 1L, 1024L, 8L, 10); - - } - - @Test - public void testUidRemovedIsMoved() throws Exception { - // pretend that network comes online - expectDefaultSettings(); - NetworkStateSnapshot[] states = new NetworkStateSnapshot[] {buildWifiState()}; - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(buildEmptyStats()); - - mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states), - new UnderlyingNetworkInfo[0]); - - // create some traffic - incrementCurrentTime(HOUR_IN_MILLIS); - expectDefaultSettings(); - expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) - .insertEntry(TEST_IFACE, 4128L, 258L, 544L, 34L)); - expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L) - .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, - 4096L, 258L, 512L, 32L, 0L) - .insertEntry(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L)); - mService.incrementOperationCount(UID_RED, 0xFAAD, 10); - - forcePollAndWaitForIdle(); - - // verify service recorded history - assertNetworkTotal(sTemplateWifi, 4128L, 258L, 544L, 34L, 0); - assertUidTotal(sTemplateWifi, UID_RED, 16L, 1L, 16L, 1L, 10); - assertUidTotal(sTemplateWifi, UID_BLUE, 4096L, 258L, 512L, 32L, 0); - assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 1L, 16L, 1L, 0); - - - // now pretend two UIDs are uninstalled, which should migrate stats to - // special "removed" bucket. - expectDefaultSettings(); - expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) - .insertEntry(TEST_IFACE, 4128L, 258L, 544L, 34L)); - expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L) - .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, - 4096L, 258L, 512L, 32L, 0L) - .insertEntry(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L)); - final Intent intent = new Intent(ACTION_UID_REMOVED); - intent.putExtra(EXTRA_UID, UID_BLUE); - mServiceContext.sendBroadcast(intent); - intent.putExtra(EXTRA_UID, UID_RED); - mServiceContext.sendBroadcast(intent); - - // existing uid and total should remain unchanged; but removed UID - // should be gone completely. - assertNetworkTotal(sTemplateWifi, 4128L, 258L, 544L, 34L, 0); - assertUidTotal(sTemplateWifi, UID_RED, 0L, 0L, 0L, 0L, 0); - assertUidTotal(sTemplateWifi, UID_BLUE, 0L, 0L, 0L, 0L, 0); - assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 1L, 16L, 1L, 0); - assertUidTotal(sTemplateWifi, UID_REMOVED, 4112L, 259L, 528L, 33L, 10); - - } - - @Test - public void testMobileStatsByRatType() throws Exception { - final NetworkTemplate template3g = - buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_UMTS); - final NetworkTemplate template4g = - buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_LTE); - final NetworkTemplate template5g = - buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_NR); - final NetworkStateSnapshot[] states = - new NetworkStateSnapshot[]{buildMobile3gState(IMSI_1)}; - - // 3G network comes online. - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(buildEmptyStats()); - - setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_UMTS); - mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states), - new UnderlyingNetworkInfo[0]); - - // Create some traffic. - incrementCurrentTime(MINUTE_IN_MILLIS); - expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, - 12L, 18L, 14L, 1L, 0L))); - forcePollAndWaitForIdle(); - - // Verify 3g templates gets stats. - assertUidTotal(sTemplateImsi1, UID_RED, 12L, 18L, 14L, 1L, 0); - assertUidTotal(template3g, UID_RED, 12L, 18L, 14L, 1L, 0); - assertUidTotal(template4g, UID_RED, 0L, 0L, 0L, 0L, 0); - assertUidTotal(template5g, UID_RED, 0L, 0L, 0L, 0L, 0); - - // 4G network comes online. - incrementCurrentTime(MINUTE_IN_MILLIS); - setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_LTE); - expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - // Append more traffic on existing 3g stats entry. - .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, - 16L, 22L, 17L, 2L, 0L)) - // Add entry that is new on 4g. - .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, - 33L, 27L, 8L, 10L, 1L))); - forcePollAndWaitForIdle(); - - // Verify ALL_MOBILE template gets all. 3g template counters do not increase. - assertUidTotal(sTemplateImsi1, UID_RED, 49L, 49L, 25L, 12L, 1); - assertUidTotal(template3g, UID_RED, 12L, 18L, 14L, 1L, 0); - // Verify 4g template counts appended stats on existing entry and newly created entry. - assertUidTotal(template4g, UID_RED, 4L + 33L, 4L + 27L, 3L + 8L, 1L + 10L, 1); - // Verify 5g template doesn't get anything since no traffic is generated on 5g. - assertUidTotal(template5g, UID_RED, 0L, 0L, 0L, 0L, 0); - - // 5g network comes online. - incrementCurrentTime(MINUTE_IN_MILLIS); - setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_NR); - expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - // Existing stats remains. - .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, - 16L, 22L, 17L, 2L, 0L)) - .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, - 33L, 27L, 8L, 10L, 1L)) - // Add some traffic on 5g. - .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, - 5L, 13L, 31L, 9L, 2L))); - forcePollAndWaitForIdle(); - - // Verify ALL_MOBILE template gets all. - assertUidTotal(sTemplateImsi1, UID_RED, 54L, 62L, 56L, 21L, 3); - // 3g/4g template counters do not increase. - assertUidTotal(template3g, UID_RED, 12L, 18L, 14L, 1L, 0); - assertUidTotal(template4g, UID_RED, 4L + 33L, 4L + 27L, 3L + 8L, 1L + 10L, 1); - // Verify 5g template gets the 5g count. - assertUidTotal(template5g, UID_RED, 5L, 13L, 31L, 9L, 2); - } - - @Test - public void testMobileStatsOemManaged() throws Exception { - final NetworkTemplate templateOemPaid = new NetworkTemplate(MATCH_MOBILE_WILDCARD, - /*subscriberId=*/null, /*matchSubscriberIds=*/null, /*networkId=*/null, - METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_PAID, - SUBSCRIBER_ID_MATCH_RULE_EXACT); - - final NetworkTemplate templateOemPrivate = new NetworkTemplate(MATCH_MOBILE_WILDCARD, - /*subscriberId=*/null, /*matchSubscriberIds=*/null, /*networkId=*/null, - METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_PRIVATE, - SUBSCRIBER_ID_MATCH_RULE_EXACT); - - final NetworkTemplate templateOemAll = new NetworkTemplate(MATCH_MOBILE_WILDCARD, - /*subscriberId=*/null, /*matchSubscriberIds=*/null, /*networkId=*/null, - METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, - OEM_PAID | OEM_PRIVATE, SUBSCRIBER_ID_MATCH_RULE_EXACT); - - final NetworkTemplate templateOemYes = new NetworkTemplate(MATCH_MOBILE_WILDCARD, - /*subscriberId=*/null, /*matchSubscriberIds=*/null, /*networkId=*/null, - METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_YES, - SUBSCRIBER_ID_MATCH_RULE_EXACT); - - final NetworkTemplate templateOemNone = new NetworkTemplate(MATCH_MOBILE_WILDCARD, - /*subscriberId=*/null, /*matchSubscriberIds=*/null, /*networkId=*/null, - METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_NO, - SUBSCRIBER_ID_MATCH_RULE_EXACT); - - // OEM_PAID network comes online. - NetworkStateSnapshot[] states = new NetworkStateSnapshot[]{ - buildOemManagedMobileState(IMSI_1, false, - new int[]{NetworkCapabilities.NET_CAPABILITY_OEM_PAID})}; - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(buildEmptyStats()); - mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states), - new UnderlyingNetworkInfo[0]); - - // Create some traffic. - incrementCurrentTime(MINUTE_IN_MILLIS); - expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, - 36L, 41L, 24L, 96L, 0L))); - forcePollAndWaitForIdle(); - - // OEM_PRIVATE network comes online. - states = new NetworkStateSnapshot[]{buildOemManagedMobileState(IMSI_1, false, - new int[]{NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE})}; - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(buildEmptyStats()); - mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states), - new UnderlyingNetworkInfo[0]); - - // Create some traffic. - incrementCurrentTime(MINUTE_IN_MILLIS); - expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, - 49L, 71L, 72L, 48L, 0L))); - forcePollAndWaitForIdle(); - - // OEM_PAID + OEM_PRIVATE network comes online. - states = new NetworkStateSnapshot[]{buildOemManagedMobileState(IMSI_1, false, - new int[]{NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE, - NetworkCapabilities.NET_CAPABILITY_OEM_PAID})}; - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(buildEmptyStats()); - mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states), - new UnderlyingNetworkInfo[0]); - - // Create some traffic. - incrementCurrentTime(MINUTE_IN_MILLIS); - expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, - 57L, 86L, 83L, 93L, 0L))); - forcePollAndWaitForIdle(); - - // OEM_NONE network comes online. - states = new NetworkStateSnapshot[]{buildOemManagedMobileState(IMSI_1, false, new int[]{})}; - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(buildEmptyStats()); - mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states), - new UnderlyingNetworkInfo[0]); - - // Create some traffic. - incrementCurrentTime(MINUTE_IN_MILLIS); - expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, - 29L, 73L, 34L, 31L, 0L))); - forcePollAndWaitForIdle(); - - // Verify OEM_PAID template gets only relevant stats. - assertUidTotal(templateOemPaid, UID_RED, 36L, 41L, 24L, 96L, 0); - - // Verify OEM_PRIVATE template gets only relevant stats. - assertUidTotal(templateOemPrivate, UID_RED, 49L, 71L, 72L, 48L, 0); - - // Verify OEM_PAID + OEM_PRIVATE template gets only relevant stats. - assertUidTotal(templateOemAll, UID_RED, 57L, 86L, 83L, 93L, 0); - - // Verify OEM_NONE sees only non-OEM managed stats. - assertUidTotal(templateOemNone, UID_RED, 29L, 73L, 34L, 31L, 0); - - // Verify OEM_MANAGED_YES sees all OEM managed stats. - assertUidTotal(templateOemYes, UID_RED, - 36L + 49L + 57L, - 41L + 71L + 86L, - 24L + 72L + 83L, - 96L + 48L + 93L, 0); - - // Verify ALL_MOBILE template gets both OEM managed and non-OEM managed stats. - assertUidTotal(sTemplateImsi1, UID_RED, - 36L + 49L + 57L + 29L, - 41L + 71L + 86L + 73L, - 24L + 72L + 83L + 34L, - 96L + 48L + 93L + 31L, 0); - } - - // TODO: support per IMSI state - private void setMobileRatTypeAndWaitForIdle(int ratType) { - when(mNetworkStatsSubscriptionsMonitor.getRatTypeForSubscriberId(anyString())) - .thenReturn(ratType); - mService.handleOnCollapsedRatTypeChanged(); - HandlerUtils.waitForIdle(mHandlerThread, WAIT_TIMEOUT); - } - - @Test - public void testSummaryForAllUid() throws Exception { - // pretend that network comes online - expectDefaultSettings(); - NetworkStateSnapshot[] states = new NetworkStateSnapshot[] {buildWifiState()}; - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(buildEmptyStats()); - - mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states), - new UnderlyingNetworkInfo[0]); - - // create some traffic for two apps - incrementCurrentTime(HOUR_IN_MILLIS); - expectDefaultSettings(); - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L) - .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 1024L, 8L, 512L, 4L, 0L)); - mService.incrementOperationCount(UID_RED, 0xF00D, 1); - - forcePollAndWaitForIdle(); - - // verify service recorded history - assertUidTotal(sTemplateWifi, UID_RED, 50L, 5L, 50L, 5L, 1); - assertUidTotal(sTemplateWifi, UID_BLUE, 1024L, 8L, 512L, 4L, 0); - - - // now create more traffic in next hour, but only for one app - incrementCurrentTime(HOUR_IN_MILLIS); - expectDefaultSettings(); - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L) - .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, - 2048L, 16L, 1024L, 8L, 0L)); - forcePollAndWaitForIdle(); - - // first verify entire history present - NetworkStats stats = mSession.getSummaryForAllUid( - sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true); - assertEquals(3, stats.size()); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 50L, 5L, 50L, 5L, 1); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 10L, 1L, 10L, 1L, 1); - assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 2048L, 16L, 1024L, 8L, 0); - - // now verify that recent history only contains one uid - final long currentTime = currentTimeMillis(); - stats = mSession.getSummaryForAllUid( - sTemplateWifi, currentTime - HOUR_IN_MILLIS, currentTime, true); - assertEquals(1, stats.size()); - assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 1024L, 8L, 512L, 4L, 0); - } - - @Test - public void testDetailedUidStats() throws Exception { - // pretend that network comes online - expectDefaultSettings(); - NetworkStateSnapshot[] states = new NetworkStateSnapshot[] {buildWifiState()}; - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(buildEmptyStats()); - - mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states), - new UnderlyingNetworkInfo[0]); - - NetworkStats.Entry entry1 = new NetworkStats.Entry( - TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L); - NetworkStats.Entry entry2 = new NetworkStats.Entry( - TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 50L, 5L, 50L, 5L, 0L); - NetworkStats.Entry entry3 = new NetworkStats.Entry( - TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xBEEF, 1024L, 8L, 512L, 4L, 0L); - - incrementCurrentTime(HOUR_IN_MILLIS); - expectDefaultSettings(); - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3) - .insertEntry(entry1) - .insertEntry(entry2) - .insertEntry(entry3)); - mService.incrementOperationCount(UID_RED, 0xF00D, 1); - - NetworkStats stats = mService.getDetailedUidStats(INTERFACES_ALL); - - assertEquals(3, stats.size()); - entry1.operations = 1; - assertEquals(entry1, stats.getValues(0, null)); - entry2.operations = 1; - assertEquals(entry2, stats.getValues(1, null)); - assertEquals(entry3, stats.getValues(2, null)); - } - - @Test - public void testDetailedUidStats_Filtered() throws Exception { - // pretend that network comes online - expectDefaultSettings(); - - final String stackedIface = "stacked-test0"; - final LinkProperties stackedProp = new LinkProperties(); - stackedProp.setInterfaceName(stackedIface); - final NetworkStateSnapshot wifiState = buildWifiState(); - wifiState.getLinkProperties().addStackedLink(stackedProp); - NetworkStateSnapshot[] states = new NetworkStateSnapshot[] {wifiState}; - - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(buildEmptyStats()); - - mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states), - new UnderlyingNetworkInfo[0]); - - NetworkStats.Entry uidStats = new NetworkStats.Entry( - TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xF00D, 1024L, 8L, 512L, 4L, 0L); - // Stacked on matching interface - NetworkStats.Entry tetheredStats1 = new NetworkStats.Entry( - stackedIface, UID_BLUE, SET_DEFAULT, 0xF00D, 1024L, 8L, 512L, 4L, 0L); - // Different interface - NetworkStats.Entry tetheredStats2 = new NetworkStats.Entry( - "otherif", UID_BLUE, SET_DEFAULT, 0xF00D, 1024L, 8L, 512L, 4L, 0L); - - final String[] ifaceFilter = new String[] { TEST_IFACE }; - final String[] augmentedIfaceFilter = new String[] { stackedIface, TEST_IFACE }; - incrementCurrentTime(HOUR_IN_MILLIS); - expectDefaultSettings(); - expectNetworkStatsSummary(buildEmptyStats()); - when(mStatsFactory.augmentWithStackedInterfaces(eq(ifaceFilter))) - .thenReturn(augmentedIfaceFilter); - when(mStatsFactory.readNetworkStatsDetail(eq(UID_ALL), any(), eq(TAG_ALL))) - .thenReturn(new NetworkStats(getElapsedRealtime(), 1) - .insertEntry(uidStats)); - when(mNetManager.getNetworkStatsTethering(STATS_PER_UID)) - .thenReturn(new NetworkStats(getElapsedRealtime(), 2) - .insertEntry(tetheredStats1) - .insertEntry(tetheredStats2)); - - NetworkStats stats = mService.getDetailedUidStats(ifaceFilter); - - // mStatsFactory#readNetworkStatsDetail() has the following invocations: - // 1) NetworkStatsService#systemReady from #setUp. - // 2) mService#notifyNetworkStatus in the test above. - // - // Additionally, we should have one call from the above call to mService#getDetailedUidStats - // with the augmented ifaceFilter. - verify(mStatsFactory, times(2)).readNetworkStatsDetail(UID_ALL, INTERFACES_ALL, TAG_ALL); - verify(mStatsFactory, times(1)).readNetworkStatsDetail( - eq(UID_ALL), - eq(augmentedIfaceFilter), - eq(TAG_ALL)); - assertTrue(ArrayUtils.contains(stats.getUniqueIfaces(), TEST_IFACE)); - assertTrue(ArrayUtils.contains(stats.getUniqueIfaces(), stackedIface)); - assertEquals(2, stats.size()); - assertEquals(uidStats, stats.getValues(0, null)); - assertEquals(tetheredStats1, stats.getValues(1, null)); - } - - @Test - public void testForegroundBackground() throws Exception { - // pretend that network comes online - expectDefaultSettings(); - NetworkStateSnapshot[] states = new NetworkStateSnapshot[] {buildWifiState()}; - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(buildEmptyStats()); - - mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states), - new UnderlyingNetworkInfo[0]); - - // create some initial traffic - incrementCurrentTime(HOUR_IN_MILLIS); - expectDefaultSettings(); - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L)); - mService.incrementOperationCount(UID_RED, 0xF00D, 1); - - forcePollAndWaitForIdle(); - - // verify service recorded history - assertUidTotal(sTemplateWifi, UID_RED, 128L, 2L, 128L, 2L, 1); - - - // now switch to foreground - incrementCurrentTime(HOUR_IN_MILLIS); - expectDefaultSettings(); - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L) - .insertEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 32L, 2L, 32L, 2L, 0L) - .insertEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 1L, 1L, 1L, 1L, 0L)); - mService.setUidForeground(UID_RED, true); - mService.incrementOperationCount(UID_RED, 0xFAAD, 1); - - forcePollAndWaitForIdle(); - - // test that we combined correctly - assertUidTotal(sTemplateWifi, UID_RED, 160L, 4L, 160L, 4L, 2); - - // verify entire history present - final NetworkStats stats = mSession.getSummaryForAllUid( - sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true); - assertEquals(4, stats.size()); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 128L, 2L, 128L, 2L, 1); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 64L, 1L, 64L, 1L, 1); - assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 32L, 2L, 32L, 2L, 1); - assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, 0xFAAD, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 1L, 1L, 1L, 1L, 1); - } - - @Test - public void testMetered() throws Exception { - // pretend that network comes online - expectDefaultSettings(); - NetworkStateSnapshot[] states = - new NetworkStateSnapshot[] {buildWifiState(true /* isMetered */, TEST_IFACE)}; - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(buildEmptyStats()); - - mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states), - new UnderlyingNetworkInfo[0]); - - // create some initial traffic - incrementCurrentTime(HOUR_IN_MILLIS); - expectDefaultSettings(); - expectNetworkStatsSummary(buildEmptyStats()); - // Note that all traffic from NetworkManagementService is tagged as METERED_NO, ROAMING_NO - // and DEFAULT_NETWORK_YES, because these three properties aren't tracked at that layer. - // We layer them on top by inspecting the iface properties. - expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 128L, 2L, 128L, 2L, 0L) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 64L, 1L, 64L, 1L, 0L)); - mService.incrementOperationCount(UID_RED, 0xF00D, 1); - - forcePollAndWaitForIdle(); - - // verify service recorded history - assertUidTotal(sTemplateWifi, UID_RED, 128L, 2L, 128L, 2L, 1); - // verify entire history present - final NetworkStats stats = mSession.getSummaryForAllUid( - sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true); - assertEquals(2, stats.size()); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, - DEFAULT_NETWORK_YES, 128L, 2L, 128L, 2L, 1); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO, - DEFAULT_NETWORK_YES, 64L, 1L, 64L, 1L, 1); - } - - @Test - public void testRoaming() throws Exception { - // pretend that network comes online - expectDefaultSettings(); - NetworkStateSnapshot[] states = - new NetworkStateSnapshot[] {buildMobile3gState(IMSI_1, true /* isRoaming */)}; - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(buildEmptyStats()); - - mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states), - new UnderlyingNetworkInfo[0]); - - // Create some traffic - incrementCurrentTime(HOUR_IN_MILLIS); - expectDefaultSettings(); - expectNetworkStatsSummary(buildEmptyStats()); - // Note that all traffic from NetworkManagementService is tagged as METERED_NO and - // ROAMING_NO, because metered and roaming isn't tracked at that layer. We layer it - // on top by inspecting the iface properties. - expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_ALL, ROAMING_NO, - DEFAULT_NETWORK_YES, 128L, 2L, 128L, 2L, 0L) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_ALL, ROAMING_NO, - DEFAULT_NETWORK_YES, 64L, 1L, 64L, 1L, 0L)); - forcePollAndWaitForIdle(); - - // verify service recorded history - assertUidTotal(sTemplateImsi1, UID_RED, 128L, 2L, 128L, 2L, 0); - - // verify entire history present - final NetworkStats stats = mSession.getSummaryForAllUid( - sTemplateImsi1, Long.MIN_VALUE, Long.MAX_VALUE, true); - assertEquals(2, stats.size()); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, METERED_ALL, ROAMING_YES, - DEFAULT_NETWORK_YES, 128L, 2L, 128L, 2L, 0); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, METERED_ALL, ROAMING_YES, - DEFAULT_NETWORK_YES, 64L, 1L, 64L, 1L, 0); - } - - @Test - public void testTethering() throws Exception { - // pretend first mobile network comes online - expectDefaultSettings(); - final NetworkStateSnapshot[] states = - new NetworkStateSnapshot[]{buildMobile3gState(IMSI_1)}; - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(buildEmptyStats()); - - mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states), - new UnderlyingNetworkInfo[0]); - - // create some tethering traffic - incrementCurrentTime(HOUR_IN_MILLIS); - expectDefaultSettings(); - - // Register custom provider and retrieve callback. - final TestableNetworkStatsProviderBinder provider = - new TestableNetworkStatsProviderBinder(); - final INetworkStatsProviderCallback cb = - mService.registerNetworkStatsProvider("TEST-TETHERING-OFFLOAD", provider); - assertNotNull(cb); - final long now = getElapsedRealtime(); - - // Traffic seen by kernel counters (includes software tethering). - final NetworkStats swIfaceStats = new NetworkStats(now, 1) - .insertEntry(TEST_IFACE, 1536L, 12L, 384L, 3L); - // Hardware tethering traffic, not seen by kernel counters. - final NetworkStats tetherHwIfaceStats = new NetworkStats(now, 1) - .insertEntry(new NetworkStats.Entry(TEST_IFACE, UID_ALL, SET_DEFAULT, - TAG_NONE, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_YES, - 512L, 4L, 128L, 1L, 0L)); - final NetworkStats tetherHwUidStats = new NetworkStats(now, 1) - .insertEntry(new NetworkStats.Entry(TEST_IFACE, UID_TETHERING, SET_DEFAULT, - TAG_NONE, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_YES, - 512L, 4L, 128L, 1L, 0L)); - cb.notifyStatsUpdated(0 /* unused */, tetherHwIfaceStats, tetherHwUidStats); - - // Fake some traffic done by apps on the device (as opposed to tethering), and record it - // into UID stats (as opposed to iface stats). - final NetworkStats localUidStats = new NetworkStats(now, 1) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L); - // Software per-uid tethering traffic. - final NetworkStats tetherSwUidStats = new NetworkStats(now, 1) - .insertEntry(TEST_IFACE, UID_TETHERING, SET_DEFAULT, TAG_NONE, 1408L, 10L, 256L, 1L, - 0L); - - expectNetworkStatsSummary(swIfaceStats); - expectNetworkStatsUidDetail(localUidStats, tetherSwUidStats); - forcePollAndWaitForIdle(); - - // verify service recorded history - assertNetworkTotal(sTemplateImsi1, 2048L, 16L, 512L, 4L, 0); - assertUidTotal(sTemplateImsi1, UID_RED, 128L, 2L, 128L, 2L, 0); - assertUidTotal(sTemplateImsi1, UID_TETHERING, 1920L, 14L, 384L, 2L, 0); - } - - @Test - public void testRegisterUsageCallback() throws Exception { - // pretend that wifi network comes online; service should ask about full - // network state, and poll any existing interfaces before updating. - expectDefaultSettings(); - NetworkStateSnapshot[] states = new NetworkStateSnapshot[] {buildWifiState()}; - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(buildEmptyStats()); - - mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states), - new UnderlyingNetworkInfo[0]); - - // verify service has empty history for wifi - assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); - long thresholdInBytes = 1L; // very small; should be overriden by framework - DataUsageRequest inputRequest = new DataUsageRequest( - DataUsageRequest.REQUEST_ID_UNSET, sTemplateWifi, thresholdInBytes); - - // Create a messenger that waits for callback activity - ConditionVariable cv = new ConditionVariable(false); - LatchedHandler latchedHandler = new LatchedHandler(Looper.getMainLooper(), cv); - Messenger messenger = new Messenger(latchedHandler); - - // Force poll - expectDefaultSettings(); - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(buildEmptyStats()); - - // Register and verify request and that binder was called - DataUsageRequest request = - mService.registerUsageCallback(mServiceContext.getOpPackageName(), inputRequest, - messenger, mBinder); - assertTrue(request.requestId > 0); - assertTrue(Objects.equals(sTemplateWifi, request.template)); - long minThresholdInBytes = 2 * 1024 * 1024; // 2 MB - assertEquals(minThresholdInBytes, request.thresholdInBytes); - - HandlerUtils.waitForIdle(mHandlerThread, WAIT_TIMEOUT); - - // Make sure that the caller binder gets connected - verify(mBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); - - // modify some number on wifi, and trigger poll event - // not enough traffic to call data usage callback - incrementCurrentTime(HOUR_IN_MILLIS); - expectDefaultSettings(); - expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) - .insertEntry(TEST_IFACE, 1024L, 1L, 2048L, 2L)); - expectNetworkStatsUidDetail(buildEmptyStats()); - forcePollAndWaitForIdle(); - - // verify service recorded history - assertNetworkTotal(sTemplateWifi, 1024L, 1L, 2048L, 2L, 0); - - // make sure callback has not being called - assertEquals(INVALID_TYPE, latchedHandler.lastMessageType); - - // and bump forward again, with counters going higher. this is - // important, since it will trigger the data usage callback - incrementCurrentTime(DAY_IN_MILLIS); - expectDefaultSettings(); - expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) - .insertEntry(TEST_IFACE, 4096000L, 4L, 8192000L, 8L)); - expectNetworkStatsUidDetail(buildEmptyStats()); - forcePollAndWaitForIdle(); - - // verify service recorded history - assertNetworkTotal(sTemplateWifi, 4096000L, 4L, 8192000L, 8L, 0); - - - // Wait for the caller to ack receipt of CALLBACK_LIMIT_REACHED - assertTrue(cv.block(WAIT_TIMEOUT)); - assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, latchedHandler.lastMessageType); - cv.close(); - - // Allow binder to disconnect - when(mBinder.unlinkToDeath(any(IBinder.DeathRecipient.class), anyInt())).thenReturn(true); - - // Unregister request - mService.unregisterUsageRequest(request); - - // Wait for the caller to ack receipt of CALLBACK_RELEASED - assertTrue(cv.block(WAIT_TIMEOUT)); - assertEquals(NetworkStatsManager.CALLBACK_RELEASED, latchedHandler.lastMessageType); - - // Make sure that the caller binder gets disconnected - verify(mBinder).unlinkToDeath(any(IBinder.DeathRecipient.class), anyInt()); - } - - @Test - public void testUnregisterUsageCallback_unknown_noop() throws Exception { - String callingPackage = "the.calling.package"; - long thresholdInBytes = 10 * 1024 * 1024; // 10 MB - DataUsageRequest unknownRequest = new DataUsageRequest( - 2 /* requestId */, sTemplateImsi1, thresholdInBytes); - - mService.unregisterUsageRequest(unknownRequest); - } - - @Test - public void testStatsProviderUpdateStats() throws Exception { - // Pretend that network comes online. - expectDefaultSettings(); - final NetworkStateSnapshot[] states = - new NetworkStateSnapshot[]{buildWifiState(true /* isMetered */, TEST_IFACE)}; - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(buildEmptyStats()); - - // Register custom provider and retrieve callback. - final TestableNetworkStatsProviderBinder provider = - new TestableNetworkStatsProviderBinder(); - final INetworkStatsProviderCallback cb = - mService.registerNetworkStatsProvider("TEST", provider); - assertNotNull(cb); - - mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states), - new UnderlyingNetworkInfo[0]); - - // Verifies that one requestStatsUpdate will be called during iface update. - provider.expectOnRequestStatsUpdate(0 /* unused */); - - // Create some initial traffic and report to the service. - incrementCurrentTime(HOUR_IN_MILLIS); - final NetworkStats expectedStats = new NetworkStats(0L, 1) - .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, - TAG_NONE, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_YES, - 128L, 2L, 128L, 2L, 1L)) - .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, - 0xF00D, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_YES, - 64L, 1L, 64L, 1L, 1L)); - cb.notifyStatsUpdated(0 /* unused */, expectedStats, expectedStats); - - // Make another empty mutable stats object. This is necessary since the new NetworkStats - // object will be used to compare with the old one in NetworkStatsRecoder, two of them - // cannot be the same object. - expectNetworkStatsUidDetail(buildEmptyStats()); - - forcePollAndWaitForIdle(); - - // Verifies that one requestStatsUpdate and setAlert will be called during polling. - provider.expectOnRequestStatsUpdate(0 /* unused */); - provider.expectOnSetAlert(MB_IN_BYTES); - - // Verifies that service recorded history, does not verify uid tag part. - assertUidTotal(sTemplateWifi, UID_RED, 128L, 2L, 128L, 2L, 1); - - // Verifies that onStatsUpdated updates the stats accordingly. - final NetworkStats stats = mSession.getSummaryForAllUid( - sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true); - assertEquals(2, stats.size()); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, - DEFAULT_NETWORK_YES, 128L, 2L, 128L, 2L, 1L); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO, - DEFAULT_NETWORK_YES, 64L, 1L, 64L, 1L, 1L); - - // Verifies that unregister the callback will remove the provider from service. - cb.unregister(); - forcePollAndWaitForIdle(); - provider.assertNoCallback(); - } - - @Test - public void testDualVilteProviderStats() throws Exception { - // Pretend that network comes online. - expectDefaultSettings(); - final int subId1 = 1; - final int subId2 = 2; - final NetworkStateSnapshot[] states = new NetworkStateSnapshot[]{ - buildImsState(IMSI_1, subId1, TEST_IFACE), - buildImsState(IMSI_2, subId2, TEST_IFACE2)}; - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(buildEmptyStats()); - - // Register custom provider and retrieve callback. - final TestableNetworkStatsProviderBinder provider = - new TestableNetworkStatsProviderBinder(); - final INetworkStatsProviderCallback cb = - mService.registerNetworkStatsProvider("TEST", provider); - assertNotNull(cb); - - mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states), - new UnderlyingNetworkInfo[0]); - - // Verifies that one requestStatsUpdate will be called during iface update. - provider.expectOnRequestStatsUpdate(0 /* unused */); - - // Create some initial traffic and report to the service. - incrementCurrentTime(HOUR_IN_MILLIS); - final String vtIface1 = NetworkStats.IFACE_VT + subId1; - final String vtIface2 = NetworkStats.IFACE_VT + subId2; - final NetworkStats expectedStats = new NetworkStats(0L, 1) - .addEntry(new NetworkStats.Entry(vtIface1, UID_RED, SET_DEFAULT, - TAG_NONE, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_YES, - 128L, 2L, 128L, 2L, 1L)) - .addEntry(new NetworkStats.Entry(vtIface2, UID_RED, SET_DEFAULT, - TAG_NONE, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_YES, - 64L, 1L, 64L, 1L, 1L)); - cb.notifyStatsUpdated(0 /* unused */, expectedStats, expectedStats); - - // Make another empty mutable stats object. This is necessary since the new NetworkStats - // object will be used to compare with the old one in NetworkStatsRecoder, two of them - // cannot be the same object. - expectNetworkStatsUidDetail(buildEmptyStats()); - - forcePollAndWaitForIdle(); - - // Verifies that one requestStatsUpdate and setAlert will be called during polling. - provider.expectOnRequestStatsUpdate(0 /* unused */); - provider.expectOnSetAlert(MB_IN_BYTES); - - // Verifies that service recorded history, does not verify uid tag part. - assertUidTotal(sTemplateImsi1, UID_RED, 128L, 2L, 128L, 2L, 1); - - // Verifies that onStatsUpdated updates the stats accordingly. - NetworkStats stats = mSession.getSummaryForAllUid( - sTemplateImsi1, Long.MIN_VALUE, Long.MAX_VALUE, true); - assertEquals(1, stats.size()); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, - DEFAULT_NETWORK_YES, 128L, 2L, 128L, 2L, 1L); - - stats = mSession.getSummaryForAllUid( - sTemplateImsi2, Long.MIN_VALUE, Long.MAX_VALUE, true); - assertEquals(1, stats.size()); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, - DEFAULT_NETWORK_YES, 64L, 1L, 64L, 1L, 1L); - - // Verifies that unregister the callback will remove the provider from service. - cb.unregister(); - forcePollAndWaitForIdle(); - provider.assertNoCallback(); - } - - @Test - public void testStatsProviderSetAlert() throws Exception { - // Pretend that network comes online. - expectDefaultSettings(); - NetworkStateSnapshot[] states = - new NetworkStateSnapshot[]{buildWifiState(true /* isMetered */, TEST_IFACE)}; - mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states), - new UnderlyingNetworkInfo[0]); - - // Register custom provider and retrieve callback. - final TestableNetworkStatsProviderBinder provider = - new TestableNetworkStatsProviderBinder(); - final INetworkStatsProviderCallback cb = - mService.registerNetworkStatsProvider("TEST", provider); - assertNotNull(cb); - - // Simulates alert quota of the provider has been reached. - cb.notifyAlertReached(); - HandlerUtils.waitForIdle(mHandlerThread, WAIT_TIMEOUT); - - // Verifies that polling is triggered by alert reached. - provider.expectOnRequestStatsUpdate(0 /* unused */); - // Verifies that global alert will be re-armed. - provider.expectOnSetAlert(MB_IN_BYTES); - } - - private void setCombineSubtypeEnabled(boolean enable) { - when(mSettings.getCombineSubtypeEnabled()).thenReturn(enable); - mHandler.post(() -> mContentObserver.onChange(false, Settings.Global - .getUriFor(Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED))); - waitForIdle(); - if (enable) { - verify(mNetworkStatsSubscriptionsMonitor).stop(); - } else { - verify(mNetworkStatsSubscriptionsMonitor).start(); - } - } - - @Test - public void testDynamicWatchForNetworkRatTypeChanges() throws Exception { - // Build 3G template, type unknown template to get stats while network type is unknown - // and type all template to get the sum of all network type stats. - final NetworkTemplate template3g = - buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_UMTS); - final NetworkTemplate templateUnknown = - buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_UNKNOWN); - final NetworkTemplate templateAll = - buildTemplateMobileWithRatType(null, NETWORK_TYPE_ALL); - final NetworkStateSnapshot[] states = - new NetworkStateSnapshot[]{buildMobile3gState(IMSI_1)}; - - expectNetworkStatsSummary(buildEmptyStats()); - expectNetworkStatsUidDetail(buildEmptyStats()); - - // 3G network comes online. - setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_UMTS); - mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states), - new UnderlyingNetworkInfo[0]); - - // Create some traffic. - incrementCurrentTime(MINUTE_IN_MILLIS); - expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, - 12L, 18L, 14L, 1L, 0L))); - forcePollAndWaitForIdle(); - - // Since CombineSubtypeEnabled is false by default in unit test, the generated traffic - // will be split by RAT type. Verify 3G templates gets stats, while template with unknown - // RAT type gets nothing, and template with NETWORK_TYPE_ALL gets all stats. - assertUidTotal(template3g, UID_RED, 12L, 18L, 14L, 1L, 0); - assertUidTotal(templateUnknown, UID_RED, 0L, 0L, 0L, 0L, 0); - assertUidTotal(templateAll, UID_RED, 12L, 18L, 14L, 1L, 0); - - // Stop monitoring data usage per RAT type changes NetworkStatsService records data - // to {@link TelephonyManager#NETWORK_TYPE_UNKNOWN}. - setCombineSubtypeEnabled(true); - - // Call handleOnCollapsedRatTypeChanged manually to simulate the callback fired - // when stopping monitor, this is needed by NetworkStatsService to trigger - // handleNotifyNetworkStatus. - mService.handleOnCollapsedRatTypeChanged(); - HandlerUtils.waitForIdle(mHandlerThread, WAIT_TIMEOUT); - // Create some traffic. - incrementCurrentTime(MINUTE_IN_MILLIS); - // Append more traffic on existing snapshot. - expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, - 12L + 4L, 18L + 4L, 14L + 3L, 1L + 1L, 0L)) - .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, - 35L, 29L, 7L, 11L, 1L))); - forcePollAndWaitForIdle(); - - // Verify 3G counters do not increase, while template with unknown RAT type gets new - // traffic and template with NETWORK_TYPE_ALL gets all stats. - assertUidTotal(template3g, UID_RED, 12L, 18L, 14L, 1L, 0); - assertUidTotal(templateUnknown, UID_RED, 4L + 35L, 4L + 29L, 3L + 7L, 1L + 11L, 1); - assertUidTotal(templateAll, UID_RED, 16L + 35L, 22L + 29L, 17L + 7L, 2L + 11L, 1); - - // Start monitoring data usage per RAT type changes and NetworkStatsService records data - // by a granular subtype representative of the actual subtype - setCombineSubtypeEnabled(false); - - mService.handleOnCollapsedRatTypeChanged(); - HandlerUtils.waitForIdle(mHandlerThread, WAIT_TIMEOUT); - // Create some traffic. - incrementCurrentTime(MINUTE_IN_MILLIS); - // Append more traffic on existing snapshot. - expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, - 22L, 26L, 19L, 5L, 0L)) - .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, - 35L, 29L, 7L, 11L, 1L))); - forcePollAndWaitForIdle(); - - // Verify traffic is split by RAT type, no increase on template with unknown RAT type - // and template with NETWORK_TYPE_ALL gets all stats. - assertUidTotal(template3g, UID_RED, 6L + 12L , 4L + 18L, 2L + 14L, 3L + 1L, 0); - assertUidTotal(templateUnknown, UID_RED, 4L + 35L, 4L + 29L, 3L + 7L, 1L + 11L, 1); - assertUidTotal(templateAll, UID_RED, 22L + 35L, 26L + 29L, 19L + 7L, 5L + 11L, 1); - } - - @Test - public void testOperationCount_nonDefault_traffic() throws Exception { - // Pretend mobile network comes online, but wifi is the default network. - expectDefaultSettings(); - NetworkStateSnapshot[] states = new NetworkStateSnapshot[]{ - buildWifiState(true /*isMetered*/, TEST_IFACE2), buildMobile3gState(IMSI_1)}; - expectNetworkStatsUidDetail(buildEmptyStats()); - mService.notifyNetworkStatus(NETWORKS_WIFI, states, getActiveIface(states), - new UnderlyingNetworkInfo[0]); - - // Create some traffic on mobile network. - incrementCurrentTime(HOUR_IN_MILLIS); - expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 4) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 2L, 1L, 3L, 4L, 0L) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_YES, 1L, 3L, 2L, 1L, 0L) - .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 5L, 4L, 1L, 4L, 0L)); - // Increment operation count, which must have a specific tag. - mService.incrementOperationCount(UID_RED, 0xF00D, 2); - forcePollAndWaitForIdle(); - - // Verify mobile summary is not changed by the operation count. - final NetworkTemplate templateMobile = - buildTemplateMobileWithRatType(null, NETWORK_TYPE_ALL); - final NetworkStats statsMobile = mSession.getSummaryForAllUid( - templateMobile, Long.MIN_VALUE, Long.MAX_VALUE, true); - assertValues(statsMobile, IFACE_ALL, UID_RED, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, - DEFAULT_NETWORK_ALL, 3L, 4L, 5L, 5L, 0); - assertValues(statsMobile, IFACE_ALL, UID_RED, SET_ALL, 0xF00D, METERED_ALL, ROAMING_ALL, - DEFAULT_NETWORK_ALL, 5L, 4L, 1L, 4L, 0); - - // Verify the operation count is blamed onto the default network. - // TODO: Blame onto the default network is not very reasonable. Consider blame onto the - // network that generates the traffic. - final NetworkTemplate templateWifi = buildTemplateWifiWildcard(); - final NetworkStats statsWifi = mSession.getSummaryForAllUid( - templateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true); - assertValues(statsWifi, IFACE_ALL, UID_RED, SET_ALL, 0xF00D, METERED_ALL, ROAMING_ALL, - DEFAULT_NETWORK_ALL, 0L, 0L, 0L, 0L, 2); - } - - private static File getBaseDir(File statsDir) { - File baseDir = new File(statsDir, "netstats"); - baseDir.mkdirs(); - return baseDir; - } - - private void assertNetworkTotal(NetworkTemplate template, long rxBytes, long rxPackets, - long txBytes, long txPackets, int operations) throws Exception { - assertNetworkTotal(template, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, rxPackets, txBytes, - txPackets, operations); - } - - private void assertNetworkTotal(NetworkTemplate template, long start, long end, long rxBytes, - long rxPackets, long txBytes, long txPackets, int operations) throws Exception { - // verify history API - final NetworkStatsHistory history = mSession.getHistoryForNetwork(template, FIELD_ALL); - assertValues(history, start, end, rxBytes, rxPackets, txBytes, txPackets, operations); - - // verify summary API - final NetworkStats stats = mSession.getSummaryForNetwork(template, start, end); - assertValues(stats, IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, - DEFAULT_NETWORK_ALL, rxBytes, rxPackets, txBytes, txPackets, operations); - } - - private void assertUidTotal(NetworkTemplate template, int uid, long rxBytes, long rxPackets, - long txBytes, long txPackets, int operations) throws Exception { - assertUidTotal(template, uid, SET_ALL, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, - rxBytes, rxPackets, txBytes, txPackets, operations); - } - - private void assertUidTotal(NetworkTemplate template, int uid, int set, int metered, - int roaming, int defaultNetwork, long rxBytes, long rxPackets, long txBytes, - long txPackets, int operations) throws Exception { - // verify history API - final NetworkStatsHistory history = mSession.getHistoryForUid( - template, uid, set, TAG_NONE, FIELD_ALL); - assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, rxPackets, txBytes, - txPackets, operations); - - // verify summary API - final NetworkStats stats = mSession.getSummaryForAllUid( - template, Long.MIN_VALUE, Long.MAX_VALUE, false); - assertValues(stats, IFACE_ALL, uid, set, TAG_NONE, metered, roaming, defaultNetwork, - rxBytes, rxPackets, txBytes, txPackets, operations); - } - - private void expectSystemReady() throws Exception { - expectNetworkStatsSummary(buildEmptyStats()); - } - - private String getActiveIface(NetworkStateSnapshot... states) throws Exception { - if (states == null || states.length == 0 || states[0].getLinkProperties() == null) { - return null; - } - return states[0].getLinkProperties().getInterfaceName(); - } - - private void expectNetworkStatsSummary(NetworkStats summary) throws Exception { - expectNetworkStatsSummaryDev(summary.clone()); - expectNetworkStatsSummaryXt(summary.clone()); - } - - private void expectNetworkStatsSummaryDev(NetworkStats summary) throws Exception { - when(mStatsFactory.readNetworkStatsSummaryDev()).thenReturn(summary); - } - - private void expectNetworkStatsSummaryXt(NetworkStats summary) throws Exception { - when(mStatsFactory.readNetworkStatsSummaryXt()).thenReturn(summary); - } - - private void expectNetworkStatsUidDetail(NetworkStats detail) throws Exception { - expectNetworkStatsUidDetail(detail, new NetworkStats(0L, 0)); - } - - private void expectNetworkStatsUidDetail(NetworkStats detail, NetworkStats tetherStats) - throws Exception { - when(mStatsFactory.readNetworkStatsDetail(UID_ALL, INTERFACES_ALL, TAG_ALL)) - .thenReturn(detail); - - // also include tethering details, since they are folded into UID - when(mNetManager.getNetworkStatsTethering(STATS_PER_UID)).thenReturn(tetherStats); - } - - private void expectDefaultSettings() throws Exception { - expectSettings(0L, HOUR_IN_MILLIS, WEEK_IN_MILLIS); - } - - private void expectSettings(long persistBytes, long bucketDuration, long deleteAge) - throws Exception { - when(mSettings.getPollInterval()).thenReturn(HOUR_IN_MILLIS); - when(mSettings.getPollDelay()).thenReturn(0L); - when(mSettings.getSampleEnabled()).thenReturn(true); - when(mSettings.getCombineSubtypeEnabled()).thenReturn(false); - - final Config config = new Config(bucketDuration, deleteAge, deleteAge); - when(mSettings.getDevConfig()).thenReturn(config); - when(mSettings.getXtConfig()).thenReturn(config); - when(mSettings.getUidConfig()).thenReturn(config); - when(mSettings.getUidTagConfig()).thenReturn(config); - - when(mSettings.getGlobalAlertBytes(anyLong())).thenReturn(MB_IN_BYTES); - when(mSettings.getDevPersistBytes(anyLong())).thenReturn(MB_IN_BYTES); - when(mSettings.getXtPersistBytes(anyLong())).thenReturn(MB_IN_BYTES); - when(mSettings.getUidPersistBytes(anyLong())).thenReturn(MB_IN_BYTES); - when(mSettings.getUidTagPersistBytes(anyLong())).thenReturn(MB_IN_BYTES); - } - - private void assertStatsFilesExist(boolean exist) { - final File basePath = new File(mStatsDir, "netstats"); - if (exist) { - assertTrue(basePath.list().length > 0); - } else { - assertTrue(basePath.list().length == 0); - } - } - - private static void assertValues(NetworkStatsHistory stats, long start, long end, long rxBytes, - long rxPackets, long txBytes, long txPackets, int operations) { - final NetworkStatsHistory.Entry entry = stats.getValues(start, end, null); - assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); - assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets); - assertEquals("unexpected txBytes", txBytes, entry.txBytes); - assertEquals("unexpected txPackets", txPackets, entry.txPackets); - assertEquals("unexpected operations", operations, entry.operations); - } - - private static NetworkStateSnapshot buildWifiState() { - return buildWifiState(false, TEST_IFACE, null); - } - - private static NetworkStateSnapshot buildWifiState(boolean isMetered, @NonNull String iface) { - return buildWifiState(isMetered, iface, null); - } - - private static NetworkStateSnapshot buildWifiState(boolean isMetered, @NonNull String iface, - String subscriberId) { - final LinkProperties prop = new LinkProperties(); - prop.setInterfaceName(iface); - final NetworkCapabilities capabilities = new NetworkCapabilities(); - capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, !isMetered); - capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true); - capabilities.addTransportType(NetworkCapabilities.TRANSPORT_WIFI); - capabilities.setSSID(TEST_SSID); - return new NetworkStateSnapshot(WIFI_NETWORK, capabilities, prop, subscriberId, TYPE_WIFI); - } - - private static NetworkStateSnapshot buildMobile3gState(String subscriberId) { - return buildMobile3gState(subscriberId, false /* isRoaming */); - } - - private static NetworkStateSnapshot buildMobile3gState(String subscriberId, boolean isRoaming) { - final LinkProperties prop = new LinkProperties(); - prop.setInterfaceName(TEST_IFACE); - final NetworkCapabilities capabilities = new NetworkCapabilities(); - capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, false); - capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, !isRoaming); - capabilities.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR); - return new NetworkStateSnapshot( - MOBILE_NETWORK, capabilities, prop, subscriberId, TYPE_MOBILE); - } - - private NetworkStats buildEmptyStats() { - return new NetworkStats(getElapsedRealtime(), 0); - } - - private static NetworkStateSnapshot buildOemManagedMobileState( - String subscriberId, boolean isRoaming, int[] oemNetCapabilities) { - final LinkProperties prop = new LinkProperties(); - prop.setInterfaceName(TEST_IFACE); - final NetworkCapabilities capabilities = new NetworkCapabilities(); - capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, false); - capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, !isRoaming); - for (int nc : oemNetCapabilities) { - capabilities.setCapability(nc, true); - } - capabilities.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR); - return new NetworkStateSnapshot(MOBILE_NETWORK, capabilities, prop, subscriberId, - TYPE_MOBILE); - } - - private static NetworkStateSnapshot buildImsState( - String subscriberId, int subId, String ifaceName) { - final LinkProperties prop = new LinkProperties(); - prop.setInterfaceName(ifaceName); - final NetworkCapabilities capabilities = new NetworkCapabilities(); - capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, true); - capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true); - capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_IMS, true); - capabilities.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR); - capabilities.setNetworkSpecifier(new TelephonyNetworkSpecifier(subId)); - return new NetworkStateSnapshot( - MOBILE_NETWORK, capabilities, prop, subscriberId, TYPE_MOBILE); - } - - private long getElapsedRealtime() { - return mElapsedRealtime; - } - - private long startTimeMillis() { - return TEST_START; - } - - private long currentTimeMillis() { - return startTimeMillis() + mElapsedRealtime; - } - - private void incrementCurrentTime(long duration) { - mElapsedRealtime += duration; - } - - private void forcePollAndWaitForIdle() { - mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); - waitForIdle(); - } - - private void waitForIdle() { - HandlerUtils.waitForIdle(mHandlerThread, WAIT_TIMEOUT); - } - - static class LatchedHandler extends Handler { - private final ConditionVariable mCv; - int lastMessageType = INVALID_TYPE; - - LatchedHandler(Looper looper, ConditionVariable cv) { - super(looper); - mCv = cv; - } - - @Override - public void handleMessage(Message msg) { - lastMessageType = msg.what; - mCv.open(); - super.handleMessage(msg); - } - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java b/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java deleted file mode 100644 index 6d2c7dc39ffd0..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.net; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.clearInvocations; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.net.NetworkTemplate; -import android.os.test.TestLooper; -import android.telephony.NetworkRegistrationInfo; -import android.telephony.PhoneStateListener; -import android.telephony.ServiceState; -import android.telephony.SubscriptionManager; -import android.telephony.TelephonyManager; - -import com.android.internal.util.CollectionUtils; -import com.android.server.net.NetworkStatsSubscriptionsMonitor.RatTypeListener; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; - -@RunWith(JUnit4.class) -public final class NetworkStatsSubscriptionsMonitorTest { - private static final int TEST_SUBID1 = 3; - private static final int TEST_SUBID2 = 5; - private static final String TEST_IMSI1 = "466921234567890"; - private static final String TEST_IMSI2 = "466920987654321"; - private static final String TEST_IMSI3 = "466929999999999"; - - @Mock private Context mContext; - @Mock private SubscriptionManager mSubscriptionManager; - @Mock private TelephonyManager mTelephonyManager; - @Mock private NetworkStatsSubscriptionsMonitor.Delegate mDelegate; - private final List mTestSubList = new ArrayList<>(); - - private final Executor mExecutor = Executors.newSingleThreadExecutor(); - private NetworkStatsSubscriptionsMonitor mMonitor; - private TestLooper mTestLooper = new TestLooper(); - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - - when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager); - - when(mContext.getSystemService(eq(Context.TELEPHONY_SUBSCRIPTION_SERVICE))) - .thenReturn(mSubscriptionManager); - when(mContext.getSystemService(eq(Context.TELEPHONY_SERVICE))) - .thenReturn(mTelephonyManager); - - mMonitor = new NetworkStatsSubscriptionsMonitor(mContext, mTestLooper.getLooper(), - mExecutor, mDelegate); - } - - @Test - public void testStartStop() { - // Verify that addOnSubscriptionsChangedListener() is never called before start(). - verify(mSubscriptionManager, never()) - .addOnSubscriptionsChangedListener(mExecutor, mMonitor); - mMonitor.start(); - verify(mSubscriptionManager).addOnSubscriptionsChangedListener(mExecutor, mMonitor); - - // Verify that removeOnSubscriptionsChangedListener() is never called before stop() - verify(mSubscriptionManager, never()).removeOnSubscriptionsChangedListener(mMonitor); - mMonitor.stop(); - verify(mSubscriptionManager).removeOnSubscriptionsChangedListener(mMonitor); - } - - @NonNull - private static int[] convertArrayListToIntArray(@NonNull List arrayList) { - final int[] list = new int[arrayList.size()]; - for (int i = 0; i < arrayList.size(); i++) { - list[i] = arrayList.get(i); - } - return list; - } - - private void setRatTypeForSub(List listeners, - int subId, int type) { - final ServiceState serviceState = mock(ServiceState.class); - when(serviceState.getDataNetworkType()).thenReturn(type); - final RatTypeListener match = CollectionUtils - .find(listeners, it -> it.getSubId() == subId); - if (match == null) { - fail("Could not find listener with subId: " + subId); - } - match.onServiceStateChanged(serviceState); - } - - private void addTestSub(int subId, String subscriberId) { - // add SubId to TestSubList. - if (mTestSubList.contains(subId)) fail("The subscriber list already contains this ID"); - - mTestSubList.add(subId); - - final int[] subList = convertArrayListToIntArray(mTestSubList); - when(mSubscriptionManager.getCompleteActiveSubscriptionIdList()).thenReturn(subList); - when(mTelephonyManager.getSubscriberId(subId)).thenReturn(subscriberId); - mMonitor.onSubscriptionsChanged(); - } - - private void updateSubscriberIdForTestSub(int subId, @Nullable final String subscriberId) { - when(mTelephonyManager.getSubscriberId(subId)).thenReturn(subscriberId); - mMonitor.onSubscriptionsChanged(); - } - - private void removeTestSub(int subId) { - // Remove subId from TestSubList. - mTestSubList.removeIf(it -> it == subId); - final int[] subList = convertArrayListToIntArray(mTestSubList); - when(mSubscriptionManager.getCompleteActiveSubscriptionIdList()).thenReturn(subList); - mMonitor.onSubscriptionsChanged(); - } - - private void assertRatTypeChangedForSub(String subscriberId, int ratType) { - assertEquals(ratType, mMonitor.getRatTypeForSubscriberId(subscriberId)); - final ArgumentCaptor typeCaptor = ArgumentCaptor.forClass(Integer.class); - // Verify callback with the subscriberId and the RAT type should be as expected. - // It will fail if get a callback with an unexpected RAT type. - verify(mDelegate).onCollapsedRatTypeChanged(eq(subscriberId), typeCaptor.capture()); - final int type = typeCaptor.getValue(); - assertEquals(ratType, type); - } - - private void assertRatTypeNotChangedForSub(String subscriberId, int ratType) { - assertEquals(mMonitor.getRatTypeForSubscriberId(subscriberId), ratType); - // Should never get callback with any RAT type. - verify(mDelegate, never()).onCollapsedRatTypeChanged(eq(subscriberId), anyInt()); - } - - @Test - public void testSubChangedAndRatTypeChanged() { - final ArgumentCaptor ratTypeListenerCaptor = - ArgumentCaptor.forClass(RatTypeListener.class); - - mMonitor.start(); - // Insert sim1, verify RAT type is NETWORK_TYPE_UNKNOWN, and never get any callback - // before changing RAT type. - addTestSub(TEST_SUBID1, TEST_IMSI1); - assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN); - - // Insert sim2. - addTestSub(TEST_SUBID2, TEST_IMSI2); - assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN); - verify(mTelephonyManager, times(2)).listen(ratTypeListenerCaptor.capture(), - eq(PhoneStateListener.LISTEN_SERVICE_STATE)); - reset(mDelegate); - - // Set RAT type of sim1 to UMTS. - // Verify RAT type of sim1 after subscription gets onCollapsedRatTypeChanged() callback - // and others remain untouched. - setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID1, - TelephonyManager.NETWORK_TYPE_UMTS); - assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS); - assertRatTypeNotChangedForSub(TEST_IMSI2, TelephonyManager.NETWORK_TYPE_UNKNOWN); - assertRatTypeNotChangedForSub(TEST_IMSI3, TelephonyManager.NETWORK_TYPE_UNKNOWN); - reset(mDelegate); - - // Set RAT type of sim2 to LTE. - // Verify RAT type of sim2 after subscription gets onCollapsedRatTypeChanged() callback - // and others remain untouched. - setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID2, - TelephonyManager.NETWORK_TYPE_LTE); - assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS); - assertRatTypeChangedForSub(TEST_IMSI2, TelephonyManager.NETWORK_TYPE_LTE); - assertRatTypeNotChangedForSub(TEST_IMSI3, TelephonyManager.NETWORK_TYPE_UNKNOWN); - reset(mDelegate); - - // Remove sim2 and verify that callbacks are fired and RAT type is correct for sim2. - // while the other two remain untouched. - removeTestSub(TEST_SUBID2); - verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_NONE)); - assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS); - assertRatTypeChangedForSub(TEST_IMSI2, TelephonyManager.NETWORK_TYPE_UNKNOWN); - assertRatTypeNotChangedForSub(TEST_IMSI3, TelephonyManager.NETWORK_TYPE_UNKNOWN); - reset(mDelegate); - - // Set RAT type of sim1 to UNKNOWN. Then stop monitoring subscription changes - // and verify that the listener for sim1 is removed. - setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID1, - TelephonyManager.NETWORK_TYPE_UNKNOWN); - assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN); - reset(mDelegate); - - mMonitor.stop(); - verify(mTelephonyManager, times(2)).listen(any(), eq(PhoneStateListener.LISTEN_NONE)); - assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN); - } - - - @Test - public void test5g() { - mMonitor.start(); - // Insert sim1, verify RAT type is NETWORK_TYPE_UNKNOWN, and never get any callback - // before changing RAT type. Also capture listener for later use. - addTestSub(TEST_SUBID1, TEST_IMSI1); - assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN); - final ArgumentCaptor ratTypeListenerCaptor = - ArgumentCaptor.forClass(RatTypeListener.class); - verify(mTelephonyManager, times(1)).listen(ratTypeListenerCaptor.capture(), - eq(PhoneStateListener.LISTEN_SERVICE_STATE)); - final RatTypeListener listener = CollectionUtils - .find(ratTypeListenerCaptor.getAllValues(), it -> it.getSubId() == TEST_SUBID1); - assertNotNull(listener); - - // Set RAT type to 5G NSA (non-standalone) mode, verify the monitor outputs - // NETWORK_TYPE_5G_NSA. - final ServiceState serviceState = mock(ServiceState.class); - when(serviceState.getDataNetworkType()).thenReturn(TelephonyManager.NETWORK_TYPE_LTE); - when(serviceState.getNrState()).thenReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED); - listener.onServiceStateChanged(serviceState); - assertRatTypeChangedForSub(TEST_IMSI1, NetworkTemplate.NETWORK_TYPE_5G_NSA); - reset(mDelegate); - - // Set RAT type to LTE without NR connected, the RAT type should be downgraded to LTE. - when(serviceState.getNrState()).thenReturn(NetworkRegistrationInfo.NR_STATE_NONE); - listener.onServiceStateChanged(serviceState); - assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_LTE); - reset(mDelegate); - - // Verify NR connected with other RAT type does not take effect. - when(serviceState.getDataNetworkType()).thenReturn(TelephonyManager.NETWORK_TYPE_UMTS); - when(serviceState.getNrState()).thenReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED); - listener.onServiceStateChanged(serviceState); - assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS); - reset(mDelegate); - - // Set RAT type to 5G standalone mode, the RAT type should be NR. - setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID1, - TelephonyManager.NETWORK_TYPE_NR); - assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_NR); - reset(mDelegate); - - // Set NR state to none in standalone mode does not change anything. - when(serviceState.getDataNetworkType()).thenReturn(TelephonyManager.NETWORK_TYPE_NR); - when(serviceState.getNrState()).thenReturn(NetworkRegistrationInfo.NR_STATE_NONE); - listener.onServiceStateChanged(serviceState); - assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_NR); - } - - @Test - public void testSubscriberIdUnavailable() { - final ArgumentCaptor ratTypeListenerCaptor = - ArgumentCaptor.forClass(RatTypeListener.class); - - mMonitor.start(); - // Insert sim1, set subscriberId to null which is normal in SIM PIN locked case. - // Verify RAT type is NETWORK_TYPE_UNKNOWN and service will not perform listener - // registration. - addTestSub(TEST_SUBID1, null); - verify(mTelephonyManager, never()).listen(any(), anyInt()); - assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN); - - // Set IMSI for sim1, verify the listener will be registered. - updateSubscriberIdForTestSub(TEST_SUBID1, TEST_IMSI1); - verify(mTelephonyManager, times(1)).listen(ratTypeListenerCaptor.capture(), - eq(PhoneStateListener.LISTEN_SERVICE_STATE)); - reset(mTelephonyManager); - when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager); - - // Set RAT type of sim1 to UMTS. Verify RAT type of sim1 is changed. - setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID1, - TelephonyManager.NETWORK_TYPE_UMTS); - assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS); - reset(mDelegate); - - // Set IMSI to null again to simulate somehow IMSI is not available, such as - // modem crash. Verify service should unregister listener. - updateSubscriberIdForTestSub(TEST_SUBID1, null); - verify(mTelephonyManager, times(1)).listen(eq(ratTypeListenerCaptor.getValue()), - eq(PhoneStateListener.LISTEN_NONE)); - assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN); - reset(mDelegate); - clearInvocations(mTelephonyManager); - - // Simulate somehow IMSI is back. Verify service will register with - // another listener and fire callback accordingly. - final ArgumentCaptor ratTypeListenerCaptor2 = - ArgumentCaptor.forClass(RatTypeListener.class); - updateSubscriberIdForTestSub(TEST_SUBID1, TEST_IMSI1); - verify(mTelephonyManager, times(1)).listen(ratTypeListenerCaptor2.capture(), - eq(PhoneStateListener.LISTEN_SERVICE_STATE)); - assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN); - reset(mDelegate); - clearInvocations(mTelephonyManager); - - // Set RAT type of sim1 to LTE. Verify RAT type of sim1 still works. - setRatTypeForSub(ratTypeListenerCaptor2.getAllValues(), TEST_SUBID1, - TelephonyManager.NETWORK_TYPE_LTE); - assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_LTE); - reset(mDelegate); - - mMonitor.stop(); - verify(mTelephonyManager, times(1)).listen(eq(ratTypeListenerCaptor2.getValue()), - eq(PhoneStateListener.LISTEN_NONE)); - assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN); - } - - /** - * Verify that when IMSI suddenly changed for a given subId, the service will register a new - * listener and unregister the old one, and report changes on updated IMSI. This is for modem - * feature that may be enabled for certain carrier, which changes to use a different IMSI while - * roaming on certain networks for multi-IMSI SIM cards, but the subId stays the same. - */ - @Test - public void testSubscriberIdChanged() { - mMonitor.start(); - // Insert sim1, verify RAT type is NETWORK_TYPE_UNKNOWN, and never get any callback - // before changing RAT type. - addTestSub(TEST_SUBID1, TEST_IMSI1); - final ArgumentCaptor ratTypeListenerCaptor = - ArgumentCaptor.forClass(RatTypeListener.class); - verify(mTelephonyManager, times(1)).listen(ratTypeListenerCaptor.capture(), - eq(PhoneStateListener.LISTEN_SERVICE_STATE)); - assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN); - - // Set RAT type of sim1 to UMTS. - // Verify RAT type of sim1 changes accordingly. - setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID1, - TelephonyManager.NETWORK_TYPE_UMTS); - assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS); - reset(mDelegate); - clearInvocations(mTelephonyManager); - - // Simulate IMSI of sim1 changed to IMSI2. Verify the service will register with - // another listener and remove the old one. The RAT type of new IMSI stays at - // NETWORK_TYPE_UNKNOWN until received initial callback from telephony. - final ArgumentCaptor ratTypeListenerCaptor2 = - ArgumentCaptor.forClass(RatTypeListener.class); - updateSubscriberIdForTestSub(TEST_SUBID1, TEST_IMSI2); - verify(mTelephonyManager, times(1)).listen(ratTypeListenerCaptor2.capture(), - eq(PhoneStateListener.LISTEN_SERVICE_STATE)); - verify(mTelephonyManager, times(1)).listen(eq(ratTypeListenerCaptor.getValue()), - eq(PhoneStateListener.LISTEN_NONE)); - assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN); - assertRatTypeNotChangedForSub(TEST_IMSI2, TelephonyManager.NETWORK_TYPE_UNKNOWN); - reset(mDelegate); - - // Set RAT type of sim1 to UMTS for new listener to simulate the initial callback received - // from telephony after registration. Verify RAT type of sim1 changes with IMSI2 - // accordingly. - setRatTypeForSub(ratTypeListenerCaptor2.getAllValues(), TEST_SUBID1, - TelephonyManager.NETWORK_TYPE_UMTS); - assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN); - assertRatTypeChangedForSub(TEST_IMSI2, TelephonyManager.NETWORK_TYPE_UMTS); - reset(mDelegate); - } -} diff --git a/packages/Connectivity/tests/unit/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java b/packages/Connectivity/tests/unit/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java deleted file mode 100644 index ebbc0ef625480..0000000000000 --- a/packages/Connectivity/tests/unit/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.net.ipmemorystore; - -import static org.junit.Assert.assertEquals; - -import android.net.ipmemorystore.NetworkAttributes; -import android.net.networkstack.aidl.quirks.IPv6ProvisioningLossQuirk; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.lang.reflect.Field; -import java.net.Inet4Address; -import java.net.UnknownHostException; -import java.util.Arrays; - -/** Unit tests for {@link NetworkAttributes}. */ -@SmallTest -@RunWith(AndroidJUnit4.class) -public class NetworkAttributesTest { - private static final String WEIGHT_FIELD_NAME_PREFIX = "WEIGHT_"; - private static final float EPSILON = 0.0001f; - - // This is running two tests to make sure the total weight is the sum of all weights. To be - // sure this is not fireproof, but you'd kind of need to do it on purpose to pass. - @Test - public void testTotalWeight() throws IllegalAccessException, UnknownHostException { - // Make sure that TOTAL_WEIGHT is equal to the sum of the fields starting with WEIGHT_ - float sum = 0f; - final Field[] fieldList = NetworkAttributes.class.getDeclaredFields(); - for (final Field field : fieldList) { - if (!field.getName().startsWith(WEIGHT_FIELD_NAME_PREFIX)) continue; - field.setAccessible(true); - sum += (float) field.get(null); - } - assertEquals(sum, NetworkAttributes.TOTAL_WEIGHT, EPSILON); - - final IPv6ProvisioningLossQuirk ipv6ProvisioningLossQuirk = - new IPv6ProvisioningLossQuirk(3, System.currentTimeMillis() + 7_200_000); - // Use directly the constructor with all attributes, and make sure that when compared - // to itself the score is a clean 1.0f. - final NetworkAttributes na = - new NetworkAttributes( - (Inet4Address) Inet4Address.getByAddress(new byte[] {1, 2, 3, 4}), - System.currentTimeMillis() + 7_200_000, - "some hint", - Arrays.asList(Inet4Address.getByAddress(new byte[] {5, 6, 7, 8}), - Inet4Address.getByAddress(new byte[] {9, 0, 1, 2})), - 98, ipv6ProvisioningLossQuirk); - assertEquals(1.0f, na.getNetworkGroupSamenessConfidence(na), EPSILON); - } -} diff --git a/packages/Connectivity/tests/unit/jni/Android.bp b/packages/Connectivity/tests/unit/jni/Android.bp deleted file mode 100644 index 22a04f5c0945f..0000000000000 --- a/packages/Connectivity/tests/unit/jni/Android.bp +++ /dev/null @@ -1,32 +0,0 @@ -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_base_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_base_license"], -} - -cc_library_shared { - name: "libnetworkstatsfactorytestjni", - - cflags: [ - "-Wall", - "-Werror", - "-Wno-unused-parameter", - "-Wthread-safety", - ], - - srcs: [ - ":lib_networkStatsFactory_native", - "test_onload.cpp", - ], - - shared_libs: [ - "libbpf_android", - "liblog", - "libnativehelper", - "libnetdbpf", - "libnetdutils", - ], -} diff --git a/packages/Connectivity/tests/unit/jni/test_onload.cpp b/packages/Connectivity/tests/unit/jni/test_onload.cpp deleted file mode 100644 index 5194ddb0d8823..0000000000000 --- a/packages/Connectivity/tests/unit/jni/test_onload.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 is a mini native libaray for NetworkStatsFactoryTest to run properly. It - * load all the native method related to NetworkStatsFactory when test run - */ -#include -#include "jni.h" -#include "utils/Log.h" -#include "utils/misc.h" - -namespace android { -int register_android_server_net_NetworkStatsFactory(JNIEnv* env); -}; - -using namespace android; - -extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) -{ - JNIEnv* env = NULL; - jint result = -1; - - if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { - ALOGE("GetEnv failed!"); - return result; - } - ALOG_ASSERT(env, "Could not retrieve the env!"); - register_android_server_net_NetworkStatsFactory(env); - return JNI_VERSION_1_4; -} diff --git a/packages/Connectivity/tests/unit/res/raw/history_v1 b/packages/Connectivity/tests/unit/res/raw/history_v1 deleted file mode 100644 index de79491c032e1..0000000000000 Binary files a/packages/Connectivity/tests/unit/res/raw/history_v1 and /dev/null differ diff --git a/packages/Connectivity/tests/unit/res/raw/net_dev_typical b/packages/Connectivity/tests/unit/res/raw/net_dev_typical deleted file mode 100644 index 290bf03eb9b42..0000000000000 --- a/packages/Connectivity/tests/unit/res/raw/net_dev_typical +++ /dev/null @@ -1,8 +0,0 @@ -Inter-| Receive | Transmit - face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed - lo: 8308 116 0 0 0 0 0 0 8308 116 0 0 0 0 0 0 -rmnet0: 1507570 2205 0 0 0 0 0 0 489339 2237 0 0 0 0 0 0 - ifb0: 52454 151 0 151 0 0 0 0 0 0 0 0 0 0 0 0 - ifb1: 52454 151 0 151 0 0 0 0 0 0 0 0 0 0 0 0 - sit0: 0 0 0 0 0 0 0 0 0 0 148 0 0 0 0 0 -ip6tnl0: 0 0 0 0 0 0 0 0 0 0 151 151 0 0 0 0 diff --git a/packages/Connectivity/tests/unit/res/raw/netstats_uid_v4 b/packages/Connectivity/tests/unit/res/raw/netstats_uid_v4 deleted file mode 100644 index e75fc1ca5c2e6..0000000000000 Binary files a/packages/Connectivity/tests/unit/res/raw/netstats_uid_v4 and /dev/null differ diff --git a/packages/Connectivity/tests/unit/res/raw/netstats_v1 b/packages/Connectivity/tests/unit/res/raw/netstats_v1 deleted file mode 100644 index e80860a6b9599..0000000000000 Binary files a/packages/Connectivity/tests/unit/res/raw/netstats_v1 and /dev/null differ diff --git a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_iface_fmt_typical b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_iface_fmt_typical deleted file mode 100644 index 656d5bb82da40..0000000000000 --- a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_iface_fmt_typical +++ /dev/null @@ -1,4 +0,0 @@ -ifname total_skb_rx_bytes total_skb_rx_packets total_skb_tx_bytes total_skb_tx_packets -rmnet2 4968 35 3081 39 -rmnet1 11153922 8051 190226 2468 -rmnet0 6824 16 5692 10 diff --git a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_iface_typical b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_iface_typical deleted file mode 100644 index 610723aef2f20..0000000000000 --- a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_iface_typical +++ /dev/null @@ -1,6 +0,0 @@ -rmnet3 1 0 0 0 0 20822 501 1149991 815 -rmnet2 1 0 0 0 0 1594 15 1313 15 -rmnet1 1 0 0 0 0 207398 458 166918 565 -rmnet0 1 0 0 0 0 2112 24 700 10 -test1 1 1 2 3 4 5 6 7 8 -test2 0 1 2 3 4 5 6 7 8 diff --git a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_typical b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_typical deleted file mode 100644 index c1b0d259955c3..0000000000000 --- a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_typical +++ /dev/null @@ -1,71 +0,0 @@ -idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets -2 wlan0 0x0 0 0 18621 96 2898 44 312 6 15897 58 2412 32 312 6 1010 16 1576 22 -3 wlan0 0x0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -4 wlan0 0x0 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -5 wlan0 0x0 1000 1 1949 13 1078 14 0 0 1600 10 349 3 0 0 600 10 478 4 -6 wlan0 0x0 10005 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -7 wlan0 0x0 10005 1 32081 38 5315 50 32081 38 0 0 0 0 5315 50 0 0 0 0 -8 wlan0 0x0 10011 0 35777 53 5718 57 0 0 0 0 35777 53 0 0 0 0 5718 57 -9 wlan0 0x0 10011 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -10 wlan0 0x0 10014 0 0 0 1098 13 0 0 0 0 0 0 0 0 0 0 1098 13 -11 wlan0 0x0 10014 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -12 wlan0 0x0 10021 0 562386 573 49228 549 0 0 0 0 562386 573 0 0 0 0 49228 549 -13 wlan0 0x0 10021 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -14 wlan0 0x0 10031 0 3425 5 586 6 0 0 0 0 3425 5 0 0 0 0 586 6 -15 wlan0 0x0 10031 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -16 wlan0 0x7fffff0100000000 10021 0 562386 573 49228 549 0 0 0 0 562386 573 0 0 0 0 49228 549 -17 wlan0 0x7fffff0100000000 10021 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -18 wlan0 0x7fffff0100000000 10031 0 3425 5 586 6 0 0 0 0 3425 5 0 0 0 0 586 6 -19 wlan0 0x7fffff0100000000 10031 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -20 rmnet2 0x0 0 0 547 5 118 2 40 1 243 1 264 3 0 0 62 1 56 1 -21 rmnet2 0x0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -22 rmnet2 0x0 10001 0 1125899906842624 5 984 11 632 5 0 0 0 0 984 11 0 0 0 0 -23 rmnet2 0x0 10001 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -24 rmnet1 0x0 0 0 26736 174 7098 130 7210 97 18382 64 1144 13 2932 64 4054 64 112 2 -25 rmnet1 0x0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -26 rmnet1 0x0 1000 0 75774 77 18038 78 75335 72 439 5 0 0 17668 73 370 5 0 0 -27 rmnet1 0x0 1000 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -28 rmnet1 0x0 10007 0 269945 578 111632 586 269945 578 0 0 0 0 111632 586 0 0 0 0 -29 rmnet1 0x0 10007 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -30 rmnet1 0x0 10011 0 1741256 6918 769778 7019 1741256 6918 0 0 0 0 769778 7019 0 0 0 0 -31 rmnet1 0x0 10011 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -32 rmnet1 0x0 10014 0 0 0 786 12 0 0 0 0 0 0 786 12 0 0 0 0 -33 rmnet1 0x0 10014 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -34 rmnet1 0x0 10021 0 433533 1454 393420 1604 433533 1454 0 0 0 0 393420 1604 0 0 0 0 -35 rmnet1 0x0 10021 1 21215 33 10278 33 21215 33 0 0 0 0 10278 33 0 0 0 0 -36 rmnet1 0x0 10036 0 6310 25 3284 29 6310 25 0 0 0 0 3284 29 0 0 0 0 -37 rmnet1 0x0 10036 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -38 rmnet1 0x0 10047 0 34264 47 3936 34 34264 47 0 0 0 0 3936 34 0 0 0 0 -39 rmnet1 0x0 10047 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -40 rmnet1 0x4e7700000000 10011 0 9187 27 4248 33 9187 27 0 0 0 0 4248 33 0 0 0 0 -41 rmnet1 0x4e7700000000 10011 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -42 rmnet1 0x1000000000000000 10007 0 2109 4 791 4 2109 4 0 0 0 0 791 4 0 0 0 0 -43 rmnet1 0x1000000000000000 10007 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -44 rmnet1 0x1000000400000000 10007 0 9811 22 6286 22 9811 22 0 0 0 0 6286 22 0 0 0 0 -45 rmnet1 0x1000000400000000 10007 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -46 rmnet1 0x1010000000000000 10021 0 164833 426 135392 527 164833 426 0 0 0 0 135392 527 0 0 0 0 -47 rmnet1 0x1010000000000000 10021 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -48 rmnet1 0x1144000400000000 10011 0 10112 18 3334 17 10112 18 0 0 0 0 3334 17 0 0 0 0 -49 rmnet1 0x1144000400000000 10011 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -50 rmnet1 0x1244000400000000 10011 0 1300 3 848 2 1300 3 0 0 0 0 848 2 0 0 0 0 -51 rmnet1 0x1244000400000000 10011 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -52 rmnet1 0x3000000000000000 10007 0 10389 14 1521 12 10389 14 0 0 0 0 1521 12 0 0 0 0 -53 rmnet1 0x3000000000000000 10007 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -54 rmnet1 0x3000000400000000 10007 0 238070 380 93938 404 238070 380 0 0 0 0 93938 404 0 0 0 0 -55 rmnet1 0x3000000400000000 10007 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -56 rmnet1 0x3010000000000000 10021 0 219110 578 227423 676 219110 578 0 0 0 0 227423 676 0 0 0 0 -57 rmnet1 0x3010000000000000 10021 1 742 3 1265 3 742 3 0 0 0 0 1265 3 0 0 0 0 -58 rmnet1 0x3020000000000000 10021 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -59 rmnet1 0x3020000000000000 10021 1 20473 30 9013 30 20473 30 0 0 0 0 9013 30 0 0 0 0 -60 rmnet1 0x3144000400000000 10011 0 43963 92 34414 116 43963 92 0 0 0 0 34414 116 0 0 0 0 -61 rmnet1 0x3144000400000000 10011 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -62 rmnet1 0x3244000400000000 10011 0 3486 8 1520 9 3486 8 0 0 0 0 1520 9 0 0 0 0 -63 rmnet1 0x3244000400000000 10011 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -64 rmnet1 0x7fffff0100000000 10021 0 29102 56 8865 60 29102 56 0 0 0 0 8865 60 0 0 0 0 -65 rmnet1 0x7fffff0100000000 10021 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -66 rmnet1 0x7fffff0300000000 1000 0 995 13 14145 14 995 13 0 0 0 0 14145 14 0 0 0 0 -67 rmnet1 0x7fffff0300000000 1000 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -68 rmnet0 0x0 0 0 4312 49 1288 23 0 0 0 0 4312 49 0 0 0 0 1288 23 -69 rmnet0 0x0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -70 rmnet0 0x0 10080 0 22266 30 20976 30 0 0 0 0 22266 30 0 0 0 0 20976 30 -71 rmnet0 0x0 10080 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 diff --git a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_incorrect_iface b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_incorrect_iface deleted file mode 100644 index fc92715253ede..0000000000000 --- a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_incorrect_iface +++ /dev/null @@ -1,3 +0,0 @@ -idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets -2 test_nss_tun0 0x0 1001 0 1000 100 1000 100 0 0 0 0 0 0 0 0 0 0 0 0 -3 test1 0x0 1004 0 1100 100 1100 100 0 0 0 0 0 0 0 0 0 0 0 0 \ No newline at end of file diff --git a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_one_underlying b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_one_underlying deleted file mode 100644 index 1ef18894b6698..0000000000000 --- a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_one_underlying +++ /dev/null @@ -1,5 +0,0 @@ -idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets -2 test_nss_tun0 0x0 1001 0 2000 200 1000 100 0 0 0 0 0 0 0 0 0 0 0 0 -3 test_nss_tun0 0x0 1002 0 1000 100 500 50 0 0 0 0 0 0 0 0 0 0 0 0 -4 test0 0x0 1004 0 3300 300 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -5 test0 0x0 1004 1 0 0 1650 150 0 0 0 0 0 0 0 0 0 0 0 0 \ No newline at end of file diff --git a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_one_underlying_compression b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_one_underlying_compression deleted file mode 100644 index 6d6bf550bbfa2..0000000000000 --- a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_one_underlying_compression +++ /dev/null @@ -1,4 +0,0 @@ -idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets -2 test_nss_tun0 0x0 1001 0 1000 100 1000 100 0 0 0 0 0 0 0 0 0 0 0 0 -3 test_nss_tun0 0x0 1002 0 3000 300 3000 300 0 0 0 0 0 0 0 0 0 0 0 0 -4 test0 0x0 1004 0 1000 100 1000 100 0 0 0 0 0 0 0 0 0 0 0 0 \ No newline at end of file diff --git a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_one_underlying_own_traffic b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_one_underlying_own_traffic deleted file mode 100644 index 2c2e5d2555f6c..0000000000000 --- a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_one_underlying_own_traffic +++ /dev/null @@ -1,6 +0,0 @@ -idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets -2 test_nss_tun0 0x0 1001 0 2000 200 1000 100 0 0 0 0 0 0 0 0 0 0 0 0 -3 test_nss_tun0 0x0 1002 0 1000 100 500 50 0 0 0 0 0 0 0 0 0 0 0 0 -4 test_nss_tun0 0x0 1004 0 5000 500 6000 600 0 0 0 0 0 0 0 0 0 0 0 0 -5 test0 0x0 1004 0 8800 800 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -6 test0 0x0 1004 1 0 0 8250 750 0 0 0 0 0 0 0 0 0 0 0 0 \ No newline at end of file diff --git a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_one_underlying_two_vpn b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_one_underlying_two_vpn deleted file mode 100644 index eb0513b10049c..0000000000000 --- a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_one_underlying_two_vpn +++ /dev/null @@ -1,9 +0,0 @@ -idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets -2 test_nss_tun0 0x0 1001 0 2000 200 1000 100 0 0 0 0 0 0 0 0 0 0 0 0 -3 test_nss_tun0 0x0 1002 0 1000 100 500 50 0 0 0 0 0 0 0 0 0 0 0 0 -4 test_nss_tun1 0x0 1001 0 3000 300 700 70 0 0 0 0 0 0 0 0 0 0 0 0 -5 test_nss_tun1 0x0 1002 0 500 50 250 25 0 0 0 0 0 0 0 0 0 0 0 0 -6 test0 0x0 1004 0 3300 300 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -7 test0 0x0 1004 1 0 0 1650 150 0 0 0 0 0 0 0 0 0 0 0 0 -8 test1 0x0 1004 0 3850 350 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -9 test1 0x0 1004 1 0 0 1045 95 0 0 0 0 0 0 0 0 0 0 0 0 \ No newline at end of file diff --git a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_rewrite_through_self b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_rewrite_through_self deleted file mode 100644 index afcdd71990264..0000000000000 --- a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_rewrite_through_self +++ /dev/null @@ -1,6 +0,0 @@ -idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets -2 test_nss_tun0 0x0 1001 0 2000 200 1000 100 0 0 0 0 0 0 0 0 0 0 0 0 -3 test_nss_tun0 0x0 1002 0 1000 100 500 50 0 0 0 0 0 0 0 0 0 0 0 0 -4 test_nss_tun0 0x0 1004 0 0 0 1600 160 0 0 0 0 0 0 0 0 0 0 0 0 -5 test0 0x0 1004 1 0 0 1760 176 0 0 0 0 0 0 0 0 0 0 0 0 -6 test0 0x0 1004 0 3300 300 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \ No newline at end of file diff --git a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_two_underlying_duplication b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_two_underlying_duplication deleted file mode 100644 index d7c7eb9f4ae8b..0000000000000 --- a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_two_underlying_duplication +++ /dev/null @@ -1,5 +0,0 @@ -idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets -2 test_nss_tun0 0x0 1001 0 1000 100 1000 100 0 0 0 0 0 0 0 0 0 0 0 0 -3 test_nss_tun0 0x0 1002 0 1000 100 1000 100 0 0 0 0 0 0 0 0 0 0 0 0 -4 test0 0x0 1004 0 2200 200 2200 200 0 0 0 0 0 0 0 0 0 0 0 0 -5 test1 0x0 1004 0 2200 200 2200 200 0 0 0 0 0 0 0 0 0 0 0 0 \ No newline at end of file diff --git a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_two_underlying_split b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_two_underlying_split deleted file mode 100644 index 38a3dce4a8344..0000000000000 --- a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_two_underlying_split +++ /dev/null @@ -1,4 +0,0 @@ -idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets -2 test_nss_tun0 0x0 1001 0 500 50 1000 100 0 0 0 0 0 0 0 0 0 0 0 0 -3 test0 0x0 1004 0 330 30 660 60 0 0 0 0 0 0 0 0 0 0 0 0 -4 test1 0x0 1004 0 220 20 440 40 0 0 0 0 0 0 0 0 0 0 0 0 \ No newline at end of file diff --git a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_two_underlying_split_compression b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_two_underlying_split_compression deleted file mode 100644 index d35244b3b4f29..0000000000000 --- a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_two_underlying_split_compression +++ /dev/null @@ -1,4 +0,0 @@ -idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets -2 test_nss_tun0 0x0 1001 0 1000 100 1000 100 0 0 0 0 0 0 0 0 0 0 0 0 -3 test0 0x0 1004 0 600 60 600 60 0 0 0 0 0 0 0 0 0 0 0 0 -4 test1 0x0 1004 0 200 20 200 20 0 0 0 0 0 0 0 0 0 0 0 0 \ No newline at end of file diff --git a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_with_clat b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_with_clat deleted file mode 100644 index 0d893d515ca23..0000000000000 --- a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_vpn_with_clat +++ /dev/null @@ -1,8 +0,0 @@ -idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets -2 test_nss_tun0 0x0 1001 0 2000 200 1000 100 0 0 0 0 0 0 0 0 0 0 0 0 -3 test_nss_tun0 0x0 1002 0 1000 100 500 50 0 0 0 0 0 0 0 0 0 0 0 0 -4 v4-test0 0x0 1004 0 3300 300 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -5 v4-test0 0x0 1004 1 0 0 1650 150 0 0 0 0 0 0 0 0 0 0 0 0 -6 test0 0x0 0 0 9300 300 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -7 test0 0x0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -8 test0 0x0 1029 0 0 0 4650 150 0 0 0 0 0 0 0 0 0 0 0 0 \ No newline at end of file diff --git a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_with_clat b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_with_clat deleted file mode 100644 index f04b32f08332d..0000000000000 --- a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_with_clat +++ /dev/null @@ -1,43 +0,0 @@ -idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets -2 v4-wlan0 0x0 0 0 256 5 196 4 256 5 0 0 0 0 196 4 0 0 0 0 -3 v4-wlan0 0x0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -4 v4-wlan0 0x0 1000 0 30312 25 1770 27 30236 24 76 1 0 0 1694 26 76 1 0 0 -5 v4-wlan0 0x0 1000 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -6 v4-wlan0 0x0 10060 0 9398432 6717 169412 4235 9398432 6717 0 0 0 0 169412 4235 0 0 0 0 -7 v4-wlan0 0x0 10060 1 1448660 1041 31192 753 1448660 1041 0 0 0 0 31192 753 0 0 0 0 -8 v4-wlan0 0x0 10102 0 9702 16 2870 23 9702 16 0 0 0 0 2870 23 0 0 0 0 -9 v4-wlan0 0x0 10102 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -10 wlan0 0x0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -11 wlan0 0x0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -12 wlan0 0x0 1000 0 6126 13 2013 16 5934 11 192 2 0 0 1821 14 192 2 0 0 -13 wlan0 0x0 1000 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -14 wlan0 0x0 10013 0 0 0 144 2 0 0 0 0 0 0 144 2 0 0 0 0 -15 wlan0 0x0 10013 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -16 wlan0 0x0 10018 0 5980263 4715 167667 1922 5972583 4709 0 0 7680 6 167667 1922 0 0 0 0 -17 wlan0 0x0 10018 1 43995 37 2766 27 43995 37 0 0 0 0 2766 27 0 0 0 0 -18 wlan0 0x0 10060 0 134356 133 8705 74 134356 133 0 0 0 0 8705 74 0 0 0 0 -19 wlan0 0x0 10060 1 294709 326 26448 256 294709 326 0 0 0 0 26448 256 0 0 0 0 -20 wlan0 0x0 10079 0 10926 13 1507 13 10926 13 0 0 0 0 1507 13 0 0 0 0 -21 wlan0 0x0 10079 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -22 wlan0 0x0 10102 0 25038 42 8245 57 25038 42 0 0 0 0 8245 57 0 0 0 0 -23 wlan0 0x0 10102 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -24 wlan0 0x0 10103 0 0 0 192 2 0 0 0 0 0 0 0 0 192 2 0 0 -25 wlan0 0x0 10103 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -26 wlan0 0x1000040700000000 10018 0 831 6 655 5 831 6 0 0 0 0 655 5 0 0 0 0 -27 wlan0 0x1000040700000000 10018 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -28 wlan0 0x1000040b00000000 10018 0 1714 8 1561 7 1714 8 0 0 0 0 1561 7 0 0 0 0 -29 wlan0 0x1000040b00000000 10018 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -30 wlan0 0x1000120300000000 10018 0 8243 11 2234 12 8243 11 0 0 0 0 2234 12 0 0 0 0 -31 wlan0 0x1000120300000000 10018 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -32 wlan0 0x1000180300000000 10018 0 56368 49 4790 39 56368 49 0 0 0 0 4790 39 0 0 0 0 -33 wlan0 0x1000180300000000 10018 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -34 wlan0 0x1000300000000000 10018 0 9488 17 18813 25 1808 11 0 0 7680 6 18813 25 0 0 0 0 -35 wlan0 0x1000300000000000 10018 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -36 wlan0 0x3000180400000000 10018 0 131262 103 7416 103 131262 103 0 0 0 0 7416 103 0 0 0 0 -37 wlan0 0x3000180400000000 10018 1 43995 37 2766 27 43995 37 0 0 0 0 2766 27 0 0 0 0 -38 wlan0 0xffffff0100000000 10018 0 5771986 4518 131190 1725 5771986 4518 0 0 0 0 131190 1725 0 0 0 0 -39 wlan0 0xffffff0100000000 10018 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -40 dummy0 0x0 0 0 0 0 168 3 0 0 0 0 0 0 0 0 0 0 168 3 -41 dummy0 0x0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -42 lo 0x0 0 0 1288 16 1288 16 0 0 532 8 756 8 0 0 532 8 756 8 -43 lo 0x0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 diff --git a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_with_clat_100mb_download_after b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_with_clat_100mb_download_after deleted file mode 100644 index 12d98ca29f571..0000000000000 --- a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_with_clat_100mb_download_after +++ /dev/null @@ -1,189 +0,0 @@ -idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets -2 r_rmnet_data0 0x0 0 0 0 0 392 6 0 0 0 0 0 0 0 0 0 0 392 6 -3 r_rmnet_data0 0x0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -4 v4-wlan0 0x0 0 0 58952 2072 2888 65 264 6 0 0 58688 2066 132 3 0 0 2756 62 -5 v4-wlan0 0x0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -6 v4-wlan0 0x0 10034 0 6192 11 1445 11 6192 11 0 0 0 0 1445 11 0 0 0 0 -7 v4-wlan0 0x0 10034 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -8 v4-wlan0 0x0 10057 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -9 v4-wlan0 0x0 10057 1 728 7 392 7 0 0 728 7 0 0 0 0 392 7 0 0 -10 v4-wlan0 0x0 10106 0 2232 18 2232 18 0 0 2232 18 0 0 0 0 2232 18 0 0 -11 v4-wlan0 0x0 10106 1 432952718 314238 5442288 121260 432950238 314218 2480 20 0 0 5433900 121029 8388 231 0 0 -12 wlan0 0x0 0 0 330187296 250652 0 0 329106990 236273 226202 1255 854104 13124 0 0 0 0 0 0 -13 wlan0 0x0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -14 wlan0 0x0 1000 0 77113 272 56151 575 77113 272 0 0 0 0 19191 190 36960 385 0 0 -15 wlan0 0x0 1000 1 20227 80 8356 72 18539 74 1688 6 0 0 7562 66 794 6 0 0 -16 wlan0 0x0 10006 0 80755 92 9122 99 80755 92 0 0 0 0 9122 99 0 0 0 0 -17 wlan0 0x0 10006 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -18 wlan0 0x0 10015 0 4390 7 14824 252 4390 7 0 0 0 0 14824 252 0 0 0 0 -19 wlan0 0x0 10015 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -20 wlan0 0x0 10018 0 4928 11 1741 14 4928 11 0 0 0 0 1741 14 0 0 0 0 -21 wlan0 0x0 10018 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -22 wlan0 0x0 10020 0 21163552 34395 2351650 15326 21162947 34390 605 5 0 0 2351045 15321 605 5 0 0 -23 wlan0 0x0 10020 1 13835740 12938 1548795 6365 13833754 12920 1986 18 0 0 1546809 6347 1986 18 0 0 -24 wlan0 0x0 10023 0 13405 40 5042 44 13405 40 0 0 0 0 5042 44 0 0 0 0 -25 wlan0 0x0 10023 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -26 wlan0 0x0 10034 0 436394741 342648 6237981 80442 436394741 342648 0 0 0 0 6237981 80442 0 0 0 0 -27 wlan0 0x0 10034 1 64860872 51297 1335539 15546 64860872 51297 0 0 0 0 1335539 15546 0 0 0 0 -28 wlan0 0x0 10044 0 17614444 14774 521004 5694 17329882 14432 284562 342 0 0 419974 5408 101030 286 0 0 -29 wlan0 0x0 10044 1 17701 33 3100 28 17701 33 0 0 0 0 3100 28 0 0 0 0 -30 wlan0 0x0 10057 0 12312074 9339 436098 5450 12248060 9263 64014 76 0 0 414224 5388 21874 62 0 0 -31 wlan0 0x0 10057 1 1332953195 954797 31849632 457698 1331933207 953569 1019988 1228 0 0 31702284 456899 147348 799 0 0 -32 wlan0 0x0 10060 0 32972 200 433705 380 32972 200 0 0 0 0 433705 380 0 0 0 0 -33 wlan0 0x0 10060 1 32106 66 37789 87 32106 66 0 0 0 0 37789 87 0 0 0 0 -34 wlan0 0x0 10061 0 7675 23 2509 22 7675 23 0 0 0 0 2509 22 0 0 0 0 -35 wlan0 0x0 10061 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -36 wlan0 0x0 10074 0 38355 82 10447 97 38355 82 0 0 0 0 10447 97 0 0 0 0 -37 wlan0 0x0 10074 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -38 wlan0 0x0 10078 0 49013 79 7167 69 49013 79 0 0 0 0 7167 69 0 0 0 0 -39 wlan0 0x0 10078 1 5872 8 1236 10 5872 8 0 0 0 0 1236 10 0 0 0 0 -40 wlan0 0x0 10082 0 8301 13 1981 15 8301 13 0 0 0 0 1981 15 0 0 0 0 -41 wlan0 0x0 10082 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -42 wlan0 0x0 10086 0 7001 14 1579 15 7001 14 0 0 0 0 1579 15 0 0 0 0 -43 wlan0 0x0 10086 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -44 wlan0 0x0 10090 0 24327795 20224 920502 14661 24327795 20224 0 0 0 0 920502 14661 0 0 0 0 -45 wlan0 0x0 10090 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -46 wlan0 0x0 10092 0 36849 78 12449 81 36849 78 0 0 0 0 12449 81 0 0 0 0 -47 wlan0 0x0 10092 1 60 1 103 1 60 1 0 0 0 0 103 1 0 0 0 0 -48 wlan0 0x0 10095 0 131962 223 37069 241 131962 223 0 0 0 0 37069 241 0 0 0 0 -49 wlan0 0x0 10095 1 12949 21 3930 21 12949 21 0 0 0 0 3930 21 0 0 0 0 -50 wlan0 0x0 10106 0 30899554 22679 632476 12296 30895334 22645 4220 34 0 0 628256 12262 4220 34 0 0 -51 wlan0 0x0 10106 1 88923475 64963 1606962 35612 88917201 64886 3586 29 2688 48 1602032 35535 4930 77 0 0 -52 wlan0 0x40700000000 10020 0 705732 10589 404428 5504 705732 10589 0 0 0 0 404428 5504 0 0 0 0 -53 wlan0 0x40700000000 10020 1 2376 36 1296 18 2376 36 0 0 0 0 1296 18 0 0 0 0 -54 wlan0 0x40800000000 10020 0 34624 146 122525 160 34624 146 0 0 0 0 122525 160 0 0 0 0 -55 wlan0 0x40800000000 10020 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -56 wlan0 0x40b00000000 10020 0 22411 85 7364 57 22411 85 0 0 0 0 7364 57 0 0 0 0 -57 wlan0 0x40b00000000 10020 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -58 wlan0 0x120300000000 10020 0 76641 241 32783 169 76641 241 0 0 0 0 32783 169 0 0 0 0 -59 wlan0 0x120300000000 10020 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -60 wlan0 0x130100000000 10020 0 73101 287 23236 203 73101 287 0 0 0 0 23236 203 0 0 0 0 -61 wlan0 0x130100000000 10020 1 264 4 144 2 264 4 0 0 0 0 144 2 0 0 0 0 -62 wlan0 0x180300000000 10020 0 330648 399 24736 232 330648 399 0 0 0 0 24736 232 0 0 0 0 -63 wlan0 0x180300000000 10020 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -64 wlan0 0x180400000000 10020 0 21865 59 5022 42 21865 59 0 0 0 0 5022 42 0 0 0 0 -65 wlan0 0x180400000000 10020 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -66 wlan0 0x300000000000 10020 0 15984 65 26927 57 15984 65 0 0 0 0 26927 57 0 0 0 0 -67 wlan0 0x300000000000 10020 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -68 wlan0 0x1065fff00000000 10020 0 131871 599 93783 445 131871 599 0 0 0 0 93783 445 0 0 0 0 -69 wlan0 0x1065fff00000000 10020 1 264 4 144 2 264 4 0 0 0 0 144 2 0 0 0 0 -70 wlan0 0x1b24f4600000000 10034 0 15445 42 23329 45 15445 42 0 0 0 0 23329 45 0 0 0 0 -71 wlan0 0x1b24f4600000000 10034 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -72 wlan0 0x1000010000000000 10020 0 5542 9 1364 10 5542 9 0 0 0 0 1364 10 0 0 0 0 -73 wlan0 0x1000010000000000 10020 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -74 wlan0 0x1000040100000000 10020 0 47196 184 213319 257 47196 184 0 0 0 0 213319 257 0 0 0 0 -75 wlan0 0x1000040100000000 10020 1 60 1 103 1 60 1 0 0 0 0 103 1 0 0 0 0 -76 wlan0 0x1000040700000000 10020 0 11599 50 10786 47 11599 50 0 0 0 0 10786 47 0 0 0 0 -77 wlan0 0x1000040700000000 10020 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -78 wlan0 0x1000040800000000 10020 0 21902 145 174139 166 21902 145 0 0 0 0 174139 166 0 0 0 0 -79 wlan0 0x1000040800000000 10020 1 8568 88 105743 90 8568 88 0 0 0 0 105743 90 0 0 0 0 -80 wlan0 0x1000100300000000 10020 0 55213 118 194551 199 55213 118 0 0 0 0 194551 199 0 0 0 0 -81 wlan0 0x1000100300000000 10020 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -82 wlan0 0x1000120300000000 10020 0 50826 74 21153 70 50826 74 0 0 0 0 21153 70 0 0 0 0 -83 wlan0 0x1000120300000000 10020 1 72 1 175 2 72 1 0 0 0 0 175 2 0 0 0 0 -84 wlan0 0x1000180300000000 10020 0 744198 657 65437 592 744198 657 0 0 0 0 65437 592 0 0 0 0 -85 wlan0 0x1000180300000000 10020 1 144719 132 10989 108 144719 132 0 0 0 0 10989 108 0 0 0 0 -86 wlan0 0x1000180600000000 10020 0 4599 8 1928 10 4599 8 0 0 0 0 1928 10 0 0 0 0 -87 wlan0 0x1000180600000000 10020 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -88 wlan0 0x1000250000000000 10020 0 57740 98 13076 88 57740 98 0 0 0 0 13076 88 0 0 0 0 -89 wlan0 0x1000250000000000 10020 1 328 3 414 4 207 2 121 1 0 0 293 3 121 1 0 0 -90 wlan0 0x1000300000000000 10020 0 7675 30 31331 32 7675 30 0 0 0 0 31331 32 0 0 0 0 -91 wlan0 0x1000300000000000 10020 1 30173 97 101335 100 30173 97 0 0 0 0 101335 100 0 0 0 0 -92 wlan0 0x1000310200000000 10020 0 1681 9 2194 9 1681 9 0 0 0 0 2194 9 0 0 0 0 -93 wlan0 0x1000310200000000 10020 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -94 wlan0 0x1000360000000000 10020 0 5606 20 2831 20 5606 20 0 0 0 0 2831 20 0 0 0 0 -95 wlan0 0x1000360000000000 10020 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -96 wlan0 0x11065fff00000000 10020 0 18363 91 83367 104 18363 91 0 0 0 0 83367 104 0 0 0 0 -97 wlan0 0x11065fff00000000 10020 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -98 wlan0 0x3000009600000000 10020 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -99 wlan0 0x3000009600000000 10020 1 6163 18 2424 18 6163 18 0 0 0 0 2424 18 0 0 0 0 -100 wlan0 0x3000009800000000 10020 0 23337 46 8723 39 23337 46 0 0 0 0 8723 39 0 0 0 0 -101 wlan0 0x3000009800000000 10020 1 33744 93 72437 89 33744 93 0 0 0 0 72437 89 0 0 0 0 -102 wlan0 0x3000020000000000 10020 0 4124 11 8969 19 4124 11 0 0 0 0 8969 19 0 0 0 0 -103 wlan0 0x3000020000000000 10020 1 5993 11 3815 14 5993 11 0 0 0 0 3815 14 0 0 0 0 -104 wlan0 0x3000040100000000 10020 0 113809 342 135666 308 113809 342 0 0 0 0 135666 308 0 0 0 0 -105 wlan0 0x3000040100000000 10020 1 142508 642 500579 637 142508 642 0 0 0 0 500579 637 0 0 0 0 -106 wlan0 0x3000040700000000 10020 0 365815 5119 213340 2733 365815 5119 0 0 0 0 213340 2733 0 0 0 0 -107 wlan0 0x3000040700000000 10020 1 30747 130 18408 100 30747 130 0 0 0 0 18408 100 0 0 0 0 -108 wlan0 0x3000040800000000 10020 0 34672 112 68623 92 34672 112 0 0 0 0 68623 92 0 0 0 0 -109 wlan0 0x3000040800000000 10020 1 78443 199 140944 192 78443 199 0 0 0 0 140944 192 0 0 0 0 -110 wlan0 0x3000040b00000000 10020 0 14949 33 4017 26 14949 33 0 0 0 0 4017 26 0 0 0 0 -111 wlan0 0x3000040b00000000 10020 1 996 15 576 8 996 15 0 0 0 0 576 8 0 0 0 0 -112 wlan0 0x3000090000000000 10020 0 11826 67 7309 52 11826 67 0 0 0 0 7309 52 0 0 0 0 -113 wlan0 0x3000090000000000 10020 1 24805 41 4785 41 24805 41 0 0 0 0 4785 41 0 0 0 0 -114 wlan0 0x3000100300000000 10020 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -115 wlan0 0x3000100300000000 10020 1 3112 10 1628 10 3112 10 0 0 0 0 1628 10 0 0 0 0 -116 wlan0 0x3000120300000000 10020 0 38249 107 20374 85 38249 107 0 0 0 0 20374 85 0 0 0 0 -117 wlan0 0x3000120300000000 10020 1 122581 174 36792 143 122581 174 0 0 0 0 36792 143 0 0 0 0 -118 wlan0 0x3000130100000000 10020 0 2700 41 1524 21 2700 41 0 0 0 0 1524 21 0 0 0 0 -119 wlan0 0x3000130100000000 10020 1 22515 59 8366 52 22515 59 0 0 0 0 8366 52 0 0 0 0 -120 wlan0 0x3000180200000000 10020 0 6411 18 14511 20 6411 18 0 0 0 0 14511 20 0 0 0 0 -121 wlan0 0x3000180200000000 10020 1 336 5 319 4 336 5 0 0 0 0 319 4 0 0 0 0 -122 wlan0 0x3000180300000000 10020 0 129301 136 17622 97 129301 136 0 0 0 0 17622 97 0 0 0 0 -123 wlan0 0x3000180300000000 10020 1 464787 429 41703 336 464787 429 0 0 0 0 41703 336 0 0 0 0 -124 wlan0 0x3000180400000000 10020 0 11014 39 2787 25 11014 39 0 0 0 0 2787 25 0 0 0 0 -125 wlan0 0x3000180400000000 10020 1 144040 139 7540 80 144040 139 0 0 0 0 7540 80 0 0 0 0 -126 wlan0 0x3000210100000000 10020 0 10278 44 4579 33 10278 44 0 0 0 0 4579 33 0 0 0 0 -127 wlan0 0x3000210100000000 10020 1 31151 73 14159 47 31151 73 0 0 0 0 14159 47 0 0 0 0 -128 wlan0 0x3000250000000000 10020 0 132 2 72 1 132 2 0 0 0 0 72 1 0 0 0 0 -129 wlan0 0x3000250000000000 10020 1 76614 143 17711 130 76080 137 534 6 0 0 17177 124 534 6 0 0 -130 wlan0 0x3000260100000000 10020 0 9426 26 3535 20 9426 26 0 0 0 0 3535 20 0 0 0 0 -131 wlan0 0x3000260100000000 10020 1 468 7 288 4 468 7 0 0 0 0 288 4 0 0 0 0 -132 wlan0 0x3000300000000000 10020 0 7241 29 12055 26 7241 29 0 0 0 0 12055 26 0 0 0 0 -133 wlan0 0x3000300000000000 10020 1 3273 23 11232 21 3273 23 0 0 0 0 11232 21 0 0 0 0 -134 wlan0 0x3000310000000000 10020 0 132 2 72 1 132 2 0 0 0 0 72 1 0 0 0 0 -135 wlan0 0x3000310000000000 10020 1 53425 64 8721 62 53425 64 0 0 0 0 8721 62 0 0 0 0 -136 wlan0 0x3000310500000000 10020 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -137 wlan0 0x3000310500000000 10020 1 9929 16 3879 18 9929 16 0 0 0 0 3879 18 0 0 0 0 -138 wlan0 0x3000320100000000 10020 0 6844 14 3745 13 6844 14 0 0 0 0 3745 13 0 0 0 0 -139 wlan0 0x3000320100000000 10020 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -140 wlan0 0x3000360000000000 10020 0 8855 43 4749 31 8855 43 0 0 0 0 4749 31 0 0 0 0 -141 wlan0 0x3000360000000000 10020 1 5597 19 2456 19 5597 19 0 0 0 0 2456 19 0 0 0 0 -142 wlan0 0x3010000000000000 10090 0 605140 527 38435 429 605140 527 0 0 0 0 38435 429 0 0 0 0 -143 wlan0 0x3010000000000000 10090 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -144 wlan0 0x31065fff00000000 10020 0 22011 67 29665 64 22011 67 0 0 0 0 29665 64 0 0 0 0 -145 wlan0 0x31065fff00000000 10020 1 10695 34 18347 35 10695 34 0 0 0 0 18347 35 0 0 0 0 -146 wlan0 0x32e544f900000000 10034 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -147 wlan0 0x32e544f900000000 10034 1 40143 54 7299 61 40143 54 0 0 0 0 7299 61 0 0 0 0 -148 wlan0 0x58872a4400000000 10018 0 4928 11 1669 13 4928 11 0 0 0 0 1669 13 0 0 0 0 -149 wlan0 0x58872a4400000000 10018 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -150 wlan0 0x5caeaa7b00000000 10034 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -151 wlan0 0x5caeaa7b00000000 10034 1 74971 73 7103 75 74971 73 0 0 0 0 7103 75 0 0 0 0 -152 wlan0 0x9e00923800000000 10034 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -153 wlan0 0x9e00923800000000 10034 1 72385 98 13072 110 72385 98 0 0 0 0 13072 110 0 0 0 0 -154 wlan0 0xb972bdd400000000 10034 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -155 wlan0 0xb972bdd400000000 10034 1 15282 24 3034 27 15282 24 0 0 0 0 3034 27 0 0 0 0 -156 wlan0 0xc7c9f7ba00000000 10034 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -157 wlan0 0xc7c9f7ba00000000 10034 1 194915 185 13316 138 194915 185 0 0 0 0 13316 138 0 0 0 0 -158 wlan0 0xc9395b2600000000 10034 0 6991 13 6215 14 6991 13 0 0 0 0 6215 14 0 0 0 0 -159 wlan0 0xc9395b2600000000 10034 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -160 wlan0 0xdaddf21100000000 10034 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -161 wlan0 0xdaddf21100000000 10034 1 928676 849 81570 799 928676 849 0 0 0 0 81570 799 0 0 0 0 -162 wlan0 0xe8d195d100000000 10020 0 516 8 288 4 516 8 0 0 0 0 288 4 0 0 0 0 -163 wlan0 0xe8d195d100000000 10020 1 5905 15 2622 15 5905 15 0 0 0 0 2622 15 0 0 0 0 -164 wlan0 0xe8d195d100000000 10034 0 236640 524 312523 555 236640 524 0 0 0 0 312523 555 0 0 0 0 -165 wlan0 0xe8d195d100000000 10034 1 319028 539 188776 553 319028 539 0 0 0 0 188776 553 0 0 0 0 -166 wlan0 0xffffff0100000000 10006 0 80755 92 9122 99 80755 92 0 0 0 0 9122 99 0 0 0 0 -167 wlan0 0xffffff0100000000 10006 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -168 wlan0 0xffffff0100000000 10020 0 17874405 14068 223987 3065 17874405 14068 0 0 0 0 223987 3065 0 0 0 0 -169 wlan0 0xffffff0100000000 10020 1 11011258 8672 177693 2407 11011258 8672 0 0 0 0 177693 2407 0 0 0 0 -170 wlan0 0xffffff0100000000 10034 0 436062595 341880 5843990 79630 436062595 341880 0 0 0 0 5843990 79630 0 0 0 0 -171 wlan0 0xffffff0100000000 10034 1 63201220 49447 1005882 13713 63201220 49447 0 0 0 0 1005882 13713 0 0 0 0 -172 wlan0 0xffffff0100000000 10044 0 17159287 13702 356212 4778 17159287 13702 0 0 0 0 356212 4778 0 0 0 0 -173 wlan0 0xffffff0100000000 10044 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -174 wlan0 0xffffff0100000000 10078 0 10439 17 1665 15 10439 17 0 0 0 0 1665 15 0 0 0 0 -175 wlan0 0xffffff0100000000 10078 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -176 wlan0 0xffffff0100000000 10090 0 23722655 19697 881995 14231 23722655 19697 0 0 0 0 881995 14231 0 0 0 0 -177 wlan0 0xffffff0100000000 10090 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -178 wlan0 0xffffff0500000000 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -179 wlan0 0xffffff0500000000 1000 1 1592 5 314 1 0 0 1592 5 0 0 0 0 314 1 0 0 -180 wlan0 0xffffff0600000000 1000 0 0 0 36960 385 0 0 0 0 0 0 0 0 36960 385 0 0 -181 wlan0 0xffffff0600000000 1000 1 96 1 480 5 0 0 96 1 0 0 0 0 480 5 0 0 -182 wlan0 0xffffff0700000000 1000 0 38732 229 16567 163 38732 229 0 0 0 0 16567 163 0 0 0 0 -183 wlan0 0xffffff0700000000 1000 1 18539 74 7562 66 18539 74 0 0 0 0 7562 66 0 0 0 0 -184 wlan0 0xffffff0900000000 1000 0 38381 43 2624 27 38381 43 0 0 0 0 2624 27 0 0 0 0 -185 wlan0 0xffffff0900000000 1000 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -186 dummy0 0x0 0 0 0 0 168 3 0 0 0 0 0 0 0 0 0 0 168 3 -187 dummy0 0x0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -188 wlan0 0x0 1029 0 0 0 8524052 130894 0 0 0 0 0 0 7871216 121284 108568 1325 544268 8285 -189 wlan0 0x0 1029 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 diff --git a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_with_clat_100mb_download_before b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_with_clat_100mb_download_before deleted file mode 100644 index ce4bcc3a3b43b..0000000000000 --- a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_with_clat_100mb_download_before +++ /dev/null @@ -1,187 +0,0 @@ -idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets -2 r_rmnet_data0 0x0 0 0 0 0 392 6 0 0 0 0 0 0 0 0 0 0 392 6 -3 r_rmnet_data0 0x0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -4 v4-wlan0 0x0 0 0 58848 2070 2836 64 160 4 0 0 58688 2066 80 2 0 0 2756 62 -5 v4-wlan0 0x0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -6 v4-wlan0 0x0 10034 0 6192 11 1445 11 6192 11 0 0 0 0 1445 11 0 0 0 0 -7 v4-wlan0 0x0 10034 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -8 v4-wlan0 0x0 10057 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -9 v4-wlan0 0x0 10057 1 728 7 392 7 0 0 728 7 0 0 0 0 392 7 0 0 -10 v4-wlan0 0x0 10106 0 1488 12 1488 12 0 0 1488 12 0 0 0 0 1488 12 0 0 -11 v4-wlan0 0x0 10106 1 323981189 235142 3509032 84542 323979453 235128 1736 14 0 0 3502676 84363 6356 179 0 0 -12 wlan0 0x0 0 0 330187296 250652 0 0 329106990 236273 226202 1255 854104 13124 0 0 0 0 0 0 -13 wlan0 0x0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -14 wlan0 0x0 1000 0 77113 272 56151 575 77113 272 0 0 0 0 19191 190 36960 385 0 0 -15 wlan0 0x0 1000 1 20227 80 8356 72 18539 74 1688 6 0 0 7562 66 794 6 0 0 -16 wlan0 0x0 10006 0 80755 92 9122 99 80755 92 0 0 0 0 9122 99 0 0 0 0 -17 wlan0 0x0 10006 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -18 wlan0 0x0 10015 0 4390 7 14824 252 4390 7 0 0 0 0 14824 252 0 0 0 0 -19 wlan0 0x0 10015 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -20 wlan0 0x0 10018 0 4928 11 1741 14 4928 11 0 0 0 0 1741 14 0 0 0 0 -21 wlan0 0x0 10018 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -22 wlan0 0x0 10020 0 21141412 34316 2329881 15262 21140807 34311 605 5 0 0 2329276 15257 605 5 0 0 -23 wlan0 0x0 10020 1 13835740 12938 1548555 6362 13833754 12920 1986 18 0 0 1546569 6344 1986 18 0 0 -24 wlan0 0x0 10023 0 13405 40 5042 44 13405 40 0 0 0 0 5042 44 0 0 0 0 -25 wlan0 0x0 10023 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -26 wlan0 0x0 10034 0 436394741 342648 6237981 80442 436394741 342648 0 0 0 0 6237981 80442 0 0 0 0 -27 wlan0 0x0 10034 1 64860872 51297 1335539 15546 64860872 51297 0 0 0 0 1335539 15546 0 0 0 0 -28 wlan0 0x0 10044 0 17614444 14774 521004 5694 17329882 14432 284562 342 0 0 419974 5408 101030 286 0 0 -29 wlan0 0x0 10044 1 17701 33 3100 28 17701 33 0 0 0 0 3100 28 0 0 0 0 -30 wlan0 0x0 10057 0 12311735 9335 435954 5448 12247721 9259 64014 76 0 0 414080 5386 21874 62 0 0 -31 wlan0 0x0 10057 1 1332953195 954797 31849632 457698 1331933207 953569 1019988 1228 0 0 31702284 456899 147348 799 0 0 -32 wlan0 0x0 10060 0 32972 200 433705 380 32972 200 0 0 0 0 433705 380 0 0 0 0 -33 wlan0 0x0 10060 1 32106 66 37789 87 32106 66 0 0 0 0 37789 87 0 0 0 0 -34 wlan0 0x0 10061 0 7675 23 2509 22 7675 23 0 0 0 0 2509 22 0 0 0 0 -35 wlan0 0x0 10061 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -36 wlan0 0x0 10074 0 38355 82 10447 97 38355 82 0 0 0 0 10447 97 0 0 0 0 -37 wlan0 0x0 10074 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -38 wlan0 0x0 10078 0 49013 79 7167 69 49013 79 0 0 0 0 7167 69 0 0 0 0 -39 wlan0 0x0 10078 1 5872 8 1236 10 5872 8 0 0 0 0 1236 10 0 0 0 0 -40 wlan0 0x0 10082 0 8301 13 1981 15 8301 13 0 0 0 0 1981 15 0 0 0 0 -41 wlan0 0x0 10082 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -42 wlan0 0x0 10086 0 7001 14 1579 15 7001 14 0 0 0 0 1579 15 0 0 0 0 -43 wlan0 0x0 10086 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -44 wlan0 0x0 10090 0 24327795 20224 920502 14661 24327795 20224 0 0 0 0 920502 14661 0 0 0 0 -45 wlan0 0x0 10090 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -46 wlan0 0x0 10092 0 36849 78 12449 81 36849 78 0 0 0 0 12449 81 0 0 0 0 -47 wlan0 0x0 10092 1 60 1 103 1 60 1 0 0 0 0 103 1 0 0 0 0 -48 wlan0 0x0 10095 0 131962 223 37069 241 131962 223 0 0 0 0 37069 241 0 0 0 0 -49 wlan0 0x0 10095 1 12949 21 3930 21 12949 21 0 0 0 0 3930 21 0 0 0 0 -50 wlan0 0x0 10106 0 30899554 22679 632476 12296 30895334 22645 4220 34 0 0 628256 12262 4220 34 0 0 -51 wlan0 0x0 10106 1 88922349 64952 1605126 35599 88916075 64875 3586 29 2688 48 1600196 35522 4930 77 0 0 -52 wlan0 0x40700000000 10020 0 705732 10589 404428 5504 705732 10589 0 0 0 0 404428 5504 0 0 0 0 -53 wlan0 0x40700000000 10020 1 2376 36 1296 18 2376 36 0 0 0 0 1296 18 0 0 0 0 -54 wlan0 0x40800000000 10020 0 34624 146 122525 160 34624 146 0 0 0 0 122525 160 0 0 0 0 -55 wlan0 0x40800000000 10020 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -56 wlan0 0x40b00000000 10020 0 22411 85 7364 57 22411 85 0 0 0 0 7364 57 0 0 0 0 -57 wlan0 0x40b00000000 10020 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -58 wlan0 0x120300000000 10020 0 76641 241 32783 169 76641 241 0 0 0 0 32783 169 0 0 0 0 -59 wlan0 0x120300000000 10020 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -60 wlan0 0x130100000000 10020 0 73101 287 23236 203 73101 287 0 0 0 0 23236 203 0 0 0 0 -61 wlan0 0x130100000000 10020 1 264 4 144 2 264 4 0 0 0 0 144 2 0 0 0 0 -62 wlan0 0x180300000000 10020 0 330648 399 24736 232 330648 399 0 0 0 0 24736 232 0 0 0 0 -63 wlan0 0x180300000000 10020 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -64 wlan0 0x180400000000 10020 0 21865 59 5022 42 21865 59 0 0 0 0 5022 42 0 0 0 0 -65 wlan0 0x180400000000 10020 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -66 wlan0 0x300000000000 10020 0 15984 65 26927 57 15984 65 0 0 0 0 26927 57 0 0 0 0 -67 wlan0 0x300000000000 10020 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -68 wlan0 0x1065fff00000000 10020 0 131871 599 93783 445 131871 599 0 0 0 0 93783 445 0 0 0 0 -69 wlan0 0x1065fff00000000 10020 1 264 4 144 2 264 4 0 0 0 0 144 2 0 0 0 0 -70 wlan0 0x1b24f4600000000 10034 0 15445 42 23329 45 15445 42 0 0 0 0 23329 45 0 0 0 0 -71 wlan0 0x1b24f4600000000 10034 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -72 wlan0 0x1000010000000000 10020 0 5542 9 1364 10 5542 9 0 0 0 0 1364 10 0 0 0 0 -73 wlan0 0x1000010000000000 10020 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -74 wlan0 0x1000040100000000 10020 0 47196 184 213319 257 47196 184 0 0 0 0 213319 257 0 0 0 0 -75 wlan0 0x1000040100000000 10020 1 60 1 103 1 60 1 0 0 0 0 103 1 0 0 0 0 -76 wlan0 0x1000040700000000 10020 0 11599 50 10786 47 11599 50 0 0 0 0 10786 47 0 0 0 0 -77 wlan0 0x1000040700000000 10020 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -78 wlan0 0x1000040800000000 10020 0 21902 145 174139 166 21902 145 0 0 0 0 174139 166 0 0 0 0 -79 wlan0 0x1000040800000000 10020 1 8568 88 105743 90 8568 88 0 0 0 0 105743 90 0 0 0 0 -80 wlan0 0x1000100300000000 10020 0 55213 118 194551 199 55213 118 0 0 0 0 194551 199 0 0 0 0 -81 wlan0 0x1000100300000000 10020 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -82 wlan0 0x1000120300000000 10020 0 50826 74 21153 70 50826 74 0 0 0 0 21153 70 0 0 0 0 -83 wlan0 0x1000120300000000 10020 1 72 1 175 2 72 1 0 0 0 0 175 2 0 0 0 0 -84 wlan0 0x1000180300000000 10020 0 744198 657 65437 592 744198 657 0 0 0 0 65437 592 0 0 0 0 -85 wlan0 0x1000180300000000 10020 1 144719 132 10989 108 144719 132 0 0 0 0 10989 108 0 0 0 0 -86 wlan0 0x1000180600000000 10020 0 4599 8 1928 10 4599 8 0 0 0 0 1928 10 0 0 0 0 -87 wlan0 0x1000180600000000 10020 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -88 wlan0 0x1000250000000000 10020 0 57740 98 13076 88 57740 98 0 0 0 0 13076 88 0 0 0 0 -89 wlan0 0x1000250000000000 10020 1 328 3 414 4 207 2 121 1 0 0 293 3 121 1 0 0 -90 wlan0 0x1000300000000000 10020 0 7675 30 31331 32 7675 30 0 0 0 0 31331 32 0 0 0 0 -91 wlan0 0x1000300000000000 10020 1 30173 97 101335 100 30173 97 0 0 0 0 101335 100 0 0 0 0 -92 wlan0 0x1000310200000000 10020 0 1681 9 2194 9 1681 9 0 0 0 0 2194 9 0 0 0 0 -93 wlan0 0x1000310200000000 10020 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -94 wlan0 0x1000360000000000 10020 0 5606 20 2831 20 5606 20 0 0 0 0 2831 20 0 0 0 0 -95 wlan0 0x1000360000000000 10020 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -96 wlan0 0x11065fff00000000 10020 0 18363 91 83367 104 18363 91 0 0 0 0 83367 104 0 0 0 0 -97 wlan0 0x11065fff00000000 10020 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -98 wlan0 0x3000009600000000 10020 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -99 wlan0 0x3000009600000000 10020 1 6163 18 2424 18 6163 18 0 0 0 0 2424 18 0 0 0 0 -100 wlan0 0x3000009800000000 10020 0 23337 46 8723 39 23337 46 0 0 0 0 8723 39 0 0 0 0 -101 wlan0 0x3000009800000000 10020 1 33744 93 72437 89 33744 93 0 0 0 0 72437 89 0 0 0 0 -102 wlan0 0x3000020000000000 10020 0 4124 11 8969 19 4124 11 0 0 0 0 8969 19 0 0 0 0 -103 wlan0 0x3000020000000000 10020 1 5993 11 3815 14 5993 11 0 0 0 0 3815 14 0 0 0 0 -104 wlan0 0x3000040100000000 10020 0 106718 322 121557 287 106718 322 0 0 0 0 121557 287 0 0 0 0 -105 wlan0 0x3000040100000000 10020 1 142508 642 500579 637 142508 642 0 0 0 0 500579 637 0 0 0 0 -106 wlan0 0x3000040700000000 10020 0 365419 5113 213124 2730 365419 5113 0 0 0 0 213124 2730 0 0 0 0 -107 wlan0 0x3000040700000000 10020 1 30747 130 18408 100 30747 130 0 0 0 0 18408 100 0 0 0 0 -108 wlan0 0x3000040800000000 10020 0 34672 112 68623 92 34672 112 0 0 0 0 68623 92 0 0 0 0 -109 wlan0 0x3000040800000000 10020 1 78443 199 140944 192 78443 199 0 0 0 0 140944 192 0 0 0 0 -110 wlan0 0x3000040b00000000 10020 0 14949 33 4017 26 14949 33 0 0 0 0 4017 26 0 0 0 0 -111 wlan0 0x3000040b00000000 10020 1 996 15 576 8 996 15 0 0 0 0 576 8 0 0 0 0 -112 wlan0 0x3000090000000000 10020 0 4017 28 3610 25 4017 28 0 0 0 0 3610 25 0 0 0 0 -113 wlan0 0x3000090000000000 10020 1 24805 41 4545 38 24805 41 0 0 0 0 4545 38 0 0 0 0 -114 wlan0 0x3000100300000000 10020 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -115 wlan0 0x3000100300000000 10020 1 3112 10 1628 10 3112 10 0 0 0 0 1628 10 0 0 0 0 -116 wlan0 0x3000120300000000 10020 0 38249 107 20374 85 38249 107 0 0 0 0 20374 85 0 0 0 0 -117 wlan0 0x3000120300000000 10020 1 122581 174 36792 143 122581 174 0 0 0 0 36792 143 0 0 0 0 -118 wlan0 0x3000130100000000 10020 0 2700 41 1524 21 2700 41 0 0 0 0 1524 21 0 0 0 0 -119 wlan0 0x3000130100000000 10020 1 22515 59 8366 52 22515 59 0 0 0 0 8366 52 0 0 0 0 -120 wlan0 0x3000180200000000 10020 0 6411 18 14511 20 6411 18 0 0 0 0 14511 20 0 0 0 0 -121 wlan0 0x3000180200000000 10020 1 336 5 319 4 336 5 0 0 0 0 319 4 0 0 0 0 -122 wlan0 0x3000180300000000 10020 0 129301 136 17622 97 129301 136 0 0 0 0 17622 97 0 0 0 0 -123 wlan0 0x3000180300000000 10020 1 464787 429 41703 336 464787 429 0 0 0 0 41703 336 0 0 0 0 -124 wlan0 0x3000180400000000 10020 0 11014 39 2787 25 11014 39 0 0 0 0 2787 25 0 0 0 0 -125 wlan0 0x3000180400000000 10020 1 144040 139 7540 80 144040 139 0 0 0 0 7540 80 0 0 0 0 -126 wlan0 0x3000210100000000 10020 0 10278 44 4579 33 10278 44 0 0 0 0 4579 33 0 0 0 0 -127 wlan0 0x3000210100000000 10020 1 31151 73 14159 47 31151 73 0 0 0 0 14159 47 0 0 0 0 -128 wlan0 0x3000250000000000 10020 0 132 2 72 1 132 2 0 0 0 0 72 1 0 0 0 0 -129 wlan0 0x3000250000000000 10020 1 76614 143 17711 130 76080 137 534 6 0 0 17177 124 534 6 0 0 -130 wlan0 0x3000260100000000 10020 0 9426 26 3535 20 9426 26 0 0 0 0 3535 20 0 0 0 0 -131 wlan0 0x3000260100000000 10020 1 468 7 288 4 468 7 0 0 0 0 288 4 0 0 0 0 -132 wlan0 0x3000300000000000 10020 0 7241 29 12055 26 7241 29 0 0 0 0 12055 26 0 0 0 0 -133 wlan0 0x3000300000000000 10020 1 3273 23 11232 21 3273 23 0 0 0 0 11232 21 0 0 0 0 -134 wlan0 0x3000310000000000 10020 0 132 2 72 1 132 2 0 0 0 0 72 1 0 0 0 0 -135 wlan0 0x3000310000000000 10020 1 53425 64 8721 62 53425 64 0 0 0 0 8721 62 0 0 0 0 -136 wlan0 0x3000310500000000 10020 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -137 wlan0 0x3000310500000000 10020 1 9929 16 3879 18 9929 16 0 0 0 0 3879 18 0 0 0 0 -138 wlan0 0x3000360000000000 10020 0 8855 43 4749 31 8855 43 0 0 0 0 4749 31 0 0 0 0 -139 wlan0 0x3000360000000000 10020 1 5597 19 2456 19 5597 19 0 0 0 0 2456 19 0 0 0 0 -140 wlan0 0x3010000000000000 10090 0 605140 527 38435 429 605140 527 0 0 0 0 38435 429 0 0 0 0 -141 wlan0 0x3010000000000000 10090 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -142 wlan0 0x31065fff00000000 10020 0 22011 67 29665 64 22011 67 0 0 0 0 29665 64 0 0 0 0 -143 wlan0 0x31065fff00000000 10020 1 10695 34 18347 35 10695 34 0 0 0 0 18347 35 0 0 0 0 -144 wlan0 0x32e544f900000000 10034 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -145 wlan0 0x32e544f900000000 10034 1 40143 54 7299 61 40143 54 0 0 0 0 7299 61 0 0 0 0 -146 wlan0 0x58872a4400000000 10018 0 4928 11 1669 13 4928 11 0 0 0 0 1669 13 0 0 0 0 -147 wlan0 0x58872a4400000000 10018 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -148 wlan0 0x5caeaa7b00000000 10034 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -149 wlan0 0x5caeaa7b00000000 10034 1 74971 73 7103 75 74971 73 0 0 0 0 7103 75 0 0 0 0 -150 wlan0 0x9e00923800000000 10034 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -151 wlan0 0x9e00923800000000 10034 1 72385 98 13072 110 72385 98 0 0 0 0 13072 110 0 0 0 0 -152 wlan0 0xb972bdd400000000 10034 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -153 wlan0 0xb972bdd400000000 10034 1 15282 24 3034 27 15282 24 0 0 0 0 3034 27 0 0 0 0 -154 wlan0 0xc7c9f7ba00000000 10034 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -155 wlan0 0xc7c9f7ba00000000 10034 1 194915 185 13316 138 194915 185 0 0 0 0 13316 138 0 0 0 0 -156 wlan0 0xc9395b2600000000 10034 0 6991 13 6215 14 6991 13 0 0 0 0 6215 14 0 0 0 0 -157 wlan0 0xc9395b2600000000 10034 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -158 wlan0 0xdaddf21100000000 10034 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -159 wlan0 0xdaddf21100000000 10034 1 928676 849 81570 799 928676 849 0 0 0 0 81570 799 0 0 0 0 -160 wlan0 0xe8d195d100000000 10020 0 516 8 288 4 516 8 0 0 0 0 288 4 0 0 0 0 -161 wlan0 0xe8d195d100000000 10020 1 5905 15 2622 15 5905 15 0 0 0 0 2622 15 0 0 0 0 -162 wlan0 0xe8d195d100000000 10034 0 236640 524 312523 555 236640 524 0 0 0 0 312523 555 0 0 0 0 -163 wlan0 0xe8d195d100000000 10034 1 319028 539 188776 553 319028 539 0 0 0 0 188776 553 0 0 0 0 -164 wlan0 0xffffff0100000000 10006 0 80755 92 9122 99 80755 92 0 0 0 0 9122 99 0 0 0 0 -165 wlan0 0xffffff0100000000 10006 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -166 wlan0 0xffffff0100000000 10020 0 17874405 14068 223987 3065 17874405 14068 0 0 0 0 223987 3065 0 0 0 0 -167 wlan0 0xffffff0100000000 10020 1 11011258 8672 177693 2407 11011258 8672 0 0 0 0 177693 2407 0 0 0 0 -168 wlan0 0xffffff0100000000 10034 0 436062595 341880 5843990 79630 436062595 341880 0 0 0 0 5843990 79630 0 0 0 0 -169 wlan0 0xffffff0100000000 10034 1 63201220 49447 1005882 13713 63201220 49447 0 0 0 0 1005882 13713 0 0 0 0 -170 wlan0 0xffffff0100000000 10044 0 17159287 13702 356212 4778 17159287 13702 0 0 0 0 356212 4778 0 0 0 0 -171 wlan0 0xffffff0100000000 10044 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -172 wlan0 0xffffff0100000000 10078 0 10439 17 1665 15 10439 17 0 0 0 0 1665 15 0 0 0 0 -173 wlan0 0xffffff0100000000 10078 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -174 wlan0 0xffffff0100000000 10090 0 23722655 19697 881995 14231 23722655 19697 0 0 0 0 881995 14231 0 0 0 0 -175 wlan0 0xffffff0100000000 10090 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -176 wlan0 0xffffff0500000000 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -177 wlan0 0xffffff0500000000 1000 1 1592 5 314 1 0 0 1592 5 0 0 0 0 314 1 0 0 -178 wlan0 0xffffff0600000000 1000 0 0 0 36960 385 0 0 0 0 0 0 0 0 36960 385 0 0 -179 wlan0 0xffffff0600000000 1000 1 96 1 480 5 0 0 96 1 0 0 0 0 480 5 0 0 -180 wlan0 0xffffff0700000000 1000 0 38732 229 16567 163 38732 229 0 0 0 0 16567 163 0 0 0 0 -181 wlan0 0xffffff0700000000 1000 1 18539 74 7562 66 18539 74 0 0 0 0 7562 66 0 0 0 0 -182 wlan0 0xffffff0900000000 1000 0 38381 43 2624 27 38381 43 0 0 0 0 2624 27 0 0 0 0 -183 wlan0 0xffffff0900000000 1000 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -184 dummy0 0x0 0 0 0 0 168 3 0 0 0 0 0 0 0 0 0 0 168 3 -185 dummy0 0x0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -186 wlan0 0x0 1029 0 0 0 5855801 94173 0 0 0 0 0 0 5208040 84634 103637 1256 544124 8283 -187 wlan0 0x0 1029 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 diff --git a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_with_clat_simple b/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_with_clat_simple deleted file mode 100644 index a1d6d411bad81..0000000000000 --- a/packages/Connectivity/tests/unit/res/raw/xt_qtaguid_with_clat_simple +++ /dev/null @@ -1,4 +0,0 @@ -idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets -2 v4-wlan0 0x0 10060 0 42600 213 4100 41 42600 213 0 0 0 0 4100 41 0 0 0 0 -3 v4-wlan0 0x0 10060 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -4 wlan0 0x0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0