Merge history of packages/Connectivity

Modified Visibility / Includes for:
- Tethering/common/TetheringLib/Android.bp

Modified License Import for:
- framework/Android.bp
- service/Android.bp
- tests/common/Android.bp
- tests/deflake/Android.bp
- tests/integration/Android.bp
- tests/smoketest/Android.bp
- tests/unit/Android.bp
- tests/unit/jni/Android.bp
Modified Lint mapping for:
- framework/lint-baseline.xml
- service/lint-baseline.xml

BUG: 186628461
TEST: TH
Merged-In: Ie82d0fb34bda77543e31c82660c6f315efa87f62
Change-Id: I3c2563d4ae4e3715d0c6270344ba8f7ef067872f
This commit is contained in:
Baligh Uddin
2021-05-24 03:50:01 +00:00
394 changed files with 94776 additions and 2 deletions

View File

@@ -31,5 +31,22 @@
"name": "CtsNetTestCasesLatestSdk[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex]",
"keywords": ["sim"]
}
],
"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"
}
]
}

View File

@@ -21,7 +21,6 @@ java_sdk_library {
name: "framework-tethering",
defaults: ["framework-module-defaults"],
impl_library_visibility: [
"//frameworks/base/packages/Tethering:__subpackages__",
"//packages/modules/Connectivity/Tethering:__subpackages__",
],
@@ -30,7 +29,7 @@ java_sdk_library {
stub_only_libs: ["framework-connectivity.stubs.module_lib"],
aidl: {
include_dirs: [
"frameworks/base/packages/Connectivity/framework/aidl-export",
"packages/modules/Connectivity/framework/aidl-export",
],
},

161
framework/Android.bp Normal file
View File

@@ -0,0 +1,161 @@
//
// 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
default_applicable_licenses: ["Android-Apache-2.0"],
}
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",
],
}

View File

@@ -0,0 +1,19 @@
/*
* 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;

View File

@@ -0,0 +1,21 @@
/**
*
* 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;

View File

@@ -0,0 +1,19 @@
/**
* 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;

View File

@@ -0,0 +1,19 @@
/*
* 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;

View File

@@ -0,0 +1,22 @@
/**
*
* 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;

View File

@@ -0,0 +1,19 @@
/*
* 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;

View File

@@ -0,0 +1,21 @@
/**
*
* 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;

View File

@@ -0,0 +1,20 @@
/*
**
** 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;

View File

@@ -0,0 +1,20 @@
/**
*
* 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;

View File

@@ -0,0 +1,20 @@
/*
**
** 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;

View File

@@ -0,0 +1,19 @@
/*
* 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;

View File

@@ -0,0 +1,21 @@
/*
**
** 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;

View File

@@ -0,0 +1,19 @@
/**
* 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;

View File

@@ -0,0 +1,20 @@
/**
* 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;

View File

@@ -0,0 +1,20 @@
/**
* 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;

View File

@@ -0,0 +1,19 @@
/*
* 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;

View File

@@ -0,0 +1,21 @@
/*
**
** 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;

View File

@@ -0,0 +1,21 @@
/*
**
** 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;

View File

@@ -0,0 +1,21 @@
/*
**
** 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;

View File

@@ -0,0 +1,21 @@
/*
**
** 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;

View File

@@ -0,0 +1,19 @@
/*
* 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;

View File

@@ -0,0 +1,20 @@
/*
**
** 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;

View File

@@ -0,0 +1,20 @@
/*
* 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;

View File

@@ -0,0 +1,20 @@
/*
**
** 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;

476
framework/api/current.txt Normal file
View File

@@ -0,0 +1,476 @@
// 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<android.net.CaptivePortal> 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<android.net.ConnectivityDiagnosticsManager.ConnectivityReport> 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<android.net.ConnectivityDiagnosticsManager.DataStallReport> 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<android.net.DhcpInfo> 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<? super java.util.List<java.net.InetAddress>>);
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<? super java.util.List<java.net.InetAddress>>);
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<? super byte[]>);
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<? super byte[]>);
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<T> {
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<android.net.IpPrefix> 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<android.net.LinkAddress> 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<java.net.InetAddress> getDnsServers();
method @Nullable public String getDomains();
method @Nullable public android.net.ProxyInfo getHttpProxy();
method @Nullable public String getInterfaceName();
method @NonNull public java.util.List<android.net.LinkAddress> getLinkAddresses();
method public int getMtu();
method @Nullable public android.net.IpPrefix getNat64Prefix();
method @Nullable public String getPrivateDnsServerName();
method @NonNull public java.util.List<android.net.RouteInfo> 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<java.net.InetAddress>);
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<android.net.LinkAddress>);
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<android.net.LinkProperties> 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<android.net.MacAddress> 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<android.net.Network> 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<android.net.NetworkCapabilities> 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<android.net.NetworkInfo> 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<android.net.NetworkRequest> 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<java.lang.String>);
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<android.net.ProxyInfo> 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<android.net.RouteInfo> 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 {
}
}

View File

@@ -0,0 +1,4 @@
// 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()

View File

@@ -0,0 +1,179 @@
// 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<android.net.NetworkStateSnapshot> getAllNetworkStateSnapshots();
method @Nullable public android.net.ProxyInfo getGlobalProxy();
method @NonNull public static android.util.Range<java.lang.Integer> 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<android.util.Range<java.lang.Integer>>);
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<java.lang.String> 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<java.lang.Integer> 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<java.lang.Integer> 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<java.lang.String>);
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<java.lang.Integer>);
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<java.lang.Integer>);
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<android.util.Range<java.lang.Integer>> 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<android.util.Range<java.lang.Integer>>);
}
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<android.util.Range<java.lang.Integer>>);
}
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<android.net.TestNetworkInterface> 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<android.net.LinkAddress>);
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<android.net.TestNetworkSpecifier> 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<android.net.VpnTransportInfo> CREATOR;
}
}

View File

@@ -0,0 +1 @@
// Signature format: 2.0

11
framework/api/removed.txt Normal file
View File

@@ -0,0 +1,11 @@
// 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);
}
}

View File

@@ -0,0 +1,505 @@
// 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<android.net.CaptivePortalData> 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<android.net.IpConfiguration> 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<java.net.InetAddress> getAddresses();
method @NonNull public java.util.List<java.lang.String> getAllInterfaceNames();
method @NonNull public java.util.List<android.net.LinkAddress> getAllLinkAddresses();
method @NonNull public java.util.List<android.net.RouteInfo> getAllRoutes();
method @Nullable public android.net.Uri getCaptivePortalApiUrl();
method @Nullable public android.net.CaptivePortalData getCaptivePortalData();
method @NonNull public java.util.List<java.net.InetAddress> getPcscfServers();
method @Nullable public String getTcpBufferSizes();
method @NonNull public java.util.List<java.net.InetAddress> 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<java.net.InetAddress>);
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<java.net.InetAddress>);
}
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<android.net.NattKeepalivePacketData> 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<android.net.Network>);
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<android.net.NetworkAgentConfig> 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<java.lang.Integer> 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<java.lang.Integer>);
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<java.lang.Integer>);
}
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<android.net.NetworkScore> 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<java.lang.String,java.lang.Integer> getNetworkPreferences();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.OemNetworkPreferences> 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<android.net.QosSession> 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<android.net.QosSocketInfo> 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<java.net.InetAddress> 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<android.net.RouteInfo> getRoutes(@Nullable String);
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.StaticIpConfiguration> 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<java.net.InetAddress>);
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<android.net.TcpKeepalivePacketData> 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<android.net.apf.ApfCapabilities> CREATOR;
field public final int apfPacketFormat;
field public final int apfVersionSupported;
field public final int maximumApfProgramSize;
}
}

View File

@@ -0,0 +1 @@
// Baseline format: 1.0

View File

@@ -0,0 +1 @@
// Signature format: 2.0

View File

@@ -0,0 +1,2 @@
rule com.android.net.module.util.** android.net.connectivity.framework.util.@1
rule android.net.NetworkFactory* android.net.connectivity.framework.NetworkFactory@1

View File

@@ -0,0 +1,271 @@
/*
* 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 <android/file_descriptor_jni.h>
#include <android/multinetwork.h>
#include <linux/filter.h>
#include <linux/tcp.h>
#include <netinet/in.h>
#include <string.h>
#include <DnsProxydProtocol.h> // NETID_USE_LOCAL_NAMESERVERS
#include <nativehelper/JNIPlatformHelp.h>
#include <utils/Log.h>
#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 <typename T>
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<T>(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<jbyte*>(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<jbyte*>(buf));
}
jclass class_DnsResponse = env->FindClass("android/net/DnsResolver$DnsResponse");
jmethodID ctor = env->GetMethodID(class_DnsResponse, "<init>", "([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<jlong>(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, "<init>", "(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

38
framework/jni/onload.cpp Normal file
View File

@@ -0,0 +1,38 @@
/*
* 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 <nativehelper/JNIHelp.h>
#include <log/log.h>
namespace android {
int register_android_net_NetworkUtils(JNIEnv* env);
extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
JNIEnv *env;
if (vm->GetEnv(reinterpret_cast<void**>(&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;
}
};

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<issues format="5" by="lint 4.1.0" client="cli" variant="all" version="4.1.0">
<issue
id="NewApi"
message="Call requires API level 31 (current min is 30): `new android.net.ParseException`"
errorLine1=" ParseException pe = new ParseException(e.reason, e.getCause());"
errorLine2=" ~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Connectivity/framework/src/android/net/DnsResolver.java"
line="301"
column="37"/>
</issue>
<issue
id="NewApi"
message="Class requires API level 31 (current min is 30): `android.telephony.TelephonyCallback`"
errorLine1=" protected class ActiveDataSubscriptionIdListener extends TelephonyCallback"
errorLine2=" ~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Connectivity/framework/src/android/net/util/MultinetworkPolicyTracker.java"
line="96"
column="62"/>
</issue>
<issue
id="NewApi"
message="Class requires API level 31 (current min is 30): `android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener`"
errorLine1=" implements TelephonyCallback.ActiveDataSubscriptionIdListener {"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Connectivity/framework/src/android/net/util/MultinetworkPolicyTracker.java"
line="97"
column="24"/>
</issue>
<issue
id="NewApi"
message="Call requires API level 31 (current min is 30): `android.telephony.TelephonyManager#registerTelephonyCallback`"
errorLine1=" ctx.getSystemService(TelephonyManager.class).registerTelephonyCallback("
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Connectivity/framework/src/android/net/util/MultinetworkPolicyTracker.java"
line="126"
column="54"/>
</issue>
</issues>

View File

@@ -0,0 +1,170 @@
/*
* 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<CaptivePortal> CREATOR
= new Parcelable.Creator<CaptivePortal>() {
@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) {
}
}

View File

@@ -0,0 +1,379 @@
/*
* 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<CaptivePortalData> CREATOR = new Creator<CaptivePortalData>() {
@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
+ "}";
}
}

View File

@@ -0,0 +1,20 @@
/*
**
** 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;

View File

@@ -0,0 +1,83 @@
/*
* 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<ConnectionInfo> CREATOR = new Creator<ConnectionInfo>() {
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];
}
};
}

View File

@@ -0,0 +1,51 @@
/*
* 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 {}
}

View File

@@ -0,0 +1,778 @@
/*
* 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.
*
* <p>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.
*
* <p>The primary responsibilities of this class are to:
*
* <ul>
* <li>Allow permissioned applications to register and unregister callbacks for network event
* notifications
* <li>Invoke callbacks for network event notifications, including:
* <ul>
* <li>Network validations
* <li>Data stalls
* <li>Connectivity reports from applications
* </ul>
* </ul>
*/
public class ConnectivityDiagnosticsManager {
/** @hide */
@VisibleForTesting
public static final Map<ConnectivityDiagnosticsCallback, ConnectivityDiagnosticsBinder>
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.
*
* <p>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.
*
* <p>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.
*
* <p>These probes may have failed or may be incomplete at the time of this report.
*
* <p>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.
*
* <p>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<ConnectivityReport> CREATOR =
new Creator<ConnectivityReport>() {
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.
*
* <p>This key will be included if the data stall detection method is
* {@link #DETECTION_METHOD_TCP_METRICS}.
*
* <p>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.
*
* <p>This key will be included if the data stall detection method is
* {@link #DETECTION_METHOD_TCP_METRICS}.
*
* <p>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.
*
* <p>The consecutive count will be reset any time a DNS response is received.
*
* <p>This key will be included if the data stall detection method is
* {@link #DETECTION_METHOD_DNS_EVENTS}.
*
* <p>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.
*
* <p>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.
*
* <p>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<DataStallReport> CREATOR =
new Creator<DataStallReport>() {
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.
*
* <p>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.
*
* <p>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.
*
* <p>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:
*
* <ul>
* <li>Carrier apps with active subscriptions
* <li>Active VPNs
* <li>WiFi Suggesters
* </ul>
*
* <p>Callbacks registered by apps not meeting the above criteria will not be invoked.
*
* <p>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).
*
* <p>Each register() call <b>MUST</b> use a ConnectivityDiagnosticsCallback instance that is
* not currently registered. If a ConnectivityDiagnosticsCallback instance is registered with
* multiple NetworkRequests, an IllegalArgumentException will be thrown.
*
* <p>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.
*
* <p>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();
}
}
}

View File

@@ -0,0 +1,78 @@
/*
* 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)
);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,108 @@
/*
* 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<ResolveInfo> 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();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,56 @@
/*
* 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();
}
}

View File

@@ -0,0 +1,105 @@
/*
* 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<DhcpInfo> CREATOR =
new Creator<DhcpInfo>() {
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];
}
};
}

View File

@@ -0,0 +1,577 @@
/*
* 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 <T> The type of the answer
*/
public interface Callback<T> {
/**
* 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 <T> 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<? super byte[]> 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<? super byte[]> 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<byte[]> {
private final List<InetAddress> mAllAnswers;
private final Network mNetwork;
private int mRcode;
private DnsException mDnsException;
private final Callback<? super List<InetAddress>> mUserCallback;
private final int mTargetAnswerCount;
private int mReceivedAnswerCount = 0;
InetAddressAnswerAccumulator(@NonNull Network network, int size,
@NonNull Callback<? super List<InetAddress>> 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<? super List<InetAddress>> 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<? super List<InetAddress>> 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<? super byte[]> 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<InetAddress> getAddresses() {
final List<InetAddress> results = new ArrayList<InetAddress>();
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;
}
}
}

View File

@@ -0,0 +1,45 @@
/*
* 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;
}
}

View File

@@ -0,0 +1,26 @@
/**
* 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);
}

View File

@@ -0,0 +1,28 @@
/**
*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing 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);
}

View File

@@ -0,0 +1,229 @@
/**
* 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<NetworkStateSnapshot> 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);
}

View File

@@ -0,0 +1,24 @@
/* 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();
}

View File

@@ -0,0 +1,51 @@
/**
* 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();
}

View File

@@ -0,0 +1,46 @@
/**
* 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<Network> 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);
}

View File

@@ -0,0 +1,61 @@
/*
* 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);
}

View File

@@ -0,0 +1,23 @@
/**
*
* 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();
}

View File

@@ -0,0 +1,37 @@
/*
* 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);
}

View File

@@ -0,0 +1,34 @@
/**
* 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();
}

View File

@@ -0,0 +1,39 @@
/**
* 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);
}

View File

@@ -0,0 +1,88 @@
/*
* 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);
}
}
}

View File

@@ -0,0 +1,65 @@
/*
* 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"}).
*
* <p>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.
*
* <p>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"}).
*
* <p>See {@link #isNumericAddress(String)} (String)} for a definition as to what constitutes a
* numeric address.
*
* <p>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);
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing 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;
}
}

View File

@@ -0,0 +1,223 @@
/*
* 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<IpConfiguration> CREATOR =
new Creator<IpConfiguration>() {
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];
}
};
}

View File

@@ -0,0 +1,303 @@
/*
* 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:
*
* <ul>
* <li>A starting IP address (IPv4 or IPv6). This is the first IP address of the prefix.
* <li>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.
* </ul>
*
* For example, the prefix <code>192.0.2.0/24</code> covers the 256 IPv4 addresses from
* <code>192.0.2.0</code> to <code>192.0.2.255</code>, inclusive, and the prefix
* <code>2001:db8:1:2</code> covers the 2^64 IPv6 addresses from <code>2001:db8:1:2::</code> to
* <code>2001:db8:1:2:ffff:ffff:ffff:ffff</code>, 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 &gt;= 0 and &lt;= (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 &gt;= 0 and &lt;= (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<InetAddress, Integer> 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<IpPrefix> lengthComparator() {
return new Comparator<IpPrefix>() {
@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<IpPrefix> CREATOR =
new Creator<IpPrefix>() {
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];
}
};
}

View File

@@ -0,0 +1,119 @@
/*
* 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();
}
}

View File

@@ -0,0 +1,549 @@
/*
* 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:
* <ul>
* <li>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.
* <li>Address flags: A bitmask of {@code OsConstants.IFA_F_*} values representing properties
* of the address (e.g., {@code android.system.OsConstants.IFA_F_OPTIMISTIC}).
* <li>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}).
* </ul>
*/
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 &gt;= 0 and &lt;= (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 &gt;= 0 and &lt;= (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 &gt;= 0 and &lt;= (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<InetAddress, Integer> 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<LinkAddress> CREATOR =
new Creator<LinkAddress>() {
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];
}
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,400 @@
/*
* 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.
*
* <p>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<MacAddress> CREATOR =
new Parcelable.Creator<MacAddress>() {
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;
}
}
}

View File

@@ -0,0 +1,144 @@
/*
* 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<NattKeepalivePacketData> CREATOR =
new Parcelable.Creator<NattKeepalivePacketData>() {
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());
}
}

View File

@@ -0,0 +1,77 @@
/*
* 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();
}
});
}
}

View File

@@ -0,0 +1,530 @@
/*
* 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<Network> CREATOR =
new Creator<Network>() {
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);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,505 @@
/*
* 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 :
* <ul>
* <li>For cellular agents, the APN name.</li>
* <li>For ethernet agents, the interface name.</li>
* </ul>
* @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<NetworkAgentConfig> CREATOR =
new Creator<NetworkAgentConfig>() {
@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];
}
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,80 @@
/*
* 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);
}
}

View File

@@ -0,0 +1,625 @@
/*
* 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.
* <p>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:
* <br/><br/>
* <table>
* <tr><td><b>Detailed state</b></td><td><b>Coarse-grained state</b></td></tr>
* <tr><td><code>IDLE</code></td><td><code>DISCONNECTED</code></td></tr>
* <tr><td><code>SCANNING</code></td><td><code>DISCONNECTED</code></td></tr>
* <tr><td><code>CONNECTING</code></td><td><code>CONNECTING</code></td></tr>
* <tr><td><code>AUTHENTICATING</code></td><td><code>CONNECTING</code></td></tr>
* <tr><td><code>OBTAINING_IPADDR</code></td><td><code>CONNECTING</code></td></tr>
* <tr><td><code>VERIFYING_POOR_LINK</code></td><td><code>CONNECTING</code></td></tr>
* <tr><td><code>CAPTIVE_PORTAL_CHECK</code></td><td><code>CONNECTING</code></td></tr>
* <tr><td><code>CONNECTED</code></td><td><code>CONNECTED</code></td></tr>
* <tr><td><code>SUSPENDED</code></td><td><code>SUSPENDED</code></td></tr>
* <tr><td><code>DISCONNECTING</code></td><td><code>DISCONNECTING</code></td></tr>
* <tr><td><code>DISCONNECTED</code></td><td><code>DISCONNECTED</code></td></tr>
* <tr><td><code>FAILED</code></td><td><code>DISCONNECTED</code></td></tr>
* <tr><td><code>BLOCKED</code></td><td><code>DISCONNECTED</code></td></tr>
* </table>
*
* @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 <code>DetailedState</code>.
*/
private static final EnumMap<DetailedState, State> stateMap =
new EnumMap<DetailedState, State>(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.
* <p>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
* <ul>
* <li>The device is out of the coverage area for any network of this type.</li>
* <li>The device is on a network other than the home network (i.e., roaming), and
* data roaming has been disabled.</li>
* <li>The device's radio is turned off, e.g., because airplane mode is enabled.</li>
* </ul>
* 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<NetworkInfo> CREATOR = new Creator<NetworkInfo>() {
@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];
}
};
}

View File

@@ -0,0 +1,332 @@
/*
* 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<NetworkOfferCallbackProxy> 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);
}
}

View File

@@ -0,0 +1,32 @@
/*
* 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");
}
}

View File

@@ -0,0 +1,753 @@
/*
* 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<Integer> 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<Integer>}, 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<Range<Integer>> uids) {
mNetworkCapabilities.setUids(uids);
return this;
}
/**
* Add a capability that must not exist in the requested network.
* <p>
* 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.
* </p>
* If the {@code networkSpecifier} is provided, it shall be interpreted as follows:
* <ul>
* <li>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.
* <li>If the value is an ethernet interface name, it will be treated as such.
* <li>For all other cases, the behavior is undefined.
* </ul>
*
* @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.
* </p>
*
* @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.
* <p>
* 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.
*
* <p>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.
* <p>
* 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.
*
* <p>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<Integer> 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<NetworkRequest> CREATOR =
new Creator<NetworkRequest>() {
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();
}
}

View File

@@ -0,0 +1,328 @@
/*
* 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<NetworkScore> 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);
}
}
}

View File

@@ -0,0 +1,130 @@
/*
* 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<NetworkState> CREATOR = new Creator<NetworkState>() {
@Override
public NetworkState createFromParcel(Parcel in) {
return new NetworkState(in);
}
@Override
public NetworkState[] newArray(int size) {
return new NetworkState[size];
}
};
}

View File

@@ -0,0 +1,429 @@
/*
* 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<InetAddress, Integer> 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<InetAddress, Integer>(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<InetAddress, Integer> 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<InetAddress, Integer>(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<InetAddress, Integer>(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<IpPrefix> deduplicatePrefixSet(final TreeSet<IpPrefix> src) {
final TreeSet<IpPrefix> 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<IpPrefix> 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<IpPrefix> 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;
}
}

View File

@@ -0,0 +1,276 @@
/*
* 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<String, Integer> 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<String, Integer> convertToUnmodifiableMap(@NonNull final Bundle bundle) {
final Map<String, Integer> 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<OemNetworkPreferences> CREATOR =
new Parcelable.Creator<OemNetworkPreferences>() {
@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()));
}
};
}

View File

@@ -0,0 +1,37 @@
/*
* 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;
}
}

View File

@@ -0,0 +1,370 @@
/*
* 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<String> 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<ProxyInfo> CREATOR =
new Creator<ProxyInfo>() {
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];
}
};
}

View File

@@ -0,0 +1,91 @@
/*
* 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}.
*
* <p>
* <br/>
* The callback will no longer receive calls if any of the following takes place:
* <ol>
* <li>{@link ConnectivityManager#unregisterQosCallback(QosCallback)} is called with the same
* callback instance.</li>
* <li>{@link QosCallback#onError(QosCallbackException)} is called.</li>
* <li>A network specific issue occurs. eg. Congestion on a carrier network.</li>
* <li>The network registered with the callback has no associated QoS providers</li>
* </ul>
* {@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.
*
* <p>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.
* <p>
* 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.
* <p>
* 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();
}
}
}

View File

@@ -0,0 +1,148 @@
/*
* 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}.
* <p/>
* 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.
* <p/>
* There are no synchronization guarantees on exactly when the callback will stop receiving
* messages.
*/
void stopReceivingMessages() {
mCallback = null;
}
}

View File

@@ -0,0 +1,110 @@
/*
* 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);
}
}

View File

@@ -0,0 +1,86 @@
/*
* 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);
}

View File

@@ -0,0 +1,113 @@
/*
* 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.
* <p/>
* Specifically leveraged when transferring {@link QosFilter} from
* {@link com.android.server.ConnectivityService} to {@link NetworkAgent} when the filter is first
* registered.
* <p/>
* 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.
* <p/>
* 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<QosFilterParcelable> CREATOR = new Creator<QosFilterParcelable>() {
@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);
}
}

View File

@@ -0,0 +1,142 @@
/*
* 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.
* <p/>
* 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.
* <p/>
* 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<QosSession> CREATOR = new Creator<QosSession>() {
@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);
}
}

View File

@@ -0,0 +1,30 @@
/*
* 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 {
}

View File

@@ -0,0 +1,179 @@
/*
* 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()}.
* <p>
* 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);
}
}

View File

@@ -0,0 +1,190 @@
/*
* 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<QosSocketInfo> CREATOR =
new Parcelable.Creator<QosSocketInfo>() {
@NonNull
@Override
public QosSocketInfo createFromParcel(final Parcel in) {
return new QosSocketInfo(in);
}
@NonNull
@Override
public QosSocketInfo[] newArray(final int size) {
return new QosSocketInfo[size];
}
};
}

View File

@@ -0,0 +1,659 @@
/*
* 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.
* <p>
* This is used both to describe static network configuration and live network
* configuration information.
*
* A route contains three pieces of information:
* <ul>
* <li>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.
* <li>a gateway {@link InetAddress} indicating the next hop to use. If this is {@code null} it
* indicates a directly-connected route.
* <li>an interface (which may be unspecified).
* </ul>
* 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 <code>0.0.0.0</code>
* if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
* route <code>::/0</code> if gateway is an instance of
* {@link Inet6Address}.
* <p>
* 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 <code>0.0.0.0</code>
* if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
* route <code>::/0</code> if gateway is an instance of
* {@link Inet6Address}.
* <p>
* 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 <code>0.0.0.0</code>
* if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
* route <code>::/0</code> if gateway is an instance of {@link Inet6Address}.
* <p>
* 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 <code>0.0.0.0</code>
* if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
* route <code>::/0</code> if gateway is an instance of {@link Inet6Address}.
* <p>
* 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<RouteInfo> 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 <code>RouteInfo</code> 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<RouteInfo> CREATOR =
new Creator<RouteInfo>() {
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];
}
};
}

Some files were not shown because too many files have changed in this diff Show More