diff --git a/core/java/android/net/CaptivePortal.java b/framework/src/android/net/CaptivePortal.java similarity index 100% rename from core/java/android/net/CaptivePortal.java rename to framework/src/android/net/CaptivePortal.java diff --git a/framework/src/android/net/CaptivePortalData.aidl b/framework/src/android/net/CaptivePortalData.aidl new file mode 100644 index 0000000000..1d57ee7591 --- /dev/null +++ b/framework/src/android/net/CaptivePortalData.aidl @@ -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; diff --git a/core/java/android/net/CaptivePortalData.java b/framework/src/android/net/CaptivePortalData.java similarity index 100% rename from core/java/android/net/CaptivePortalData.java rename to framework/src/android/net/CaptivePortalData.java diff --git a/framework/src/android/net/ConnectionInfo.aidl b/framework/src/android/net/ConnectionInfo.aidl new file mode 100644 index 0000000000..07faf8bbbe --- /dev/null +++ b/framework/src/android/net/ConnectionInfo.aidl @@ -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; diff --git a/core/java/android/net/ConnectionInfo.java b/framework/src/android/net/ConnectionInfo.java similarity index 100% rename from core/java/android/net/ConnectionInfo.java rename to framework/src/android/net/ConnectionInfo.java diff --git a/framework/src/android/net/ConnectivityDiagnosticsManager.aidl b/framework/src/android/net/ConnectivityDiagnosticsManager.aidl new file mode 100644 index 0000000000..82ba0ca113 --- /dev/null +++ b/framework/src/android/net/ConnectivityDiagnosticsManager.aidl @@ -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; \ No newline at end of file diff --git a/core/java/android/net/ConnectivityDiagnosticsManager.java b/framework/src/android/net/ConnectivityDiagnosticsManager.java similarity index 100% rename from core/java/android/net/ConnectivityDiagnosticsManager.java rename to framework/src/android/net/ConnectivityDiagnosticsManager.java diff --git a/core/java/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java similarity index 100% rename from core/java/android/net/ConnectivityManager.java rename to framework/src/android/net/ConnectivityManager.java diff --git a/framework/src/android/net/ConnectivityMetricsEvent.aidl b/framework/src/android/net/ConnectivityMetricsEvent.aidl new file mode 100644 index 0000000000..1c541dc4c8 --- /dev/null +++ b/framework/src/android/net/ConnectivityMetricsEvent.aidl @@ -0,0 +1,20 @@ +/* + * 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; + +/** {@hide} */ +parcelable ConnectivityMetricsEvent; diff --git a/core/java/android/net/ConnectivityThread.java b/framework/src/android/net/ConnectivityThread.java similarity index 100% rename from core/java/android/net/ConnectivityThread.java rename to framework/src/android/net/ConnectivityThread.java diff --git a/framework/src/android/net/DhcpInfo.aidl b/framework/src/android/net/DhcpInfo.aidl new file mode 100644 index 0000000000..29cd21fe76 --- /dev/null +++ b/framework/src/android/net/DhcpInfo.aidl @@ -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; diff --git a/core/java/android/net/DhcpInfo.java b/framework/src/android/net/DhcpInfo.java similarity index 100% rename from core/java/android/net/DhcpInfo.java rename to framework/src/android/net/DhcpInfo.java diff --git a/core/java/android/net/DnsResolver.java b/framework/src/android/net/DnsResolver.java similarity index 100% rename from core/java/android/net/DnsResolver.java rename to framework/src/android/net/DnsResolver.java diff --git a/framework/src/android/net/ICaptivePortal.aidl b/framework/src/android/net/ICaptivePortal.aidl new file mode 100644 index 0000000000..fe21905c70 --- /dev/null +++ b/framework/src/android/net/ICaptivePortal.aidl @@ -0,0 +1,27 @@ +/** + * 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); + void logEvent(int eventId, String packageName); +} diff --git a/framework/src/android/net/IConnectivityDiagnosticsCallback.aidl b/framework/src/android/net/IConnectivityDiagnosticsCallback.aidl new file mode 100644 index 0000000000..82b64a9280 --- /dev/null +++ b/framework/src/android/net/IConnectivityDiagnosticsCallback.aidl @@ -0,0 +1,28 @@ +/** + * + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.net.ConnectivityDiagnosticsManager; +import android.net.Network; + +/** @hide */ +oneway interface IConnectivityDiagnosticsCallback { + void onConnectivityReportAvailable(in ConnectivityDiagnosticsManager.ConnectivityReport report); + void onDataStallSuspected(in ConnectivityDiagnosticsManager.DataStallReport report); + void onNetworkConnectivityReported(in Network n, boolean hasConnectivity); +} \ No newline at end of file diff --git a/core/java/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl similarity index 100% rename from core/java/android/net/IConnectivityManager.aidl rename to framework/src/android/net/IConnectivityManager.aidl diff --git a/framework/src/android/net/ISocketKeepaliveCallback.aidl b/framework/src/android/net/ISocketKeepaliveCallback.aidl new file mode 100644 index 0000000000..020fbcacbf --- /dev/null +++ b/framework/src/android/net/ISocketKeepaliveCallback.aidl @@ -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(); +} diff --git a/framework/src/android/net/ITestNetworkManager.aidl b/framework/src/android/net/ITestNetworkManager.aidl new file mode 100644 index 0000000000..2a863adde5 --- /dev/null +++ b/framework/src/android/net/ITestNetworkManager.aidl @@ -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); +} diff --git a/core/java/android/net/InetAddresses.java b/framework/src/android/net/InetAddresses.java similarity index 100% rename from core/java/android/net/InetAddresses.java rename to framework/src/android/net/InetAddresses.java diff --git a/framework/src/android/net/InterfaceConfiguration.aidl b/framework/src/android/net/InterfaceConfiguration.aidl new file mode 100644 index 0000000000..8aa5e34528 --- /dev/null +++ b/framework/src/android/net/InterfaceConfiguration.aidl @@ -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 InterfaceConfiguration; diff --git a/core/java/android/net/InvalidPacketException.java b/framework/src/android/net/InvalidPacketException.java similarity index 100% rename from core/java/android/net/InvalidPacketException.java rename to framework/src/android/net/InvalidPacketException.java diff --git a/framework/src/android/net/IpConfiguration.aidl b/framework/src/android/net/IpConfiguration.aidl new file mode 100644 index 0000000000..7a30f0e79c --- /dev/null +++ b/framework/src/android/net/IpConfiguration.aidl @@ -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; diff --git a/core/java/android/net/IpConfiguration.java b/framework/src/android/net/IpConfiguration.java similarity index 100% rename from core/java/android/net/IpConfiguration.java rename to framework/src/android/net/IpConfiguration.java diff --git a/framework/src/android/net/IpPrefix.aidl b/framework/src/android/net/IpPrefix.aidl new file mode 100644 index 0000000000..0d70f2a1ed --- /dev/null +++ b/framework/src/android/net/IpPrefix.aidl @@ -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). IpPrefix is also used in cpp but only as non-stable aidl. +@JavaOnlyStableParcelable parcelable IpPrefix cpp_header "binder/IpPrefix.h"; diff --git a/core/java/android/net/IpPrefix.java b/framework/src/android/net/IpPrefix.java similarity index 100% rename from core/java/android/net/IpPrefix.java rename to framework/src/android/net/IpPrefix.java diff --git a/framework/src/android/net/KeepalivePacketData.aidl b/framework/src/android/net/KeepalivePacketData.aidl new file mode 100644 index 0000000000..d456b53fd1 --- /dev/null +++ b/framework/src/android/net/KeepalivePacketData.aidl @@ -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; diff --git a/core/java/android/net/KeepalivePacketData.java b/framework/src/android/net/KeepalivePacketData.java similarity index 100% rename from core/java/android/net/KeepalivePacketData.java rename to framework/src/android/net/KeepalivePacketData.java diff --git a/framework/src/android/net/LinkAddress.aidl b/framework/src/android/net/LinkAddress.aidl new file mode 100644 index 0000000000..9c804db08d --- /dev/null +++ b/framework/src/android/net/LinkAddress.aidl @@ -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; + diff --git a/core/java/android/net/LinkAddress.java b/framework/src/android/net/LinkAddress.java similarity index 100% rename from core/java/android/net/LinkAddress.java rename to framework/src/android/net/LinkAddress.java diff --git a/framework/src/android/net/LinkProperties.aidl b/framework/src/android/net/LinkProperties.aidl new file mode 100644 index 0000000000..a8b3c7b039 --- /dev/null +++ b/framework/src/android/net/LinkProperties.aidl @@ -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; diff --git a/core/java/android/net/LinkProperties.java b/framework/src/android/net/LinkProperties.java similarity index 100% rename from core/java/android/net/LinkProperties.java rename to framework/src/android/net/LinkProperties.java diff --git a/framework/src/android/net/MacAddress.aidl b/framework/src/android/net/MacAddress.aidl new file mode 100644 index 0000000000..48a18a7ac8 --- /dev/null +++ b/framework/src/android/net/MacAddress.aidl @@ -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; diff --git a/core/java/android/net/MacAddress.java b/framework/src/android/net/MacAddress.java similarity index 100% rename from core/java/android/net/MacAddress.java rename to framework/src/android/net/MacAddress.java diff --git a/core/java/android/net/NattKeepalivePacketData.java b/framework/src/android/net/NattKeepalivePacketData.java similarity index 100% rename from core/java/android/net/NattKeepalivePacketData.java rename to framework/src/android/net/NattKeepalivePacketData.java diff --git a/core/java/android/net/NattSocketKeepalive.java b/framework/src/android/net/NattSocketKeepalive.java similarity index 100% rename from core/java/android/net/NattSocketKeepalive.java rename to framework/src/android/net/NattSocketKeepalive.java diff --git a/framework/src/android/net/Network.aidl b/framework/src/android/net/Network.aidl new file mode 100644 index 0000000000..05622025bf --- /dev/null +++ b/framework/src/android/net/Network.aidl @@ -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; diff --git a/core/java/android/net/Network.java b/framework/src/android/net/Network.java similarity index 100% rename from core/java/android/net/Network.java rename to framework/src/android/net/Network.java diff --git a/core/java/android/net/NetworkAgent.java b/framework/src/android/net/NetworkAgent.java similarity index 100% rename from core/java/android/net/NetworkAgent.java rename to framework/src/android/net/NetworkAgent.java diff --git a/framework/src/android/net/NetworkAgentConfig.aidl b/framework/src/android/net/NetworkAgentConfig.aidl new file mode 100644 index 0000000000..cb70bdd312 --- /dev/null +++ b/framework/src/android/net/NetworkAgentConfig.aidl @@ -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; diff --git a/core/java/android/net/NetworkAgentConfig.java b/framework/src/android/net/NetworkAgentConfig.java similarity index 100% rename from core/java/android/net/NetworkAgentConfig.java rename to framework/src/android/net/NetworkAgentConfig.java diff --git a/framework/src/android/net/NetworkCapabilities.aidl b/framework/src/android/net/NetworkCapabilities.aidl new file mode 100644 index 0000000000..01d328605d --- /dev/null +++ b/framework/src/android/net/NetworkCapabilities.aidl @@ -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; + diff --git a/core/java/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java similarity index 100% rename from core/java/android/net/NetworkCapabilities.java rename to framework/src/android/net/NetworkCapabilities.java diff --git a/core/java/android/net/NetworkConfig.java b/framework/src/android/net/NetworkConfig.java similarity index 100% rename from core/java/android/net/NetworkConfig.java rename to framework/src/android/net/NetworkConfig.java diff --git a/framework/src/android/net/NetworkInfo.aidl b/framework/src/android/net/NetworkInfo.aidl new file mode 100644 index 0000000000..f501873029 --- /dev/null +++ b/framework/src/android/net/NetworkInfo.aidl @@ -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; diff --git a/core/java/android/net/NetworkInfo.java b/framework/src/android/net/NetworkInfo.java similarity index 100% rename from core/java/android/net/NetworkInfo.java rename to framework/src/android/net/NetworkInfo.java diff --git a/core/java/android/net/NetworkProvider.java b/framework/src/android/net/NetworkProvider.java similarity index 100% rename from core/java/android/net/NetworkProvider.java rename to framework/src/android/net/NetworkProvider.java diff --git a/framework/src/android/net/NetworkRequest.aidl b/framework/src/android/net/NetworkRequest.aidl new file mode 100644 index 0000000000..508defc6b4 --- /dev/null +++ b/framework/src/android/net/NetworkRequest.aidl @@ -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; + diff --git a/core/java/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java similarity index 100% rename from core/java/android/net/NetworkRequest.java rename to framework/src/android/net/NetworkRequest.java diff --git a/core/java/android/net/NetworkUtils.java b/framework/src/android/net/NetworkUtils.java similarity index 100% rename from core/java/android/net/NetworkUtils.java rename to framework/src/android/net/NetworkUtils.java diff --git a/framework/src/android/net/PacProxySelector.java b/framework/src/android/net/PacProxySelector.java new file mode 100644 index 0000000000..326943a27d --- /dev/null +++ b/framework/src/android/net/PacProxySelector.java @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.os.ServiceManager; +import android.util.Log; + +import com.android.net.IProxyService; + +import com.google.android.collect.Lists; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.MalformedURLException; +import java.net.Proxy; +import java.net.Proxy.Type; +import java.net.ProxySelector; +import java.net.SocketAddress; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; + +/** + * @hide + */ +public class PacProxySelector extends ProxySelector { + private static final String TAG = "PacProxySelector"; + public static final String PROXY_SERVICE = "com.android.net.IProxyService"; + private static final String SOCKS = "SOCKS "; + private static final String PROXY = "PROXY "; + + private IProxyService mProxyService; + private final List mDefaultList; + + public PacProxySelector() { + mProxyService = IProxyService.Stub.asInterface( + ServiceManager.getService(PROXY_SERVICE)); + if (mProxyService == null) { + // Added because of b10267814 where mako is restarting. + Log.e(TAG, "PacProxyInstaller: no proxy service"); + } + mDefaultList = Lists.newArrayList(java.net.Proxy.NO_PROXY); + } + + @Override + public List select(URI uri) { + if (mProxyService == null) { + mProxyService = IProxyService.Stub.asInterface( + ServiceManager.getService(PROXY_SERVICE)); + } + if (mProxyService == null) { + Log.e(TAG, "select: no proxy service return NO_PROXY"); + return Lists.newArrayList(java.net.Proxy.NO_PROXY); + } + String response = null; + String urlString; + try { + // Strip path and username/password from URI so it's not visible to PAC script. The + // path often contains credentials the app does not want exposed to a potentially + // malicious PAC script. + if (!"http".equalsIgnoreCase(uri.getScheme())) { + uri = new URI(uri.getScheme(), null, uri.getHost(), uri.getPort(), "/", null, null); + } + urlString = uri.toURL().toString(); + } catch (URISyntaxException e) { + urlString = uri.getHost(); + } catch (MalformedURLException e) { + urlString = uri.getHost(); + } + try { + response = mProxyService.resolvePacFile(uri.getHost(), urlString); + } catch (Exception e) { + Log.e(TAG, "Error resolving PAC File", e); + } + if (response == null) { + return mDefaultList; + } + + return parseResponse(response); + } + + private static List parseResponse(String response) { + String[] split = response.split(";"); + List ret = Lists.newArrayList(); + for (String s : split) { + String trimmed = s.trim(); + if (trimmed.equals("DIRECT")) { + ret.add(java.net.Proxy.NO_PROXY); + } else if (trimmed.startsWith(PROXY)) { + Proxy proxy = proxyFromHostPort(Type.HTTP, trimmed.substring(PROXY.length())); + if (proxy != null) { + ret.add(proxy); + } + } else if (trimmed.startsWith(SOCKS)) { + Proxy proxy = proxyFromHostPort(Type.SOCKS, trimmed.substring(SOCKS.length())); + if (proxy != null) { + ret.add(proxy); + } + } + } + if (ret.size() == 0) { + ret.add(java.net.Proxy.NO_PROXY); + } + return ret; + } + + private static Proxy proxyFromHostPort(Proxy.Type type, String hostPortString) { + try { + String[] hostPort = hostPortString.split(":"); + String host = hostPort[0]; + int port = Integer.parseInt(hostPort[1]); + return new Proxy(type, InetSocketAddress.createUnresolved(host, port)); + } catch (NumberFormatException|ArrayIndexOutOfBoundsException e) { + Log.d(TAG, "Unable to parse proxy " + hostPortString + " " + e); + return null; + } + } + + @Override + public void connectFailed(URI uri, SocketAddress address, IOException failure) { + + } + +} diff --git a/framework/src/android/net/Proxy.java b/framework/src/android/net/Proxy.java new file mode 100644 index 0000000000..03b07e080a --- /dev/null +++ b/framework/src/android/net/Proxy.java @@ -0,0 +1,294 @@ +/* + * 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; + +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; +import android.compat.annotation.UnsupportedAppUsage; +import android.content.Context; +import android.os.Build; +import android.text.TextUtils; +import android.util.Log; + +import com.android.net.module.util.ProxyUtils; + +import java.net.InetSocketAddress; +import java.net.ProxySelector; +import java.net.URI; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * A convenience class for accessing the user and default proxy + * settings. + */ +public final class Proxy { + + private static final String TAG = "Proxy"; + + private static final ProxySelector sDefaultProxySelector; + + /** + * Used to notify an app that's caching the proxy that either the default + * connection has changed or any connection's proxy has changed. The new + * proxy should be queried using {@link ConnectivityManager#getDefaultProxy()}. + * + *

This is a protected intent that can only be sent by the system + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String PROXY_CHANGE_ACTION = "android.intent.action.PROXY_CHANGE"; + /** + * Intent extra included with {@link #PROXY_CHANGE_ACTION} intents. + * It describes the new proxy being used (as a {@link ProxyInfo} object). + * @deprecated Because {@code PROXY_CHANGE_ACTION} is sent whenever the proxy + * for any network on the system changes, applications should always use + * {@link ConnectivityManager#getDefaultProxy()} or + * {@link ConnectivityManager#getLinkProperties(Network)}.{@link LinkProperties#getHttpProxy()} + * to get the proxy for the Network(s) they are using. + */ + @Deprecated + public static final String EXTRA_PROXY_INFO = "android.intent.extra.PROXY_INFO"; + + /** @hide */ + public static final int PROXY_VALID = 0; + /** @hide */ + public static final int PROXY_HOSTNAME_EMPTY = 1; + /** @hide */ + public static final int PROXY_HOSTNAME_INVALID = 2; + /** @hide */ + public static final int PROXY_PORT_EMPTY = 3; + /** @hide */ + public static final int PROXY_PORT_INVALID = 4; + /** @hide */ + public static final int PROXY_EXCLLIST_INVALID = 5; + + private static ConnectivityManager sConnectivityManager = null; + + // Hostname / IP REGEX validation + // Matches blank input, ips, and domain names + private static final String NAME_IP_REGEX = + "[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*(\\.[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*)*"; + + private static final String HOSTNAME_REGEXP = "^$|^" + NAME_IP_REGEX + "$"; + + private static final Pattern HOSTNAME_PATTERN; + + private static final String EXCL_REGEX = + "[a-zA-Z0-9*]+(\\-[a-zA-Z0-9*]+)*(\\.[a-zA-Z0-9*]+(\\-[a-zA-Z0-9*]+)*)*"; + + private static final String EXCLLIST_REGEXP = "^$|^" + EXCL_REGEX + "(," + EXCL_REGEX + ")*$"; + + private static final Pattern EXCLLIST_PATTERN; + + static { + HOSTNAME_PATTERN = Pattern.compile(HOSTNAME_REGEXP); + EXCLLIST_PATTERN = Pattern.compile(EXCLLIST_REGEXP); + sDefaultProxySelector = ProxySelector.getDefault(); + } + + /** + * Return the proxy object to be used for the URL given as parameter. + * @param ctx A Context used to get the settings for the proxy host. + * @param url A URL to be accessed. Used to evaluate exclusion list. + * @return Proxy (java.net) object containing the host name. If the + * user did not set a hostname it returns the default host. + * A null value means that no host is to be used. + * {@hide} + */ + @UnsupportedAppUsage + public static final java.net.Proxy getProxy(Context ctx, String url) { + String host = ""; + if ((url != null) && !isLocalHost(host)) { + URI uri = URI.create(url); + ProxySelector proxySelector = ProxySelector.getDefault(); + + List proxyList = proxySelector.select(uri); + + if (proxyList.size() > 0) { + return proxyList.get(0); + } + } + return java.net.Proxy.NO_PROXY; + } + + + /** + * Return the proxy host set by the user. + * @param ctx A Context used to get the settings for the proxy host. + * @return String containing the host name. If the user did not set a host + * name it returns the default host. A null value means that no + * host is to be used. + * @deprecated Use standard java vm proxy values to find the host, port + * and exclusion list. This call ignores the exclusion list. + */ + @Deprecated + public static final String getHost(Context ctx) { + java.net.Proxy proxy = getProxy(ctx, null); + if (proxy == java.net.Proxy.NO_PROXY) return null; + try { + return ((InetSocketAddress)(proxy.address())).getHostName(); + } catch (Exception e) { + return null; + } + } + + /** + * Return the proxy port set by the user. + * @param ctx A Context used to get the settings for the proxy port. + * @return The port number to use or -1 if no proxy is to be used. + * @deprecated Use standard java vm proxy values to find the host, port + * and exclusion list. This call ignores the exclusion list. + */ + @Deprecated + public static final int getPort(Context ctx) { + java.net.Proxy proxy = getProxy(ctx, null); + if (proxy == java.net.Proxy.NO_PROXY) return -1; + try { + return ((InetSocketAddress)(proxy.address())).getPort(); + } catch (Exception e) { + return -1; + } + } + + /** + * Return the default proxy host specified by the carrier. + * @return String containing the host name or null if there is no proxy for + * this carrier. + * @deprecated Use standard java vm proxy values to find the host, port and + * exclusion list. This call ignores the exclusion list and no + * longer reports only mobile-data apn-based proxy values. + */ + @Deprecated + public static final String getDefaultHost() { + String host = System.getProperty("http.proxyHost"); + if (TextUtils.isEmpty(host)) return null; + return host; + } + + /** + * Return the default proxy port specified by the carrier. + * @return The port number to be used with the proxy host or -1 if there is + * no proxy for this carrier. + * @deprecated Use standard java vm proxy values to find the host, port and + * exclusion list. This call ignores the exclusion list and no + * longer reports only mobile-data apn-based proxy values. + */ + @Deprecated + public static final int getDefaultPort() { + if (getDefaultHost() == null) return -1; + try { + return Integer.parseInt(System.getProperty("http.proxyPort")); + } catch (NumberFormatException e) { + return -1; + } + } + + private static final boolean isLocalHost(String host) { + if (host == null) { + return false; + } + try { + if (host != null) { + if (host.equalsIgnoreCase("localhost")) { + return true; + } + if (InetAddresses.parseNumericAddress(host).isLoopbackAddress()) { + return true; + } + } + } catch (IllegalArgumentException iex) { + } + return false; + } + + /** + * Validate syntax of hostname, port and exclusion list entries + * {@hide} + */ + public static int validate(String hostname, String port, String exclList) { + Matcher match = HOSTNAME_PATTERN.matcher(hostname); + Matcher listMatch = EXCLLIST_PATTERN.matcher(exclList); + + if (!match.matches()) return PROXY_HOSTNAME_INVALID; + + if (!listMatch.matches()) return PROXY_EXCLLIST_INVALID; + + if (hostname.length() > 0 && port.length() == 0) return PROXY_PORT_EMPTY; + + if (port.length() > 0) { + if (hostname.length() == 0) return PROXY_HOSTNAME_EMPTY; + int portVal = -1; + try { + portVal = Integer.parseInt(port); + } catch (NumberFormatException ex) { + return PROXY_PORT_INVALID; + } + if (portVal <= 0 || portVal > 0xFFFF) return PROXY_PORT_INVALID; + } + return PROXY_VALID; + } + + /** @hide */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public static final void setHttpProxySystemProperty(ProxyInfo p) { + String host = null; + String port = null; + String exclList = null; + Uri pacFileUrl = Uri.EMPTY; + if (p != null) { + host = p.getHost(); + port = Integer.toString(p.getPort()); + exclList = ProxyUtils.exclusionListAsString(p.getExclusionList()); + pacFileUrl = p.getPacFileUrl(); + } + setHttpProxySystemProperty(host, port, exclList, pacFileUrl); + } + + /** @hide */ + public static final void setHttpProxySystemProperty(String host, String port, String exclList, + Uri pacFileUrl) { + if (exclList != null) exclList = exclList.replace(",", "|"); + if (false) Log.d(TAG, "setHttpProxySystemProperty :"+host+":"+port+" - "+exclList); + if (host != null) { + System.setProperty("http.proxyHost", host); + System.setProperty("https.proxyHost", host); + } else { + System.clearProperty("http.proxyHost"); + System.clearProperty("https.proxyHost"); + } + if (port != null) { + System.setProperty("http.proxyPort", port); + System.setProperty("https.proxyPort", port); + } else { + System.clearProperty("http.proxyPort"); + System.clearProperty("https.proxyPort"); + } + if (exclList != null) { + System.setProperty("http.nonProxyHosts", exclList); + System.setProperty("https.nonProxyHosts", exclList); + } else { + System.clearProperty("http.nonProxyHosts"); + System.clearProperty("https.nonProxyHosts"); + } + if (!Uri.EMPTY.equals(pacFileUrl)) { + ProxySelector.setDefault(new PacProxySelector()); + } else { + ProxySelector.setDefault(sDefaultProxySelector); + } + } +} diff --git a/framework/src/android/net/ProxyInfo.aidl b/framework/src/android/net/ProxyInfo.aidl new file mode 100644 index 0000000000..a5d0c120e7 --- /dev/null +++ b/framework/src/android/net/ProxyInfo.aidl @@ -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; + diff --git a/core/java/android/net/ProxyInfo.java b/framework/src/android/net/ProxyInfo.java similarity index 100% rename from core/java/android/net/ProxyInfo.java rename to framework/src/android/net/ProxyInfo.java diff --git a/framework/src/android/net/RouteInfo.aidl b/framework/src/android/net/RouteInfo.aidl new file mode 100644 index 0000000000..7af9fdaef3 --- /dev/null +++ b/framework/src/android/net/RouteInfo.aidl @@ -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; diff --git a/core/java/android/net/RouteInfo.java b/framework/src/android/net/RouteInfo.java similarity index 100% rename from core/java/android/net/RouteInfo.java rename to framework/src/android/net/RouteInfo.java diff --git a/core/java/android/net/SocketKeepalive.java b/framework/src/android/net/SocketKeepalive.java similarity index 100% rename from core/java/android/net/SocketKeepalive.java rename to framework/src/android/net/SocketKeepalive.java diff --git a/framework/src/android/net/StaticIpConfiguration.aidl b/framework/src/android/net/StaticIpConfiguration.aidl new file mode 100644 index 0000000000..8aac701fe7 --- /dev/null +++ b/framework/src/android/net/StaticIpConfiguration.aidl @@ -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; \ No newline at end of file diff --git a/core/java/android/net/StaticIpConfiguration.java b/framework/src/android/net/StaticIpConfiguration.java similarity index 100% rename from core/java/android/net/StaticIpConfiguration.java rename to framework/src/android/net/StaticIpConfiguration.java diff --git a/core/java/android/net/TcpKeepalivePacketData.java b/framework/src/android/net/TcpKeepalivePacketData.java similarity index 100% rename from core/java/android/net/TcpKeepalivePacketData.java rename to framework/src/android/net/TcpKeepalivePacketData.java diff --git a/core/java/android/net/TcpRepairWindow.java b/framework/src/android/net/TcpRepairWindow.java similarity index 100% rename from core/java/android/net/TcpRepairWindow.java rename to framework/src/android/net/TcpRepairWindow.java diff --git a/core/java/android/net/TcpSocketKeepalive.java b/framework/src/android/net/TcpSocketKeepalive.java similarity index 100% rename from core/java/android/net/TcpSocketKeepalive.java rename to framework/src/android/net/TcpSocketKeepalive.java diff --git a/framework/src/android/net/TestNetworkInterface.aidl b/framework/src/android/net/TestNetworkInterface.aidl new file mode 100644 index 0000000000..e1f4f9f794 --- /dev/null +++ b/framework/src/android/net/TestNetworkInterface.aidl @@ -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; diff --git a/core/java/android/net/TestNetworkInterface.java b/framework/src/android/net/TestNetworkInterface.java similarity index 100% rename from core/java/android/net/TestNetworkInterface.java rename to framework/src/android/net/TestNetworkInterface.java diff --git a/core/java/android/net/TestNetworkManager.java b/framework/src/android/net/TestNetworkManager.java similarity index 100% rename from core/java/android/net/TestNetworkManager.java rename to framework/src/android/net/TestNetworkManager.java diff --git a/core/java/android/net/TransportInfo.java b/framework/src/android/net/TransportInfo.java similarity index 100% rename from core/java/android/net/TransportInfo.java rename to framework/src/android/net/TransportInfo.java diff --git a/framework/src/android/net/UidRange.aidl b/framework/src/android/net/UidRange.aidl new file mode 100644 index 0000000000..f70fc8e2fe --- /dev/null +++ b/framework/src/android/net/UidRange.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +/** + * An inclusive range of UIDs. + * + * {@hide} + */ +parcelable UidRange; \ No newline at end of file diff --git a/framework/src/android/net/VpnManager.java b/framework/src/android/net/VpnManager.java new file mode 100644 index 0000000000..c87b8279c4 --- /dev/null +++ b/framework/src/android/net/VpnManager.java @@ -0,0 +1,164 @@ +/* + * 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 com.android.internal.util.Preconditions.checkNotNull; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.os.RemoteException; + +import com.android.internal.net.VpnProfile; + +import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.security.GeneralSecurityException; + +/** + * This class provides an interface for apps to manage platform VPN profiles + * + *

Apps can use this API to provide profiles with which the platform can set up a VPN without + * further app intermediation. When a VPN profile is present and the app is selected as an always-on + * VPN, the platform will directly trigger the negotiation of the VPN without starting or waking the + * app (unlike VpnService). + * + *

VPN apps using supported protocols should preferentially use this API over the {@link + * VpnService} API for ease-of-development and reduced maintainance burden. This also give the user + * the guarantee that VPN network traffic is not subjected to on-device packet interception. + * + * @see Ikev2VpnProfile + */ +public class VpnManager { + /** Type representing a lack of VPN @hide */ + public static final int TYPE_VPN_NONE = -1; + /** VPN service type code @hide */ + public static final int TYPE_VPN_SERVICE = 1; + /** Platform VPN type code @hide */ + public static final int TYPE_VPN_PLATFORM = 2; + + /** @hide */ + @IntDef(value = {TYPE_VPN_NONE, TYPE_VPN_SERVICE, TYPE_VPN_PLATFORM}) + @Retention(RetentionPolicy.SOURCE) + public @interface VpnType {} + + @NonNull private final Context mContext; + @NonNull private final IConnectivityManager mService; + + private static Intent getIntentForConfirmation() { + final Intent intent = new Intent(); + final ComponentName componentName = ComponentName.unflattenFromString( + Resources.getSystem().getString( + com.android.internal.R.string.config_platformVpnConfirmDialogComponent)); + intent.setComponent(componentName); + return intent; + } + + /** + * Create an instance of the VpnManager with the given context. + * + *

Internal only. Applications are expected to obtain an instance of the VpnManager via the + * {@link Context.getSystemService()} method call. + * + * @hide + */ + public VpnManager(@NonNull Context ctx, @NonNull IConnectivityManager service) { + mContext = checkNotNull(ctx, "missing Context"); + mService = checkNotNull(service, "missing IConnectivityManager"); + } + + /** + * Install a VpnProfile configuration keyed on the calling app's package name. + * + *

This method returns {@code null} if user consent has already been granted, or an {@link + * Intent} to a system activity. If an intent is returned, the application should launch the + * activity using {@link Activity#startActivityForResult} to request user consent. The activity + * may pop up a dialog to require user action, and the result will come back via its {@link + * Activity#onActivityResult}. If the result is {@link Activity#RESULT_OK}, the user has + * consented, and the VPN profile can be started. + * + * @param profile the VpnProfile provided by this package. Will override any previous VpnProfile + * stored for this package. + * @return an Intent requesting user consent to start the VPN, or null if consent is not + * required based on privileges or previous user consent. + */ + @Nullable + public Intent provisionVpnProfile(@NonNull PlatformVpnProfile profile) { + final VpnProfile internalProfile; + + try { + internalProfile = profile.toVpnProfile(); + } catch (GeneralSecurityException | IOException e) { + // Conversion to VpnProfile failed; this is an invalid profile. Both of these exceptions + // indicate a failure to convert a PrivateKey or X509Certificate to a Base64 encoded + // string as required by the VpnProfile. + throw new IllegalArgumentException("Failed to serialize PlatformVpnProfile", e); + } + + try { + // Profile can never be null; it either gets set, or an exception is thrown. + if (mService.provisionVpnProfile(internalProfile, mContext.getOpPackageName())) { + return null; + } + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + return getIntentForConfirmation(); + } + + /** + * Delete the VPN profile configuration that was provisioned by the calling app + * + * @throws SecurityException if this would violate user settings + */ + public void deleteProvisionedVpnProfile() { + try { + mService.deleteVpnProfile(mContext.getOpPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Request the startup of a previously provisioned VPN. + * + * @throws SecurityException exception if user or device settings prevent this VPN from being + * setup, or if user consent has not been granted + */ + public void startProvisionedVpnProfile() { + try { + mService.startVpnProfile(mContext.getOpPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** Tear down the VPN provided by the calling app (if any) */ + public void stopProvisionedVpnProfile() { + try { + mService.stopVpnProfile(mContext.getOpPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } +} diff --git a/framework/src/android/net/VpnService.java b/framework/src/android/net/VpnService.java new file mode 100644 index 0000000000..8e90a119fe --- /dev/null +++ b/framework/src/android/net/VpnService.java @@ -0,0 +1,903 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import static android.system.OsConstants.AF_INET; +import static android.system.OsConstants.AF_INET6; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.RequiresPermission; +import android.annotation.SystemApi; +import android.app.Activity; +import android.app.PendingIntent; +import android.app.Service; +import android.app.admin.DevicePolicyManager; +import android.compat.annotation.UnsupportedAppUsage; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.IPackageManager; +import android.content.pm.PackageManager; +import android.os.Binder; +import android.os.IBinder; +import android.os.Parcel; +import android.os.ParcelFileDescriptor; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.UserHandle; + +import com.android.internal.net.VpnConfig; + +import java.net.DatagramSocket; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.Socket; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * VpnService is a base class for applications to extend and build their + * own VPN solutions. In general, it creates a virtual network interface, + * configures addresses and routing rules, and returns a file descriptor + * to the application. Each read from the descriptor retrieves an outgoing + * packet which was routed to the interface. Each write to the descriptor + * injects an incoming packet just like it was received from the interface. + * The interface is running on Internet Protocol (IP), so packets are + * always started with IP headers. The application then completes a VPN + * connection by processing and exchanging packets with the remote server + * over a tunnel. + * + *

Letting applications intercept packets raises huge security concerns. + * A VPN application can easily break the network. Besides, two of them may + * conflict with each other. The system takes several actions to address + * these issues. Here are some key points: + *

    + *
  • User action is required the first time an application creates a VPN + * connection.
  • + *
  • There can be only one VPN connection running at the same time. The + * existing interface is deactivated when a new one is created.
  • + *
  • A system-managed notification is shown during the lifetime of a + * VPN connection.
  • + *
  • A system-managed dialog gives the information of the current VPN + * connection. It also provides a button to disconnect.
  • + *
  • The network is restored automatically when the file descriptor is + * closed. It also covers the cases when a VPN application is crashed + * or killed by the system.
  • + *
+ * + *

There are two primary methods in this class: {@link #prepare} and + * {@link Builder#establish}. The former deals with user action and stops + * the VPN connection created by another application. The latter creates + * a VPN interface using the parameters supplied to the {@link Builder}. + * An application must call {@link #prepare} to grant the right to use + * other methods in this class, and the right can be revoked at any time. + * Here are the general steps to create a VPN connection: + *

    + *
  1. When the user presses the button to connect, call {@link #prepare} + * and launch the returned intent, if non-null.
  2. + *
  3. When the application becomes prepared, start the service.
  4. + *
  5. Create a tunnel to the remote server and negotiate the network + * parameters for the VPN connection.
  6. + *
  7. Supply those parameters to a {@link Builder} and create a VPN + * interface by calling {@link Builder#establish}.
  8. + *
  9. Process and exchange packets between the tunnel and the returned + * file descriptor.
  10. + *
  11. When {@link #onRevoke} is invoked, close the file descriptor and + * shut down the tunnel gracefully.
  12. + *
+ * + *

Services extending this class need to be declared with an appropriate + * permission and intent filter. Their access must be secured by + * {@link android.Manifest.permission#BIND_VPN_SERVICE} permission, and + * their intent filter must match {@link #SERVICE_INTERFACE} action. Here + * is an example of declaring a VPN service in {@code AndroidManifest.xml}: + *

+ * <service android:name=".ExampleVpnService"
+ *         android:permission="android.permission.BIND_VPN_SERVICE">
+ *     <intent-filter>
+ *         <action android:name="android.net.VpnService"/>
+ *     </intent-filter>
+ * </service>
+ * + *

The Android system starts a VPN in the background by calling + * {@link android.content.Context#startService startService()}. In Android 8.0 + * (API level 26) and higher, the system places VPN apps on the temporary + * allowlist for a short period so the app can start in the background. The VPN + * app must promote itself to the foreground after it's launched or the system + * will shut down the app. + * + *

Developer's guide

+ * + *

To learn more about developing VPN apps, read the + * VPN developer's guide. + * + * @see Builder + */ +public class VpnService extends Service { + + /** + * The action must be matched by the intent filter of this service. It also + * needs to require {@link android.Manifest.permission#BIND_VPN_SERVICE} + * permission so that other applications cannot abuse it. + */ + public static final String SERVICE_INTERFACE = VpnConfig.SERVICE_INTERFACE; + + /** + * Key for boolean meta-data field indicating whether this VpnService supports always-on mode. + * + *

For a VPN app targeting {@link android.os.Build.VERSION_CODES#N API 24} or above, Android + * provides users with the ability to set it as always-on, so that VPN connection is + * persisted after device reboot and app upgrade. Always-on VPN can also be enabled by device + * owner and profile owner apps through + * {@link DevicePolicyManager#setAlwaysOnVpnPackage}. + * + *

VPN apps not supporting this feature should opt out by adding this meta-data field to the + * {@code VpnService} component of {@code AndroidManifest.xml}. In case there is more than one + * {@code VpnService} component defined in {@code AndroidManifest.xml}, opting out any one of + * them will opt out the entire app. For example, + *

 {@code
+     * 
+     *     
+     *         
+     *     
+     *     
+     * 
+     * } 
+ * + *

This meta-data field defaults to {@code true} if absent. It will only have effect on + * {@link android.os.Build.VERSION_CODES#O_MR1} or higher. + */ + public static final String SERVICE_META_DATA_SUPPORTS_ALWAYS_ON = + "android.net.VpnService.SUPPORTS_ALWAYS_ON"; + + /** + * Use IConnectivityManager since those methods are hidden and not + * available in ConnectivityManager. + */ + private static IConnectivityManager getService() { + return IConnectivityManager.Stub.asInterface( + ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); + } + + /** + * Prepare to establish a VPN connection. This method returns {@code null} + * if the VPN application is already prepared or if the user has previously + * consented to the VPN application. Otherwise, it returns an + * {@link Intent} to a system activity. The application should launch the + * activity using {@link Activity#startActivityForResult} to get itself + * prepared. The activity may pop up a dialog to require user action, and + * the result will come back via its {@link Activity#onActivityResult}. + * If the result is {@link Activity#RESULT_OK}, the application becomes + * prepared and is granted to use other methods in this class. + * + *

Only one application can be granted at the same time. The right + * is revoked when another application is granted. The application + * losing the right will be notified via its {@link #onRevoke}. Unless + * it becomes prepared again, subsequent calls to other methods in this + * class will fail. + * + *

The user may disable the VPN at any time while it is activated, in + * which case this method will return an intent the next time it is + * executed to obtain the user's consent again. + * + * @see #onRevoke + */ + public static Intent prepare(Context context) { + try { + if (getService().prepareVpn(context.getPackageName(), null, context.getUserId())) { + return null; + } + } catch (RemoteException e) { + // ignore + } + return VpnConfig.getIntentForConfirmation(); + } + + /** + * Version of {@link #prepare(Context)} which does not require user consent. + * + *

Requires {@link android.Manifest.permission#CONTROL_VPN} and should generally not be + * used. Only acceptable in situations where user consent has been obtained through other means. + * + *

Once this is run, future preparations may be done with the standard prepare method as this + * will authorize the package to prepare the VPN without consent in the future. + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.CONTROL_VPN) + public static void prepareAndAuthorize(Context context) { + IConnectivityManager cm = getService(); + String packageName = context.getPackageName(); + try { + // Only prepare if we're not already prepared. + int userId = context.getUserId(); + if (!cm.prepareVpn(packageName, null, userId)) { + cm.prepareVpn(null, packageName, userId); + } + cm.setVpnPackageAuthorization(packageName, userId, VpnManager.TYPE_VPN_SERVICE); + } catch (RemoteException e) { + // ignore + } + } + + /** + * Protect a socket from VPN connections. After protecting, data sent + * through this socket will go directly to the underlying network, + * so its traffic will not be forwarded through the VPN. + * This method is useful if some connections need to be kept + * outside of VPN. For example, a VPN tunnel should protect itself if its + * destination is covered by VPN routes. Otherwise its outgoing packets + * will be sent back to the VPN interface and cause an infinite loop. This + * method will fail if the application is not prepared or is revoked. + * + *

The socket is NOT closed by this method. + * + * @return {@code true} on success. + */ + public boolean protect(int socket) { + return NetworkUtils.protectFromVpn(socket); + } + + /** + * Convenience method to protect a {@link Socket} from VPN connections. + * + * @return {@code true} on success. + * @see #protect(int) + */ + public boolean protect(Socket socket) { + return protect(socket.getFileDescriptor$().getInt$()); + } + + /** + * Convenience method to protect a {@link DatagramSocket} from VPN + * connections. + * + * @return {@code true} on success. + * @see #protect(int) + */ + public boolean protect(DatagramSocket socket) { + return protect(socket.getFileDescriptor$().getInt$()); + } + + /** + * Adds a network address to the VPN interface. + * + * Both IPv4 and IPv6 addresses are supported. The VPN must already be established. Fails if the + * address is already in use or cannot be assigned to the interface for any other reason. + * + * Adding an address implicitly allows traffic from that address family (i.e., IPv4 or IPv6) to + * be routed over the VPN. @see Builder#allowFamily + * + * @throws IllegalArgumentException if the address is invalid. + * + * @param address The IP address (IPv4 or IPv6) to assign to the VPN interface. + * @param prefixLength The prefix length of the address. + * + * @return {@code true} on success. + * @see Builder#addAddress + * + * @hide + */ + public boolean addAddress(InetAddress address, int prefixLength) { + check(address, prefixLength); + try { + return getService().addVpnAddress(address.getHostAddress(), prefixLength); + } catch (RemoteException e) { + throw new IllegalStateException(e); + } + } + + /** + * Removes a network address from the VPN interface. + * + * Both IPv4 and IPv6 addresses are supported. The VPN must already be established. Fails if the + * address is not assigned to the VPN interface, or if it is the only address assigned (thus + * cannot be removed), or if the address cannot be removed for any other reason. + * + * After removing an address, if there are no addresses, routes or DNS servers of a particular + * address family (i.e., IPv4 or IPv6) configured on the VPN, that DOES NOT block that + * family from being routed. In other words, once an address family has been allowed, it stays + * allowed for the rest of the VPN's session. @see Builder#allowFamily + * + * @throws IllegalArgumentException if the address is invalid. + * + * @param address The IP address (IPv4 or IPv6) to assign to the VPN interface. + * @param prefixLength The prefix length of the address. + * + * @return {@code true} on success. + * + * @hide + */ + public boolean removeAddress(InetAddress address, int prefixLength) { + check(address, prefixLength); + try { + return getService().removeVpnAddress(address.getHostAddress(), prefixLength); + } catch (RemoteException e) { + throw new IllegalStateException(e); + } + } + + /** + * Sets the underlying networks used by the VPN for its upstream connections. + * + *

Used by the system to know the actual networks that carry traffic for apps affected by + * this VPN in order to present this information to the user (e.g., via status bar icons). + * + *

This method only needs to be called if the VPN has explicitly bound its underlying + * communications channels — such as the socket(s) passed to {@link #protect(int)} — + * to a {@code Network} using APIs such as {@link Network#bindSocket(Socket)} or + * {@link Network#bindSocket(DatagramSocket)}. The VPN should call this method every time + * the set of {@code Network}s it is using changes. + * + *

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

    + *
  • a non-empty array: an array of one or more {@link Network}s, in + * decreasing preference order. For example, if this VPN uses both wifi and mobile (cellular) + * networks to carry app traffic, but prefers or uses wifi more than mobile, wifi should appear + * first in the array.
  • + *
  • an empty array: a zero-element array, meaning that the VPN has no + * underlying network connection, and thus, app traffic will not be sent or received.
  • + *
  • null: (default) signifies that the VPN uses whatever is the system's + * default network. I.e., it doesn't use the {@code bindSocket} or {@code bindDatagramSocket} + * APIs mentioned above to send traffic over specific channels.
  • + *
+ * + *

This call will succeed only if the VPN is currently established. For setting this value + * when the VPN has not yet been established, see {@link Builder#setUnderlyingNetworks}. + * + * @param networks An array of networks the VPN uses to tunnel traffic to/from its servers. + * + * @return {@code true} on success. + */ + public boolean setUnderlyingNetworks(Network[] networks) { + try { + return getService().setUnderlyingNetworksForVpn(networks); + } catch (RemoteException e) { + throw new IllegalStateException(e); + } + } + + /** + * Returns whether the service is running in always-on VPN mode. In this mode the system ensures + * that the service is always running by restarting it when necessary, e.g. after reboot. + * + * @see DevicePolicyManager#setAlwaysOnVpnPackage(ComponentName, String, boolean, Set) + */ + public final boolean isAlwaysOn() { + try { + return getService().isCallerCurrentAlwaysOnVpnApp(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns whether the service is running in always-on VPN lockdown mode. In this mode the + * system ensures that the service is always running and that the apps aren't allowed to bypass + * the VPN. + * + * @see DevicePolicyManager#setAlwaysOnVpnPackage(ComponentName, String, boolean, Set) + */ + public final boolean isLockdownEnabled() { + try { + return getService().isCallerCurrentAlwaysOnVpnLockdownApp(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Return the communication interface to the service. This method returns + * {@code null} on {@link Intent}s other than {@link #SERVICE_INTERFACE} + * action. Applications overriding this method must identify the intent + * and return the corresponding interface accordingly. + * + * @see Service#onBind + */ + @Override + public IBinder onBind(Intent intent) { + if (intent != null && SERVICE_INTERFACE.equals(intent.getAction())) { + return new Callback(); + } + return null; + } + + /** + * Invoked when the application is revoked. At this moment, the VPN + * interface is already deactivated by the system. The application should + * close the file descriptor and shut down gracefully. The default + * implementation of this method is calling {@link Service#stopSelf()}. + * + *

Calls to this method may not happen on the main thread + * of the process. + * + * @see #prepare + */ + public void onRevoke() { + stopSelf(); + } + + /** + * Use raw Binder instead of AIDL since now there is only one usage. + */ + private class Callback extends Binder { + @Override + protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) { + if (code == IBinder.LAST_CALL_TRANSACTION) { + onRevoke(); + return true; + } + return false; + } + } + + /** + * Private method to validate address and prefixLength. + */ + private static void check(InetAddress address, int prefixLength) { + if (address.isLoopbackAddress()) { + throw new IllegalArgumentException("Bad address"); + } + if (address instanceof Inet4Address) { + if (prefixLength < 0 || prefixLength > 32) { + throw new IllegalArgumentException("Bad prefixLength"); + } + } else if (address instanceof Inet6Address) { + if (prefixLength < 0 || prefixLength > 128) { + throw new IllegalArgumentException("Bad prefixLength"); + } + } else { + throw new IllegalArgumentException("Unsupported family"); + } + } + + /** + * Helper class to create a VPN interface. This class should be always + * used within the scope of the outer {@link VpnService}. + * + * @see VpnService + */ + public class Builder { + + private final VpnConfig mConfig = new VpnConfig(); + @UnsupportedAppUsage + private final List mAddresses = new ArrayList(); + @UnsupportedAppUsage + private final List mRoutes = new ArrayList(); + + public Builder() { + mConfig.user = VpnService.this.getClass().getName(); + } + + /** + * Set the name of this session. It will be displayed in + * system-managed dialogs and notifications. This is recommended + * not required. + */ + @NonNull + public Builder setSession(@NonNull String session) { + mConfig.session = session; + return this; + } + + /** + * Set the {@link PendingIntent} to an activity for users to + * configure the VPN connection. If it is not set, the button + * to configure will not be shown in system-managed dialogs. + */ + @NonNull + public Builder setConfigureIntent(@NonNull PendingIntent intent) { + mConfig.configureIntent = intent; + return this; + } + + /** + * Set the maximum transmission unit (MTU) of the VPN interface. If + * it is not set, the default value in the operating system will be + * used. + * + * @throws IllegalArgumentException if the value is not positive. + */ + @NonNull + public Builder setMtu(int mtu) { + if (mtu <= 0) { + throw new IllegalArgumentException("Bad mtu"); + } + mConfig.mtu = mtu; + return this; + } + + /** + * Sets an HTTP proxy for the VPN network. This proxy is only a recommendation + * and it is possible that some apps will ignore it. + */ + @NonNull + public Builder setHttpProxy(@NonNull ProxyInfo proxyInfo) { + mConfig.proxyInfo = proxyInfo; + return this; + } + + /** + * Add a network address to the VPN interface. Both IPv4 and IPv6 + * addresses are supported. At least one address must be set before + * calling {@link #establish}. + * + * Adding an address implicitly allows traffic from that address family + * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily + * + * @throws IllegalArgumentException if the address is invalid. + */ + @NonNull + public Builder addAddress(@NonNull InetAddress address, int prefixLength) { + check(address, prefixLength); + + if (address.isAnyLocalAddress()) { + throw new IllegalArgumentException("Bad address"); + } + mAddresses.add(new LinkAddress(address, prefixLength)); + mConfig.updateAllowedFamilies(address); + return this; + } + + /** + * Convenience method to add a network address to the VPN interface + * using a numeric address string. See {@link InetAddress} for the + * definitions of numeric address formats. + * + * Adding an address implicitly allows traffic from that address family + * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily + * + * @throws IllegalArgumentException if the address is invalid. + * @see #addAddress(InetAddress, int) + */ + @NonNull + public Builder addAddress(@NonNull String address, int prefixLength) { + return addAddress(InetAddress.parseNumericAddress(address), prefixLength); + } + + /** + * Add a network route to the VPN interface. Both IPv4 and IPv6 + * routes are supported. + * + * Adding a route implicitly allows traffic from that address family + * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily + * + * @throws IllegalArgumentException if the route is invalid. + */ + @NonNull + public Builder addRoute(@NonNull InetAddress address, int prefixLength) { + check(address, prefixLength); + + int offset = prefixLength / 8; + byte[] bytes = address.getAddress(); + if (offset < bytes.length) { + for (bytes[offset] <<= prefixLength % 8; offset < bytes.length; ++offset) { + if (bytes[offset] != 0) { + throw new IllegalArgumentException("Bad address"); + } + } + } + mRoutes.add(new RouteInfo(new IpPrefix(address, prefixLength), null)); + mConfig.updateAllowedFamilies(address); + return this; + } + + /** + * Convenience method to add a network route to the VPN interface + * using a numeric address string. See {@link InetAddress} for the + * definitions of numeric address formats. + * + * Adding a route implicitly allows traffic from that address family + * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily + * + * @throws IllegalArgumentException if the route is invalid. + * @see #addRoute(InetAddress, int) + */ + @NonNull + public Builder addRoute(@NonNull String address, int prefixLength) { + return addRoute(InetAddress.parseNumericAddress(address), prefixLength); + } + + /** + * Add a DNS server to the VPN connection. Both IPv4 and IPv6 + * addresses are supported. If none is set, the DNS servers of + * the default network will be used. + * + * Adding a server implicitly allows traffic from that address family + * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily + * + * @throws IllegalArgumentException if the address is invalid. + */ + @NonNull + public Builder addDnsServer(@NonNull InetAddress address) { + if (address.isLoopbackAddress() || address.isAnyLocalAddress()) { + throw new IllegalArgumentException("Bad address"); + } + if (mConfig.dnsServers == null) { + mConfig.dnsServers = new ArrayList(); + } + mConfig.dnsServers.add(address.getHostAddress()); + return this; + } + + /** + * Convenience method to add a DNS server to the VPN connection + * using a numeric address string. See {@link InetAddress} for the + * definitions of numeric address formats. + * + * Adding a server implicitly allows traffic from that address family + * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily + * + * @throws IllegalArgumentException if the address is invalid. + * @see #addDnsServer(InetAddress) + */ + @NonNull + public Builder addDnsServer(@NonNull String address) { + return addDnsServer(InetAddress.parseNumericAddress(address)); + } + + /** + * Add a search domain to the DNS resolver. + */ + @NonNull + public Builder addSearchDomain(@NonNull String domain) { + if (mConfig.searchDomains == null) { + mConfig.searchDomains = new ArrayList(); + } + mConfig.searchDomains.add(domain); + return this; + } + + /** + * Allows traffic from the specified address family. + * + * By default, if no address, route or DNS server of a specific family (IPv4 or IPv6) is + * added to this VPN, then all outgoing traffic of that family is blocked. If any address, + * route or DNS server is added, that family is allowed. + * + * This method allows an address family to be unblocked even without adding an address, + * route or DNS server of that family. Traffic of that family will then typically + * fall-through to the underlying network if it's supported. + * + * {@code family} must be either {@code AF_INET} (for IPv4) or {@code AF_INET6} (for IPv6). + * {@link IllegalArgumentException} is thrown if it's neither. + * + * @param family The address family ({@code AF_INET} or {@code AF_INET6}) to allow. + * + * @return this {@link Builder} object to facilitate chaining of method calls. + */ + @NonNull + public Builder allowFamily(int family) { + if (family == AF_INET) { + mConfig.allowIPv4 = true; + } else if (family == AF_INET6) { + mConfig.allowIPv6 = true; + } else { + throw new IllegalArgumentException(family + " is neither " + AF_INET + " nor " + + AF_INET6); + } + return this; + } + + private void verifyApp(String packageName) throws PackageManager.NameNotFoundException { + IPackageManager pm = IPackageManager.Stub.asInterface( + ServiceManager.getService("package")); + try { + pm.getApplicationInfo(packageName, 0, UserHandle.getCallingUserId()); + } catch (RemoteException e) { + throw new IllegalStateException(e); + } + } + + /** + * Adds an application that's allowed to access the VPN connection. + * + * If this method is called at least once, only applications added through this method (and + * no others) are allowed access. Else (if this method is never called), all applications + * are allowed by default. If some applications are added, other, un-added applications + * will use networking as if the VPN wasn't running. + * + * A {@link Builder} may have only a set of allowed applications OR a set of disallowed + * ones, but not both. Calling this method after {@link #addDisallowedApplication} has + * already been called, or vice versa, will throw an {@link UnsupportedOperationException}. + * + * {@code packageName} must be the canonical name of a currently installed application. + * {@link PackageManager.NameNotFoundException} is thrown if there's no such application. + * + * @throws PackageManager.NameNotFoundException If the application isn't installed. + * + * @param packageName The full name (e.g.: "com.google.apps.contacts") of an application. + * + * @return this {@link Builder} object to facilitate chaining method calls. + */ + @NonNull + public Builder addAllowedApplication(@NonNull String packageName) + throws PackageManager.NameNotFoundException { + if (mConfig.disallowedApplications != null) { + throw new UnsupportedOperationException("addDisallowedApplication already called"); + } + verifyApp(packageName); + if (mConfig.allowedApplications == null) { + mConfig.allowedApplications = new ArrayList(); + } + mConfig.allowedApplications.add(packageName); + return this; + } + + /** + * Adds an application that's denied access to the VPN connection. + * + * By default, all applications are allowed access, except for those denied through this + * method. Denied applications will use networking as if the VPN wasn't running. + * + * A {@link Builder} may have only a set of allowed applications OR a set of disallowed + * ones, but not both. Calling this method after {@link #addAllowedApplication} has already + * been called, or vice versa, will throw an {@link UnsupportedOperationException}. + * + * {@code packageName} must be the canonical name of a currently installed application. + * {@link PackageManager.NameNotFoundException} is thrown if there's no such application. + * + * @throws PackageManager.NameNotFoundException If the application isn't installed. + * + * @param packageName The full name (e.g.: "com.google.apps.contacts") of an application. + * + * @return this {@link Builder} object to facilitate chaining method calls. + */ + @NonNull + public Builder addDisallowedApplication(@NonNull String packageName) + throws PackageManager.NameNotFoundException { + if (mConfig.allowedApplications != null) { + throw new UnsupportedOperationException("addAllowedApplication already called"); + } + verifyApp(packageName); + if (mConfig.disallowedApplications == null) { + mConfig.disallowedApplications = new ArrayList(); + } + mConfig.disallowedApplications.add(packageName); + return this; + } + + /** + * Allows all apps to bypass this VPN connection. + * + * By default, all traffic from apps is forwarded through the VPN interface and it is not + * possible for apps to side-step the VPN. If this method is called, apps may use methods + * such as {@link ConnectivityManager#bindProcessToNetwork} to instead send/receive + * directly over the underlying network or any other network they have permissions for. + * + * @return this {@link Builder} object to facilitate chaining of method calls. + */ + @NonNull + public Builder allowBypass() { + mConfig.allowBypass = true; + return this; + } + + /** + * Sets the VPN interface's file descriptor to be in blocking/non-blocking mode. + * + * By default, the file descriptor returned by {@link #establish} is non-blocking. + * + * @param blocking True to put the descriptor into blocking mode; false for non-blocking. + * + * @return this {@link Builder} object to facilitate chaining method calls. + */ + @NonNull + public Builder setBlocking(boolean blocking) { + mConfig.blocking = blocking; + return this; + } + + /** + * Sets the underlying networks used by the VPN for its upstream connections. + * + * @see VpnService#setUnderlyingNetworks + * + * @param networks An array of networks the VPN uses to tunnel traffic to/from its servers. + * + * @return this {@link Builder} object to facilitate chaining method calls. + */ + @NonNull + public Builder setUnderlyingNetworks(@Nullable Network[] networks) { + mConfig.underlyingNetworks = networks != null ? networks.clone() : null; + return this; + } + + /** + * Marks the VPN network as metered. A VPN network is classified as metered when the user is + * sensitive to heavy data usage due to monetary costs and/or data limitations. In such + * cases, you should set this to {@code true} so that apps on the system can avoid doing + * large data transfers. Otherwise, set this to {@code false}. Doing so would cause VPN + * network to inherit its meteredness from its underlying networks. + * + *

VPN apps targeting {@link android.os.Build.VERSION_CODES#Q} or above will be + * considered metered by default. + * + * @param isMetered {@code true} if VPN network should be treated as metered regardless of + * underlying network meteredness + * @return this {@link Builder} object to facilitate chaining method calls + * @see #setUnderlyingNetworks(Network[]) + * @see ConnectivityManager#isActiveNetworkMetered() + */ + @NonNull + public Builder setMetered(boolean isMetered) { + mConfig.isMetered = isMetered; + return this; + } + + /** + * Create a VPN interface using the parameters supplied to this + * builder. The interface works on IP packets, and a file descriptor + * is returned for the application to access them. Each read + * retrieves an outgoing packet which was routed to the interface. + * Each write injects an incoming packet just like it was received + * from the interface. The file descriptor is put into non-blocking + * mode by default to avoid blocking Java threads. To use the file + * descriptor completely in native space, see + * {@link ParcelFileDescriptor#detachFd()}. The application MUST + * close the file descriptor when the VPN connection is terminated. + * The VPN interface will be removed and the network will be + * restored by the system automatically. + * + *

To avoid conflicts, there can be only one active VPN interface + * at the same time. Usually network parameters are never changed + * during the lifetime of a VPN connection. It is also common for an + * application to create a new file descriptor after closing the + * previous one. However, it is rare but not impossible to have two + * interfaces while performing a seamless handover. In this case, the + * old interface will be deactivated when the new one is created + * successfully. Both file descriptors are valid but now outgoing + * packets will be routed to the new interface. Therefore, after + * draining the old file descriptor, the application MUST close it + * and start using the new file descriptor. If the new interface + * cannot be created, the existing interface and its file descriptor + * remain untouched. + * + *

An exception will be thrown if the interface cannot be created + * for any reason. However, this method returns {@code null} if the + * application is not prepared or is revoked. This helps solve + * possible race conditions between other VPN applications. + * + * @return {@link ParcelFileDescriptor} of the VPN interface, or + * {@code null} if the application is not prepared. + * @throws IllegalArgumentException if a parameter is not accepted + * by the operating system. + * @throws IllegalStateException if a parameter cannot be applied + * by the operating system. + * @throws SecurityException if the service is not properly declared + * in {@code AndroidManifest.xml}. + * @see VpnService + */ + @Nullable + public ParcelFileDescriptor establish() { + mConfig.addresses = mAddresses; + mConfig.routes = mRoutes; + + try { + return getService().establishVpn(mConfig); + } catch (RemoteException e) { + throw new IllegalStateException(e); + } + } + } +} diff --git a/framework/src/android/net/apf/ApfCapabilities.aidl b/framework/src/android/net/apf/ApfCapabilities.aidl new file mode 100644 index 0000000000..7c4d4c2da4 --- /dev/null +++ b/framework/src/android/net/apf/ApfCapabilities.aidl @@ -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; \ No newline at end of file diff --git a/core/java/android/net/apf/ApfCapabilities.java b/framework/src/android/net/apf/ApfCapabilities.java similarity index 100% rename from core/java/android/net/apf/ApfCapabilities.java rename to framework/src/android/net/apf/ApfCapabilities.java diff --git a/core/java/android/net/util/DnsUtils.java b/framework/src/android/net/util/DnsUtils.java similarity index 100% rename from core/java/android/net/util/DnsUtils.java rename to framework/src/android/net/util/DnsUtils.java diff --git a/core/java/android/net/util/KeepaliveUtils.java b/framework/src/android/net/util/KeepaliveUtils.java similarity index 100% rename from core/java/android/net/util/KeepaliveUtils.java rename to framework/src/android/net/util/KeepaliveUtils.java diff --git a/core/java/android/net/util/MultinetworkPolicyTracker.java b/framework/src/android/net/util/MultinetworkPolicyTracker.java similarity index 100% rename from core/java/android/net/util/MultinetworkPolicyTracker.java rename to framework/src/android/net/util/MultinetworkPolicyTracker.java diff --git a/framework/src/android/net/util/SocketUtils.java b/framework/src/android/net/util/SocketUtils.java new file mode 100644 index 0000000000..e64060f1b2 --- /dev/null +++ b/framework/src/android/net/util/SocketUtils.java @@ -0,0 +1,121 @@ +/* + * 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.util; + +import static android.system.OsConstants.SOL_SOCKET; +import static android.system.OsConstants.SO_BINDTODEVICE; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.net.NetworkUtils; +import android.system.ErrnoException; +import android.system.NetlinkSocketAddress; +import android.system.Os; +import android.system.PacketSocketAddress; + +import libcore.io.IoBridge; + +import java.io.FileDescriptor; +import java.io.IOException; +import java.net.SocketAddress; + +/** + * Collection of utilities to interact with raw sockets. + * @hide + */ +@SystemApi +public final class SocketUtils { + /** + * Create a raw datagram socket that is bound to an interface. + * + *

Data sent through the socket will go directly to the underlying network, ignoring VPNs. + */ + public static void bindSocketToInterface(@NonNull FileDescriptor socket, @NonNull String iface) + throws ErrnoException { + // SO_BINDTODEVICE actually takes a string. This works because the first member + // of struct ifreq is a NULL-terminated interface name. + // TODO: add a setsockoptString() + Os.setsockoptIfreq(socket, SOL_SOCKET, SO_BINDTODEVICE, iface); + NetworkUtils.protectFromVpn(socket); + } + + /** + * Make a socket address to communicate with netlink. + */ + @NonNull + public static SocketAddress makeNetlinkSocketAddress(int portId, int groupsMask) { + return new NetlinkSocketAddress(portId, groupsMask); + } + + /** + * Make socket address that packet sockets can bind to. + * + * @param protocol the layer 2 protocol of the packets to receive. One of the {@code ETH_P_*} + * constants in {@link android.system.OsConstants}. + * @param ifIndex the interface index on which packets will be received. + */ + @NonNull + public static SocketAddress makePacketSocketAddress(int protocol, int ifIndex) { + return new PacketSocketAddress( + protocol /* sll_protocol */, + ifIndex /* sll_ifindex */, + null /* sll_addr */); + } + + /** + * Make a socket address that packet socket can send packets to. + * @deprecated Use {@link #makePacketSocketAddress(int, int, byte[])} instead. + * + * @param ifIndex the interface index on which packets will be sent. + * @param hwAddr the hardware address to which packets will be sent. + */ + @Deprecated + @NonNull + public static SocketAddress makePacketSocketAddress(int ifIndex, @NonNull byte[] hwAddr) { + return new PacketSocketAddress( + 0 /* sll_protocol */, + ifIndex /* sll_ifindex */, + hwAddr /* sll_addr */); + } + + /** + * Make a socket address that a packet socket can send packets to. + * + * @param protocol the layer 2 protocol of the packets to send. One of the {@code ETH_P_*} + * constants in {@link android.system.OsConstants}. + * @param ifIndex the interface index on which packets will be sent. + * @param hwAddr the hardware address to which packets will be sent. + */ + @NonNull + public static SocketAddress makePacketSocketAddress(int protocol, int ifIndex, + @NonNull byte[] hwAddr) { + return new PacketSocketAddress( + protocol /* sll_protocol */, + ifIndex /* sll_ifindex */, + hwAddr /* sll_addr */); + } + + /** + * @see IoBridge#closeAndSignalBlockedThreads(FileDescriptor) + */ + public static void closeSocket(@Nullable FileDescriptor fd) throws IOException { + IoBridge.closeAndSignalBlockedThreads(fd); + } + + private SocketUtils() {} +}