Merge "Address comment from aosp/1948169"
diff --git a/Tethering/Android.bp b/Tethering/Android.bp
index ae96e8c..46fd50f 100644
--- a/Tethering/Android.bp
+++ b/Tethering/Android.bp
@@ -179,7 +179,7 @@
// The permission configuration *must* be included to ensure security of the device
required: [
"NetworkPermissionConfig",
- "privapp_whitelist_com.android.networkstack.tethering",
+ "privapp_allowlist_com.android.tethering",
],
apex_available: ["com.android.tethering"],
lint: { strict_updatability_linting: true },
@@ -199,7 +199,7 @@
// The permission configuration *must* be included to ensure security of the device
required: [
"NetworkPermissionConfig",
- "privapp_whitelist_com.android.networkstack.tethering",
+ "privapp_allowlist_com.android.tethering",
],
apex_available: ["com.android.tethering"],
lint: { strict_updatability_linting: true },
diff --git a/Tethering/apex/Android.bp b/Tethering/apex/Android.bp
index ea3f8d6..1a4ba9d 100644
--- a/Tethering/apex/Android.bp
+++ b/Tethering/apex/Android.bp
@@ -74,7 +74,10 @@
apps: [
"ServiceConnectivityResources",
],
- prebuilts: ["current_sdkinfo"],
+ prebuilts: [
+ "current_sdkinfo",
+ "privapp_allowlist_com.android.tethering",
+ ],
manifest: "manifest.json",
key: "com.android.tethering.key",
// Indicates that pre-installed version of this apex can be compressed.
diff --git a/Tethering/apex/hiddenapi/hiddenapi-max-target-o-low-priority-tiramisu.txt b/Tethering/apex/hiddenapi/hiddenapi-max-target-o-low-priority-tiramisu.txt
index 88c77f2..c1d87bb 100644
--- a/Tethering/apex/hiddenapi/hiddenapi-max-target-o-low-priority-tiramisu.txt
+++ b/Tethering/apex/hiddenapi/hiddenapi-max-target-o-low-priority-tiramisu.txt
@@ -1,3 +1,216 @@
+Landroid/net/IIpSecService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Landroid/net/IIpSecService$Stub$Proxy;->addAddressToTunnelInterface(ILandroid/net/LinkAddress;Ljava/lang/String;)V
+Landroid/net/IIpSecService$Stub$Proxy;->allocateSecurityParameterIndex(Ljava/lang/String;ILandroid/os/IBinder;)Landroid/net/IpSecSpiResponse;
+Landroid/net/IIpSecService$Stub$Proxy;->applyTransportModeTransform(Landroid/os/ParcelFileDescriptor;II)V
+Landroid/net/IIpSecService$Stub$Proxy;->applyTunnelModeTransform(IIILjava/lang/String;)V
+Landroid/net/IIpSecService$Stub$Proxy;->closeUdpEncapsulationSocket(I)V
+Landroid/net/IIpSecService$Stub$Proxy;->createTransform(Landroid/net/IpSecConfig;Landroid/os/IBinder;Ljava/lang/String;)Landroid/net/IpSecTransformResponse;
+Landroid/net/IIpSecService$Stub$Proxy;->createTunnelInterface(Ljava/lang/String;Ljava/lang/String;Landroid/net/Network;Landroid/os/IBinder;Ljava/lang/String;)Landroid/net/IpSecTunnelInterfaceResponse;
+Landroid/net/IIpSecService$Stub$Proxy;->deleteTransform(I)V
+Landroid/net/IIpSecService$Stub$Proxy;->deleteTunnelInterface(ILjava/lang/String;)V
+Landroid/net/IIpSecService$Stub$Proxy;->getInterfaceDescriptor()Ljava/lang/String;
+Landroid/net/IIpSecService$Stub$Proxy;->mRemote:Landroid/os/IBinder;
+Landroid/net/IIpSecService$Stub$Proxy;->openUdpEncapsulationSocket(ILandroid/os/IBinder;)Landroid/net/IpSecUdpEncapResponse;
+Landroid/net/IIpSecService$Stub$Proxy;->releaseSecurityParameterIndex(I)V
+Landroid/net/IIpSecService$Stub$Proxy;->removeAddressFromTunnelInterface(ILandroid/net/LinkAddress;Ljava/lang/String;)V
+Landroid/net/IIpSecService$Stub$Proxy;->removeTransportModeTransforms(Landroid/os/ParcelFileDescriptor;)V
+Landroid/net/IIpSecService$Stub;-><init>()V
+Landroid/net/IIpSecService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/IIpSecService;
+Landroid/net/IIpSecService$Stub;->DESCRIPTOR:Ljava/lang/String;
+Landroid/net/IIpSecService$Stub;->TRANSACTION_addAddressToTunnelInterface:I
+Landroid/net/IIpSecService$Stub;->TRANSACTION_allocateSecurityParameterIndex:I
+Landroid/net/IIpSecService$Stub;->TRANSACTION_applyTransportModeTransform:I
+Landroid/net/IIpSecService$Stub;->TRANSACTION_applyTunnelModeTransform:I
+Landroid/net/IIpSecService$Stub;->TRANSACTION_closeUdpEncapsulationSocket:I
+Landroid/net/IIpSecService$Stub;->TRANSACTION_createTransform:I
+Landroid/net/IIpSecService$Stub;->TRANSACTION_createTunnelInterface:I
+Landroid/net/IIpSecService$Stub;->TRANSACTION_deleteTransform:I
+Landroid/net/IIpSecService$Stub;->TRANSACTION_deleteTunnelInterface:I
+Landroid/net/IIpSecService$Stub;->TRANSACTION_openUdpEncapsulationSocket:I
+Landroid/net/IIpSecService$Stub;->TRANSACTION_releaseSecurityParameterIndex:I
+Landroid/net/IIpSecService$Stub;->TRANSACTION_removeAddressFromTunnelInterface:I
+Landroid/net/IIpSecService$Stub;->TRANSACTION_removeTransportModeTransforms:I
+Landroid/net/IIpSecService;->addAddressToTunnelInterface(ILandroid/net/LinkAddress;Ljava/lang/String;)V
+Landroid/net/IIpSecService;->allocateSecurityParameterIndex(Ljava/lang/String;ILandroid/os/IBinder;)Landroid/net/IpSecSpiResponse;
+Landroid/net/IIpSecService;->applyTransportModeTransform(Landroid/os/ParcelFileDescriptor;II)V
+Landroid/net/IIpSecService;->applyTunnelModeTransform(IIILjava/lang/String;)V
+Landroid/net/IIpSecService;->closeUdpEncapsulationSocket(I)V
+Landroid/net/IIpSecService;->createTransform(Landroid/net/IpSecConfig;Landroid/os/IBinder;Ljava/lang/String;)Landroid/net/IpSecTransformResponse;
+Landroid/net/IIpSecService;->createTunnelInterface(Ljava/lang/String;Ljava/lang/String;Landroid/net/Network;Landroid/os/IBinder;Ljava/lang/String;)Landroid/net/IpSecTunnelInterfaceResponse;
+Landroid/net/IIpSecService;->deleteTransform(I)V
+Landroid/net/IIpSecService;->deleteTunnelInterface(ILjava/lang/String;)V
+Landroid/net/IIpSecService;->openUdpEncapsulationSocket(ILandroid/os/IBinder;)Landroid/net/IpSecUdpEncapResponse;
+Landroid/net/IIpSecService;->releaseSecurityParameterIndex(I)V
+Landroid/net/IIpSecService;->removeAddressFromTunnelInterface(ILandroid/net/LinkAddress;Ljava/lang/String;)V
+Landroid/net/IIpSecService;->removeTransportModeTransforms(Landroid/os/ParcelFileDescriptor;)V
+Landroid/net/IpSecAlgorithm;->checkValidOrThrow(Ljava/lang/String;II)V
+Landroid/net/IpSecAlgorithm;->CRYPT_NULL:Ljava/lang/String;
+Landroid/net/IpSecAlgorithm;->equals(Landroid/net/IpSecAlgorithm;Landroid/net/IpSecAlgorithm;)Z
+Landroid/net/IpSecAlgorithm;->isAead()Z
+Landroid/net/IpSecAlgorithm;->isAuthentication()Z
+Landroid/net/IpSecAlgorithm;->isEncryption()Z
+Landroid/net/IpSecAlgorithm;->isUnsafeBuild()Z
+Landroid/net/IpSecAlgorithm;->mKey:[B
+Landroid/net/IpSecAlgorithm;->mName:Ljava/lang/String;
+Landroid/net/IpSecAlgorithm;->mTruncLenBits:I
+Landroid/net/IpSecAlgorithm;->TAG:Ljava/lang/String;
+Landroid/net/IpSecConfig;-><init>()V
+Landroid/net/IpSecConfig;-><init>(Landroid/net/IpSecConfig;)V
+Landroid/net/IpSecConfig;-><init>(Landroid/os/Parcel;)V
+Landroid/net/IpSecConfig;->CREATOR:Landroid/os/Parcelable$Creator;
+Landroid/net/IpSecConfig;->equals(Landroid/net/IpSecConfig;Landroid/net/IpSecConfig;)Z
+Landroid/net/IpSecConfig;->getAuthenticatedEncryption()Landroid/net/IpSecAlgorithm;
+Landroid/net/IpSecConfig;->getAuthentication()Landroid/net/IpSecAlgorithm;
+Landroid/net/IpSecConfig;->getDestinationAddress()Ljava/lang/String;
+Landroid/net/IpSecConfig;->getEncapRemotePort()I
+Landroid/net/IpSecConfig;->getEncapSocketResourceId()I
+Landroid/net/IpSecConfig;->getEncapType()I
+Landroid/net/IpSecConfig;->getEncryption()Landroid/net/IpSecAlgorithm;
+Landroid/net/IpSecConfig;->getMarkMask()I
+Landroid/net/IpSecConfig;->getMarkValue()I
+Landroid/net/IpSecConfig;->getMode()I
+Landroid/net/IpSecConfig;->getNattKeepaliveInterval()I
+Landroid/net/IpSecConfig;->getNetwork()Landroid/net/Network;
+Landroid/net/IpSecConfig;->getSourceAddress()Ljava/lang/String;
+Landroid/net/IpSecConfig;->getSpiResourceId()I
+Landroid/net/IpSecConfig;->mAuthenticatedEncryption:Landroid/net/IpSecAlgorithm;
+Landroid/net/IpSecConfig;->mAuthentication:Landroid/net/IpSecAlgorithm;
+Landroid/net/IpSecConfig;->mDestinationAddress:Ljava/lang/String;
+Landroid/net/IpSecConfig;->mEncapRemotePort:I
+Landroid/net/IpSecConfig;->mEncapSocketResourceId:I
+Landroid/net/IpSecConfig;->mEncapType:I
+Landroid/net/IpSecConfig;->mEncryption:Landroid/net/IpSecAlgorithm;
+Landroid/net/IpSecConfig;->mMarkMask:I
+Landroid/net/IpSecConfig;->mMarkValue:I
+Landroid/net/IpSecConfig;->mMode:I
+Landroid/net/IpSecConfig;->mNattKeepaliveInterval:I
+Landroid/net/IpSecConfig;->mNetwork:Landroid/net/Network;
+Landroid/net/IpSecConfig;->mSourceAddress:Ljava/lang/String;
+Landroid/net/IpSecConfig;->mSpiResourceId:I
+Landroid/net/IpSecConfig;->setAuthenticatedEncryption(Landroid/net/IpSecAlgorithm;)V
+Landroid/net/IpSecConfig;->setAuthentication(Landroid/net/IpSecAlgorithm;)V
+Landroid/net/IpSecConfig;->setDestinationAddress(Ljava/lang/String;)V
+Landroid/net/IpSecConfig;->setEncapRemotePort(I)V
+Landroid/net/IpSecConfig;->setEncapSocketResourceId(I)V
+Landroid/net/IpSecConfig;->setEncapType(I)V
+Landroid/net/IpSecConfig;->setEncryption(Landroid/net/IpSecAlgorithm;)V
+Landroid/net/IpSecConfig;->setMarkMask(I)V
+Landroid/net/IpSecConfig;->setMarkValue(I)V
+Landroid/net/IpSecConfig;->setMode(I)V
+Landroid/net/IpSecConfig;->setNattKeepaliveInterval(I)V
+Landroid/net/IpSecConfig;->setNetwork(Landroid/net/Network;)V
+Landroid/net/IpSecConfig;->setSourceAddress(Ljava/lang/String;)V
+Landroid/net/IpSecConfig;->setSpiResourceId(I)V
+Landroid/net/IpSecConfig;->TAG:Ljava/lang/String;
+Landroid/net/IpSecManager$IpSecTunnelInterface;-><init>(Landroid/content/Context;Landroid/net/IIpSecService;Ljava/net/InetAddress;Ljava/net/InetAddress;Landroid/net/Network;)V
+Landroid/net/IpSecManager$IpSecTunnelInterface;->addAddress(Ljava/net/InetAddress;I)V
+Landroid/net/IpSecManager$IpSecTunnelInterface;->getInterfaceName()Ljava/lang/String;
+Landroid/net/IpSecManager$IpSecTunnelInterface;->getResourceId()I
+Landroid/net/IpSecManager$IpSecTunnelInterface;->mCloseGuard:Ldalvik/system/CloseGuard;
+Landroid/net/IpSecManager$IpSecTunnelInterface;->mInterfaceName:Ljava/lang/String;
+Landroid/net/IpSecManager$IpSecTunnelInterface;->mLocalAddress:Ljava/net/InetAddress;
+Landroid/net/IpSecManager$IpSecTunnelInterface;->mOpPackageName:Ljava/lang/String;
+Landroid/net/IpSecManager$IpSecTunnelInterface;->mRemoteAddress:Ljava/net/InetAddress;
+Landroid/net/IpSecManager$IpSecTunnelInterface;->mResourceId:I
+Landroid/net/IpSecManager$IpSecTunnelInterface;->mService:Landroid/net/IIpSecService;
+Landroid/net/IpSecManager$IpSecTunnelInterface;->mUnderlyingNetwork:Landroid/net/Network;
+Landroid/net/IpSecManager$IpSecTunnelInterface;->removeAddress(Ljava/net/InetAddress;I)V
+Landroid/net/IpSecManager$ResourceUnavailableException;-><init>(Ljava/lang/String;)V
+Landroid/net/IpSecManager$SecurityParameterIndex;-><init>(Landroid/net/IIpSecService;Ljava/net/InetAddress;I)V
+Landroid/net/IpSecManager$SecurityParameterIndex;->getResourceId()I
+Landroid/net/IpSecManager$SecurityParameterIndex;->mCloseGuard:Ldalvik/system/CloseGuard;
+Landroid/net/IpSecManager$SecurityParameterIndex;->mDestinationAddress:Ljava/net/InetAddress;
+Landroid/net/IpSecManager$SecurityParameterIndex;->mResourceId:I
+Landroid/net/IpSecManager$SecurityParameterIndex;->mService:Landroid/net/IIpSecService;
+Landroid/net/IpSecManager$SecurityParameterIndex;->mSpi:I
+Landroid/net/IpSecManager$SpiUnavailableException;-><init>(Ljava/lang/String;I)V
+Landroid/net/IpSecManager$SpiUnavailableException;->mSpi:I
+Landroid/net/IpSecManager$Status;->OK:I
+Landroid/net/IpSecManager$Status;->RESOURCE_UNAVAILABLE:I
+Landroid/net/IpSecManager$Status;->SPI_UNAVAILABLE:I
+Landroid/net/IpSecManager$UdpEncapsulationSocket;-><init>(Landroid/net/IIpSecService;I)V
+Landroid/net/IpSecManager$UdpEncapsulationSocket;->getResourceId()I
+Landroid/net/IpSecManager$UdpEncapsulationSocket;->mCloseGuard:Ldalvik/system/CloseGuard;
+Landroid/net/IpSecManager$UdpEncapsulationSocket;->mPfd:Landroid/os/ParcelFileDescriptor;
+Landroid/net/IpSecManager$UdpEncapsulationSocket;->mPort:I
+Landroid/net/IpSecManager$UdpEncapsulationSocket;->mResourceId:I
+Landroid/net/IpSecManager$UdpEncapsulationSocket;->mService:Landroid/net/IIpSecService;
+Landroid/net/IpSecManager;-><init>(Landroid/content/Context;Landroid/net/IIpSecService;)V
+Landroid/net/IpSecManager;->applyTunnelModeTransform(Landroid/net/IpSecManager$IpSecTunnelInterface;ILandroid/net/IpSecTransform;)V
+Landroid/net/IpSecManager;->createIpSecTunnelInterface(Ljava/net/InetAddress;Ljava/net/InetAddress;Landroid/net/Network;)Landroid/net/IpSecManager$IpSecTunnelInterface;
+Landroid/net/IpSecManager;->INVALID_RESOURCE_ID:I
+Landroid/net/IpSecManager;->maybeHandleServiceSpecificException(Landroid/os/ServiceSpecificException;)V
+Landroid/net/IpSecManager;->mContext:Landroid/content/Context;
+Landroid/net/IpSecManager;->mService:Landroid/net/IIpSecService;
+Landroid/net/IpSecManager;->removeTunnelModeTransform(Landroid/net/Network;Landroid/net/IpSecTransform;)V
+Landroid/net/IpSecManager;->rethrowCheckedExceptionFromServiceSpecificException(Landroid/os/ServiceSpecificException;)Ljava/io/IOException;
+Landroid/net/IpSecManager;->rethrowUncheckedExceptionFromServiceSpecificException(Landroid/os/ServiceSpecificException;)Ljava/lang/RuntimeException;
+Landroid/net/IpSecManager;->TAG:Ljava/lang/String;
+Landroid/net/IpSecSpiResponse;-><init>(I)V
+Landroid/net/IpSecSpiResponse;-><init>(III)V
+Landroid/net/IpSecSpiResponse;-><init>(Landroid/os/Parcel;)V
+Landroid/net/IpSecSpiResponse;->CREATOR:Landroid/os/Parcelable$Creator;
+Landroid/net/IpSecSpiResponse;->resourceId:I
+Landroid/net/IpSecSpiResponse;->spi:I
+Landroid/net/IpSecSpiResponse;->status:I
+Landroid/net/IpSecSpiResponse;->TAG:Ljava/lang/String;
+Landroid/net/IpSecTransform$Builder;->buildTunnelModeTransform(Ljava/net/InetAddress;Landroid/net/IpSecManager$SecurityParameterIndex;)Landroid/net/IpSecTransform;
+Landroid/net/IpSecTransform$Builder;->mConfig:Landroid/net/IpSecConfig;
+Landroid/net/IpSecTransform$Builder;->mContext:Landroid/content/Context;
+Landroid/net/IpSecTransform$NattKeepaliveCallback;-><init>()V
+Landroid/net/IpSecTransform$NattKeepaliveCallback;->ERROR_HARDWARE_ERROR:I
+Landroid/net/IpSecTransform$NattKeepaliveCallback;->ERROR_HARDWARE_UNSUPPORTED:I
+Landroid/net/IpSecTransform$NattKeepaliveCallback;->ERROR_INVALID_NETWORK:I
+Landroid/net/IpSecTransform$NattKeepaliveCallback;->onError(I)V
+Landroid/net/IpSecTransform$NattKeepaliveCallback;->onStarted()V
+Landroid/net/IpSecTransform$NattKeepaliveCallback;->onStopped()V
+Landroid/net/IpSecTransform;-><init>(Landroid/content/Context;Landroid/net/IpSecConfig;)V
+Landroid/net/IpSecTransform;->activate()Landroid/net/IpSecTransform;
+Landroid/net/IpSecTransform;->checkResultStatus(I)V
+Landroid/net/IpSecTransform;->ENCAP_ESPINUDP:I
+Landroid/net/IpSecTransform;->ENCAP_ESPINUDP_NON_IKE:I
+Landroid/net/IpSecTransform;->ENCAP_NONE:I
+Landroid/net/IpSecTransform;->equals(Landroid/net/IpSecTransform;Landroid/net/IpSecTransform;)Z
+Landroid/net/IpSecTransform;->getConfig()Landroid/net/IpSecConfig;
+Landroid/net/IpSecTransform;->getIpSecService()Landroid/net/IIpSecService;
+Landroid/net/IpSecTransform;->getResourceId()I
+Landroid/net/IpSecTransform;->mCallbackHandler:Landroid/os/Handler;
+Landroid/net/IpSecTransform;->mCloseGuard:Ldalvik/system/CloseGuard;
+Landroid/net/IpSecTransform;->mConfig:Landroid/net/IpSecConfig;
+Landroid/net/IpSecTransform;->mContext:Landroid/content/Context;
+Landroid/net/IpSecTransform;->mKeepalive:Landroid/net/ConnectivityManager$PacketKeepalive;
+Landroid/net/IpSecTransform;->mKeepaliveCallback:Landroid/net/ConnectivityManager$PacketKeepaliveCallback;
+Landroid/net/IpSecTransform;->MODE_TRANSPORT:I
+Landroid/net/IpSecTransform;->MODE_TUNNEL:I
+Landroid/net/IpSecTransform;->mResourceId:I
+Landroid/net/IpSecTransform;->mUserKeepaliveCallback:Landroid/net/IpSecTransform$NattKeepaliveCallback;
+Landroid/net/IpSecTransform;->startNattKeepalive(Landroid/net/IpSecTransform$NattKeepaliveCallback;ILandroid/os/Handler;)V
+Landroid/net/IpSecTransform;->stopNattKeepalive()V
+Landroid/net/IpSecTransform;->TAG:Ljava/lang/String;
+Landroid/net/IpSecTransformResponse;-><init>(I)V
+Landroid/net/IpSecTransformResponse;-><init>(II)V
+Landroid/net/IpSecTransformResponse;-><init>(Landroid/os/Parcel;)V
+Landroid/net/IpSecTransformResponse;->CREATOR:Landroid/os/Parcelable$Creator;
+Landroid/net/IpSecTransformResponse;->resourceId:I
+Landroid/net/IpSecTransformResponse;->status:I
+Landroid/net/IpSecTransformResponse;->TAG:Ljava/lang/String;
+Landroid/net/IpSecTunnelInterfaceResponse;-><init>(I)V
+Landroid/net/IpSecTunnelInterfaceResponse;-><init>(IILjava/lang/String;)V
+Landroid/net/IpSecTunnelInterfaceResponse;-><init>(Landroid/os/Parcel;)V
+Landroid/net/IpSecTunnelInterfaceResponse;->CREATOR:Landroid/os/Parcelable$Creator;
+Landroid/net/IpSecTunnelInterfaceResponse;->interfaceName:Ljava/lang/String;
+Landroid/net/IpSecTunnelInterfaceResponse;->resourceId:I
+Landroid/net/IpSecTunnelInterfaceResponse;->status:I
+Landroid/net/IpSecTunnelInterfaceResponse;->TAG:Ljava/lang/String;
+Landroid/net/IpSecUdpEncapResponse;-><init>(I)V
+Landroid/net/IpSecUdpEncapResponse;-><init>(IIILjava/io/FileDescriptor;)V
+Landroid/net/IpSecUdpEncapResponse;-><init>(Landroid/os/Parcel;)V
+Landroid/net/IpSecUdpEncapResponse;->CREATOR:Landroid/os/Parcelable$Creator;
+Landroid/net/IpSecUdpEncapResponse;->fileDescriptor:Landroid/os/ParcelFileDescriptor;
+Landroid/net/IpSecUdpEncapResponse;->port:I
+Landroid/net/IpSecUdpEncapResponse;->resourceId:I
+Landroid/net/IpSecUdpEncapResponse;->status:I
+Landroid/net/IpSecUdpEncapResponse;->TAG:Ljava/lang/String;
Landroid/net/nsd/DnsSdTxtRecord;-><init>()V
Landroid/net/nsd/DnsSdTxtRecord;-><init>(Landroid/net/nsd/DnsSdTxtRecord;)V
Landroid/net/nsd/DnsSdTxtRecord;-><init>([B)V
diff --git a/Tethering/apex/permissions/Android.bp b/Tethering/apex/permissions/Android.bp
new file mode 100644
index 0000000..ac9ec65
--- /dev/null
+++ b/Tethering/apex/permissions/Android.bp
@@ -0,0 +1,28 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+ default_visibility: ["//packages/modules/Connectivity/Tethering:__subpackages__"],
+}
+
+prebuilt_etc {
+ name: "privapp_allowlist_com.android.tethering",
+ sub_dir: "permissions",
+ filename: "permissions.xml",
+ src: "permissions.xml",
+ installable: false,
+}
\ No newline at end of file
diff --git a/Tethering/apex/permissions/OWNERS b/Tethering/apex/permissions/OWNERS
new file mode 100644
index 0000000..8b7e2e5
--- /dev/null
+++ b/Tethering/apex/permissions/OWNERS
@@ -0,0 +1,2 @@
+per-file *.xml,OWNERS = set noparent
+per-file *.xml,OWNERS = file:platform/frameworks/base:/data/etc/OWNERS
diff --git a/Tethering/apex/permissions/permissions.xml b/Tethering/apex/permissions/permissions.xml
new file mode 100644
index 0000000..f26a961
--- /dev/null
+++ b/Tethering/apex/permissions/permissions.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+-->
+
+<permissions>
+ <privapp-permissions package="com.android.networkstack.tethering">
+ <permission name="android.permission.BLUETOOTH_PRIVILEGED" />
+ <permission name="android.permission.MANAGE_USB"/>
+ <permission name="android.permission.MODIFY_PHONE_STATE"/>
+ <permission name="android.permission.READ_NETWORK_USAGE_HISTORY"/>
+ <permission name="android.permission.TETHER_PRIVILEGED"/>
+ <permission name="android.permission.UPDATE_APP_OPS_STATS"/>
+ <permission name="android.permission.UPDATE_DEVICE_STATS"/>
+ </privapp-permissions>
+</permissions>
diff --git a/Tethering/apishim/30/com/android/networkstack/tethering/apishim/api30/BpfCoordinatorShimImpl.java b/Tethering/apishim/30/com/android/networkstack/tethering/apishim/api30/BpfCoordinatorShimImpl.java
index a33af61..26040a2 100644
--- a/Tethering/apishim/30/com/android/networkstack/tethering/apishim/api30/BpfCoordinatorShimImpl.java
+++ b/Tethering/apishim/30/com/android/networkstack/tethering/apishim/api30/BpfCoordinatorShimImpl.java
@@ -27,10 +27,10 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.net.module.util.bpf.Tether4Key;
+import com.android.net.module.util.bpf.Tether4Value;
import com.android.networkstack.tethering.BpfCoordinator.Dependencies;
import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule;
-import com.android.networkstack.tethering.Tether4Key;
-import com.android.networkstack.tethering.Tether4Value;
import com.android.networkstack.tethering.TetherStatsValue;
import java.util.function.BiConsumer;
diff --git a/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java b/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java
index 7189933..e3b1539 100644
--- a/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java
+++ b/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java
@@ -30,11 +30,11 @@
import androidx.annotation.Nullable;
import com.android.net.module.util.BpfMap;
+import com.android.net.module.util.bpf.Tether4Key;
+import com.android.net.module.util.bpf.Tether4Value;
import com.android.networkstack.tethering.BpfCoordinator.Dependencies;
import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule;
import com.android.networkstack.tethering.BpfUtils;
-import com.android.networkstack.tethering.Tether4Key;
-import com.android.networkstack.tethering.Tether4Value;
import com.android.networkstack.tethering.Tether6Value;
import com.android.networkstack.tethering.TetherDevKey;
import com.android.networkstack.tethering.TetherDevValue;
diff --git a/Tethering/apishim/common/com/android/networkstack/tethering/apishim/common/BpfCoordinatorShim.java b/Tethering/apishim/common/com/android/networkstack/tethering/apishim/common/BpfCoordinatorShim.java
index 08ab9ca..d663968 100644
--- a/Tethering/apishim/common/com/android/networkstack/tethering/apishim/common/BpfCoordinatorShim.java
+++ b/Tethering/apishim/common/com/android/networkstack/tethering/apishim/common/BpfCoordinatorShim.java
@@ -22,10 +22,10 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.net.module.util.bpf.Tether4Key;
+import com.android.net.module.util.bpf.Tether4Value;
import com.android.networkstack.tethering.BpfCoordinator.Dependencies;
import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule;
-import com.android.networkstack.tethering.Tether4Key;
-import com.android.networkstack.tethering.Tether4Value;
import com.android.networkstack.tethering.TetherStatsValue;
import java.util.function.BiConsumer;
diff --git a/Tethering/common/TetheringLib/Android.bp b/Tethering/common/TetheringLib/Android.bp
index c82a993..9ca3f14 100644
--- a/Tethering/common/TetheringLib/Android.bp
+++ b/Tethering/common/TetheringLib/Android.bp
@@ -26,13 +26,18 @@
// Using for test only
"//cts/tests/netlegacy22.api",
"//external/sl4a:__subpackages__",
+ "//frameworks/base/core/tests/bandwidthtests",
+ "//frameworks/base/core/tests/benchmarks",
+ "//frameworks/base/core/tests/utillib",
"//frameworks/base/packages/Connectivity/tests:__subpackages__",
+ "//frameworks/base/tests/vcn",
"//frameworks/libs/net/common/testutils",
"//frameworks/libs/net/common/tests:__subpackages__",
"//frameworks/opt/telephony/tests/telephonytests",
"//packages/modules/CaptivePortalLogin/tests",
"//packages/modules/Connectivity/Tethering/tests:__subpackages__",
"//packages/modules/Connectivity/tests:__subpackages__",
+ "//packages/modules/IPsec/tests/iketests",
"//packages/modules/NetworkStack/tests:__subpackages__",
"//packages/modules/Wifi/service/tests/wifitests",
],
diff --git a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
index 8c8a2fd..6550de2 100644
--- a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
+++ b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
@@ -52,6 +52,7 @@
import android.system.OsConstants;
import android.text.TextUtils;
import android.util.ArraySet;
+import android.util.Base64;
import android.util.Log;
import android.util.SparseArray;
@@ -65,6 +66,8 @@
import com.android.net.module.util.CollectionUtils;
import com.android.net.module.util.NetworkStackConstants;
import com.android.net.module.util.Struct;
+import com.android.net.module.util.bpf.Tether4Key;
+import com.android.net.module.util.bpf.Tether4Value;
import com.android.net.module.util.netlink.ConntrackMessage;
import com.android.net.module.util.netlink.NetlinkConstants;
import com.android.net.module.util.netlink.NetlinkSocket;
@@ -116,6 +119,9 @@
private static final String TETHER_ERROR_MAP_PATH = makeMapPath("error");
private static final String TETHER_DEV_MAP_PATH = makeMapPath("dev");
+ // Using "," as a separator is safe because base64 characters are [0-9a-zA-Z/=+].
+ private static final String DUMP_BASE64_DELIMITER = ",";
+
/** The names of all the BPF counters defined in bpf_tethering.h. */
public static final String[] sBpfCounterNames = getBpfCounterNames();
@@ -1066,6 +1072,42 @@
}
}
+ private String ipv4RuleToBase64String(Tether4Key key, Tether4Value value) {
+ final byte[] keyBytes = key.writeToBytes();
+ final String keyBase64Str = Base64.encodeToString(keyBytes, Base64.DEFAULT)
+ .replace("\n", "");
+ final byte[] valueBytes = value.writeToBytes();
+ final String valueBase64Str = Base64.encodeToString(valueBytes, Base64.DEFAULT)
+ .replace("\n", "");
+
+ return keyBase64Str + DUMP_BASE64_DELIMITER + valueBase64Str;
+ }
+
+ private void dumpRawIpv4ForwardingRuleMap(
+ BpfMap<Tether4Key, Tether4Value> map, IndentingPrintWriter pw) throws ErrnoException {
+ if (map == null) {
+ pw.println("No IPv4 support");
+ return;
+ }
+ if (map.isEmpty()) {
+ pw.println("No rules");
+ return;
+ }
+ map.forEach((k, v) -> pw.println(ipv4RuleToBase64String(k, v)));
+ }
+
+ /**
+ * Dump raw BPF map in base64 encoded strings. For test only.
+ */
+ public void dumpRawMap(@NonNull IndentingPrintWriter pw) {
+ try (BpfMap<Tether4Key, Tether4Value> upstreamMap = mDeps.getBpfUpstream4Map()) {
+ // TODO: dump downstream map.
+ dumpRawIpv4ForwardingRuleMap(upstreamMap, pw);
+ } catch (ErrnoException e) {
+ pw.println("Error dumping IPv4 map: " + e);
+ }
+ }
+
private String l4protoToString(int proto) {
if (proto == OsConstants.IPPROTO_TCP) {
return "tcp";
diff --git a/Tethering/src/com/android/networkstack/tethering/Tether4Key.java b/Tethering/src/com/android/networkstack/tethering/Tether4Key.java
deleted file mode 100644
index a01ea34..0000000
--- a/Tethering/src/com/android/networkstack/tethering/Tether4Key.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.networkstack.tethering;
-
-import android.net.MacAddress;
-
-import androidx.annotation.NonNull;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-import java.net.Inet4Address;
-import java.net.UnknownHostException;
-import java.util.Objects;
-
-/** Key type for downstream & upstream IPv4 forwarding maps. */
-public class Tether4Key extends Struct {
- @Field(order = 0, type = Type.U32)
- public final long iif;
-
- @Field(order = 1, type = Type.EUI48)
- public final MacAddress dstMac;
-
- @Field(order = 2, type = Type.U8, padding = 1)
- public final short l4proto;
-
- @Field(order = 3, type = Type.ByteArray, arraysize = 4)
- public final byte[] src4;
-
- @Field(order = 4, type = Type.ByteArray, arraysize = 4)
- public final byte[] dst4;
-
- @Field(order = 5, type = Type.UBE16)
- public final int srcPort;
-
- @Field(order = 6, type = Type.UBE16)
- public final int dstPort;
-
- public Tether4Key(final long iif, @NonNull final MacAddress dstMac, final short l4proto,
- final byte[] src4, final byte[] dst4, final int srcPort,
- final int dstPort) {
- Objects.requireNonNull(dstMac);
-
- this.iif = iif;
- this.dstMac = dstMac;
- this.l4proto = l4proto;
- this.src4 = src4;
- this.dst4 = dst4;
- this.srcPort = srcPort;
- this.dstPort = dstPort;
- }
-
- @Override
- public String toString() {
- try {
- return String.format(
- "iif: %d, dstMac: %s, l4proto: %d, src4: %s, dst4: %s, "
- + "srcPort: %d, dstPort: %d",
- iif, dstMac, l4proto,
- Inet4Address.getByAddress(src4), Inet4Address.getByAddress(dst4),
- Short.toUnsignedInt((short) srcPort), Short.toUnsignedInt((short) dstPort));
- } catch (UnknownHostException | IllegalArgumentException e) {
- return String.format("Invalid IP address", e);
- }
- }
-}
diff --git a/Tethering/src/com/android/networkstack/tethering/Tether4Value.java b/Tethering/src/com/android/networkstack/tethering/Tether4Value.java
deleted file mode 100644
index 03a226c..0000000
--- a/Tethering/src/com/android/networkstack/tethering/Tether4Value.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.networkstack.tethering;
-
-import android.net.MacAddress;
-
-import androidx.annotation.NonNull;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.Objects;
-
-/** Value type for downstream & upstream IPv4 forwarding maps. */
-public class Tether4Value extends Struct {
- @Field(order = 0, type = Type.U32)
- public final long oif;
-
- // The ethhdr struct which is defined in uapi/linux/if_ether.h
- @Field(order = 1, type = Type.EUI48)
- public final MacAddress ethDstMac;
- @Field(order = 2, type = Type.EUI48)
- public final MacAddress ethSrcMac;
- @Field(order = 3, type = Type.UBE16)
- public final int ethProto; // Packet type ID field.
-
- @Field(order = 4, type = Type.U16)
- public final int pmtu;
-
- @Field(order = 5, type = Type.ByteArray, arraysize = 16)
- public final byte[] src46;
-
- @Field(order = 6, type = Type.ByteArray, arraysize = 16)
- public final byte[] dst46;
-
- @Field(order = 7, type = Type.UBE16)
- public final int srcPort;
-
- @Field(order = 8, type = Type.UBE16)
- public final int dstPort;
-
- // TODO: consider using U64.
- @Field(order = 9, type = Type.U63)
- public final long lastUsed;
-
- public Tether4Value(final long oif, @NonNull final MacAddress ethDstMac,
- @NonNull final MacAddress ethSrcMac, final int ethProto, final int pmtu,
- final byte[] src46, final byte[] dst46, final int srcPort,
- final int dstPort, final long lastUsed) {
- Objects.requireNonNull(ethDstMac);
- Objects.requireNonNull(ethSrcMac);
-
- this.oif = oif;
- this.ethDstMac = ethDstMac;
- this.ethSrcMac = ethSrcMac;
- this.ethProto = ethProto;
- this.pmtu = pmtu;
- this.src46 = src46;
- this.dst46 = dst46;
- this.srcPort = srcPort;
- this.dstPort = dstPort;
- this.lastUsed = lastUsed;
- }
-
- @Override
- public String toString() {
- try {
- return String.format(
- "oif: %d, ethDstMac: %s, ethSrcMac: %s, ethProto: %d, pmtu: %d, "
- + "src46: %s, dst46: %s, srcPort: %d, dstPort: %d, "
- + "lastUsed: %d",
- oif, ethDstMac, ethSrcMac, ethProto, pmtu,
- InetAddress.getByAddress(src46), InetAddress.getByAddress(dst46),
- Short.toUnsignedInt((short) srcPort), Short.toUnsignedInt((short) dstPort),
- lastUsed);
- } catch (UnknownHostException | IllegalArgumentException e) {
- return String.format("Invalid IP address", e);
- }
- }
-}
diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java
index db9a64f..301a682 100644
--- a/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -2479,6 +2479,13 @@
@SuppressWarnings("resource") final IndentingPrintWriter pw = new IndentingPrintWriter(
writer, " ");
+ // Used for testing instead of human debug.
+ // TODO: add options to choose which map to dump.
+ if (argsContain(args, "bpfRawMap")) {
+ mBpfCoordinator.dumpRawMap(pw);
+ return;
+ }
+
if (argsContain(args, "bpf")) {
dumpBpf(pw);
return;
diff --git a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
index 267c376..a3c46c2 100644
--- a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
+++ b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
@@ -101,11 +101,11 @@
import com.android.net.module.util.BpfMap;
import com.android.net.module.util.NetworkStackConstants;
+import com.android.net.module.util.bpf.Tether4Key;
+import com.android.net.module.util.bpf.Tether4Value;
import com.android.networkstack.tethering.BpfCoordinator;
import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule;
import com.android.networkstack.tethering.PrivateAddressCoordinator;
-import com.android.networkstack.tethering.Tether4Key;
-import com.android.networkstack.tethering.Tether4Value;
import com.android.networkstack.tethering.Tether6Value;
import com.android.networkstack.tethering.TetherDevKey;
import com.android.networkstack.tethering.TetherDevValue;
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
index d51f6fd..6c7a66d 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
@@ -99,6 +99,8 @@
import com.android.net.module.util.BpfMap;
import com.android.net.module.util.CollectionUtils;
import com.android.net.module.util.NetworkStackConstants;
+import com.android.net.module.util.bpf.Tether4Key;
+import com.android.net.module.util.bpf.Tether4Value;
import com.android.net.module.util.netlink.ConntrackMessage;
import com.android.net.module.util.netlink.NetlinkConstants;
import com.android.net.module.util.netlink.NetlinkSocket;
diff --git a/bpf_progs/netd.c b/bpf_progs/netd.c
index c1a74e7..8d05757 100644
--- a/bpf_progs/netd.c
+++ b/bpf_progs/netd.c
@@ -297,12 +297,12 @@
return match;
}
-DEFINE_BPF_PROG("cgroupskb/ingress/stats", AID_ROOT, AID_ROOT, bpf_cgroup_ingress)
+DEFINE_BPF_PROG("cgroupskb/ingress/stats", AID_ROOT, AID_SYSTEM, bpf_cgroup_ingress)
(struct __sk_buff* skb) {
return bpf_traffic_account(skb, BPF_INGRESS);
}
-DEFINE_BPF_PROG("cgroupskb/egress/stats", AID_ROOT, AID_ROOT, bpf_cgroup_egress)
+DEFINE_BPF_PROG("cgroupskb/egress/stats", AID_ROOT, AID_SYSTEM, bpf_cgroup_egress)
(struct __sk_buff* skb) {
return bpf_traffic_account(skb, BPF_EGRESS);
}
diff --git a/framework-t/Android.bp b/framework-t/Android.bp
index b5aedeb..50a3eb2 100644
--- a/framework-t/Android.bp
+++ b/framework-t/Android.bp
@@ -29,22 +29,17 @@
// SDK library for connectivity bootclasspath classes that were part of the non-updatable API before
// T, and were moved to the module in T. Other bootclasspath classes in connectivity should go to
// framework-connectivity.
-java_sdk_library {
- name: "framework-connectivity-tiramisu",
+java_defaults {
+ name: "framework-connectivity-tiramisu-defaults",
sdk_version: "module_current",
min_sdk_version: "Tiramisu",
defaults: [
"framework-module-defaults",
- "enable-framework-connectivity-t-targets",
],
srcs: [
":framework-connectivity-tiramisu-updatable-sources",
":framework-nearby-java-sources",
],
- // Do not add static_libs to this library: put them in framework-connectivity instead.
- // The jarjar rules are only so that references to jarjared utils in
- // framework-connectivity-pre-jarjar match at runtime.
- jarjar_rules: ":connectivity-jarjar-rules",
stub_only_libs: [
// Use prebuilt framework-connectivity stubs to avoid circular dependencies
"sdk_module-lib_current_framework-connectivity",
@@ -67,6 +62,43 @@
// non-jarjard names of widely-used packages such as com.android.net.module.util.
"framework-connectivity-pre-jarjar",
],
+ aidl: {
+ generate_get_transaction_name: true,
+ include_dirs: [
+ // For connectivity-framework classes such as Network.aidl,
+ // and connectivity-framework-t classes such as
+ // NetworkStateSnapshot.aidl
+ "packages/modules/Connectivity/framework/aidl-export",
+ ],
+ },
+ apex_available: [
+ "com.android.tethering",
+ ],
+}
+
+java_library {
+ name: "framework-connectivity-tiramisu-pre-jarjar",
+ defaults: ["framework-connectivity-tiramisu-defaults"],
+ libs: [
+ "framework-bluetooth",
+ "framework-connectivity-pre-jarjar",
+ ],
+ visibility: ["//packages/modules/Connectivity:__subpackages__"],
+}
+
+// SDK library for connectivity bootclasspath classes that were part of the non-updatable API before
+// T, and were moved to the module in T. Other bootclasspath classes in connectivity should go to
+// framework-connectivity.
+java_sdk_library {
+ name: "framework-connectivity-tiramisu",
+ defaults: [
+ "framework-connectivity-tiramisu-defaults",
+ "enable-framework-connectivity-t-targets",
+ ],
+ // Do not add static_libs to this library: put them in framework-connectivity instead.
+ // The jarjar rules are only so that references to jarjared utils in
+ // framework-connectivity-pre-jarjar match at runtime.
+ jarjar_rules: ":connectivity-jarjar-rules",
permitted_packages: [
"android.net",
"android.net.nsd",
@@ -74,9 +106,6 @@
"com.android.connectivity",
"com.android.nearby",
],
- apex_available: [
- "com.android.tethering",
- ],
impl_library_visibility: [
"//packages/modules/Connectivity/Tethering/apex",
// In preparation for future move
@@ -89,12 +118,17 @@
"//cts/tests/netlegacy22.api",
"//cts/tests/tests/app.usage", // NetworkUsageStatsTest
"//external/sl4a:__subpackages__",
+ "//frameworks/base/core/tests/bandwidthtests",
+ "//frameworks/base/core/tests/benchmarks",
+ "//frameworks/base/core/tests/utillib",
+ "//frameworks/base/tests/vcn",
"//frameworks/libs/net/common/testutils",
"//frameworks/libs/net/common/tests:__subpackages__",
"//frameworks/opt/telephony/tests/telephonytests",
"//packages/modules/CaptivePortalLogin/tests",
"//packages/modules/Connectivity/Tethering/tests:__subpackages__",
"//packages/modules/Connectivity/tests:__subpackages__",
+ "//packages/modules/IPsec/tests/iketests",
"//packages/modules/NetworkStack/tests:__subpackages__",
"//packages/modules/Nearby/tests:__subpackages__",
"//packages/modules/Wifi/service/tests/wifitests",
diff --git a/framework-t/api/OWNERS b/framework-t/api/OWNERS
new file mode 100644
index 0000000..de0f905
--- /dev/null
+++ b/framework-t/api/OWNERS
@@ -0,0 +1 @@
+file:platform/packages/modules/Connectivity:master:/nearby/OWNERS
diff --git a/framework-t/api/current.txt b/framework-t/api/current.txt
index 7977cc5..1389ff2 100644
--- a/framework-t/api/current.txt
+++ b/framework-t/api/current.txt
@@ -1,4 +1,77 @@
// Signature format: 2.0
+package android.net {
+
+ public final class IpSecAlgorithm implements android.os.Parcelable {
+ ctor public IpSecAlgorithm(@NonNull String, @NonNull byte[]);
+ ctor public IpSecAlgorithm(@NonNull String, @NonNull byte[], int);
+ method public int describeContents();
+ method @NonNull public byte[] getKey();
+ method @NonNull public String getName();
+ method @NonNull public static java.util.Set<java.lang.String> getSupportedAlgorithms();
+ method public int getTruncationLengthBits();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final String AUTH_AES_CMAC = "cmac(aes)";
+ field public static final String AUTH_AES_XCBC = "xcbc(aes)";
+ field public static final String AUTH_CRYPT_AES_GCM = "rfc4106(gcm(aes))";
+ field public static final String AUTH_CRYPT_CHACHA20_POLY1305 = "rfc7539esp(chacha20,poly1305)";
+ field public static final String AUTH_HMAC_MD5 = "hmac(md5)";
+ field public static final String AUTH_HMAC_SHA1 = "hmac(sha1)";
+ field public static final String AUTH_HMAC_SHA256 = "hmac(sha256)";
+ field public static final String AUTH_HMAC_SHA384 = "hmac(sha384)";
+ field public static final String AUTH_HMAC_SHA512 = "hmac(sha512)";
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.IpSecAlgorithm> CREATOR;
+ field public static final String CRYPT_AES_CBC = "cbc(aes)";
+ field public static final String CRYPT_AES_CTR = "rfc3686(ctr(aes))";
+ }
+
+ public class IpSecManager {
+ method @NonNull public android.net.IpSecManager.SecurityParameterIndex allocateSecurityParameterIndex(@NonNull java.net.InetAddress) throws android.net.IpSecManager.ResourceUnavailableException;
+ method @NonNull public android.net.IpSecManager.SecurityParameterIndex allocateSecurityParameterIndex(@NonNull java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
+ method public void applyTransportModeTransform(@NonNull java.net.Socket, int, @NonNull android.net.IpSecTransform) throws java.io.IOException;
+ method public void applyTransportModeTransform(@NonNull java.net.DatagramSocket, int, @NonNull android.net.IpSecTransform) throws java.io.IOException;
+ method public void applyTransportModeTransform(@NonNull java.io.FileDescriptor, int, @NonNull android.net.IpSecTransform) throws java.io.IOException;
+ method @NonNull public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket(int) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
+ method @NonNull public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
+ method public void removeTransportModeTransforms(@NonNull java.net.Socket) throws java.io.IOException;
+ method public void removeTransportModeTransforms(@NonNull java.net.DatagramSocket) throws java.io.IOException;
+ method public void removeTransportModeTransforms(@NonNull java.io.FileDescriptor) throws java.io.IOException;
+ field public static final int DIRECTION_IN = 0; // 0x0
+ field public static final int DIRECTION_OUT = 1; // 0x1
+ }
+
+ public static final class IpSecManager.ResourceUnavailableException extends android.util.AndroidException {
+ }
+
+ public static final class IpSecManager.SecurityParameterIndex implements java.lang.AutoCloseable {
+ method public void close();
+ method public int getSpi();
+ }
+
+ public static final class IpSecManager.SpiUnavailableException extends android.util.AndroidException {
+ method public int getSpi();
+ }
+
+ public static final class IpSecManager.UdpEncapsulationSocket implements java.lang.AutoCloseable {
+ method public void close() throws java.io.IOException;
+ method public java.io.FileDescriptor getFileDescriptor();
+ method public int getPort();
+ }
+
+ public final class IpSecTransform implements java.lang.AutoCloseable {
+ method public void close();
+ }
+
+ public static class IpSecTransform.Builder {
+ ctor public IpSecTransform.Builder(@NonNull android.content.Context);
+ method @NonNull public android.net.IpSecTransform buildTransportModeTransform(@NonNull java.net.InetAddress, @NonNull android.net.IpSecManager.SecurityParameterIndex) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
+ method @NonNull public android.net.IpSecTransform.Builder setAuthenticatedEncryption(@NonNull android.net.IpSecAlgorithm);
+ method @NonNull public android.net.IpSecTransform.Builder setAuthentication(@NonNull android.net.IpSecAlgorithm);
+ method @NonNull public android.net.IpSecTransform.Builder setEncryption(@NonNull android.net.IpSecAlgorithm);
+ method @NonNull public android.net.IpSecTransform.Builder setIpv4Encapsulation(@NonNull android.net.IpSecManager.UdpEncapsulationSocket, int);
+ }
+
+}
+
package android.net.nsd {
public final class NsdManager {
diff --git a/framework-t/api/lint-baseline.txt b/framework-t/api/lint-baseline.txt
new file mode 100644
index 0000000..1e30747
--- /dev/null
+++ b/framework-t/api/lint-baseline.txt
@@ -0,0 +1,7 @@
+// Baseline format: 1.0
+GenericException: android.net.IpSecManager.SecurityParameterIndex#finalize():
+ Methods must not throw generic exceptions (`java.lang.Throwable`)
+GenericException: android.net.IpSecManager.UdpEncapsulationSocket#finalize():
+ Methods must not throw generic exceptions (`java.lang.Throwable`)
+GenericException: android.net.IpSecTransform#finalize():
+ Methods must not throw generic exceptions (`java.lang.Throwable`)
diff --git a/framework-t/api/module-lib-current.txt b/framework-t/api/module-lib-current.txt
index 81d89c6..2ff3451 100644
--- a/framework-t/api/module-lib-current.txt
+++ b/framework-t/api/module-lib-current.txt
@@ -5,5 +5,13 @@
method public static void registerServiceWrappers();
}
+ public class IpSecManager {
+ field public static final int DIRECTION_FWD = 2; // 0x2
+ }
+
+ public static final class IpSecManager.UdpEncapsulationSocket implements java.lang.AutoCloseable {
+ method public int getResourceId();
+ }
+
}
diff --git a/framework-t/api/system-current.txt b/framework-t/api/system-current.txt
index d802177..041bcaf 100644
--- a/framework-t/api/system-current.txt
+++ b/framework-t/api/system-current.txt
@@ -1 +1,22 @@
// Signature format: 2.0
+package android.net {
+
+ public class IpSecManager {
+ method @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void applyTunnelModeTransform(@NonNull android.net.IpSecManager.IpSecTunnelInterface, int, @NonNull android.net.IpSecTransform) throws java.io.IOException;
+ method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public android.net.IpSecManager.IpSecTunnelInterface createIpSecTunnelInterface(@NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull android.net.Network) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
+ }
+
+ public static final class IpSecManager.IpSecTunnelInterface implements java.lang.AutoCloseable {
+ method @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void addAddress(@NonNull java.net.InetAddress, int) throws java.io.IOException;
+ method public void close();
+ method @NonNull public String getInterfaceName();
+ method @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void removeAddress(@NonNull java.net.InetAddress, int) throws java.io.IOException;
+ method @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void setUnderlyingNetwork(@NonNull android.net.Network) throws java.io.IOException;
+ }
+
+ public static class IpSecTransform.Builder {
+ method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public android.net.IpSecTransform buildTunnelModeTransform(@NonNull java.net.InetAddress, @NonNull android.net.IpSecManager.SecurityParameterIndex) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
+ }
+
+}
+
diff --git a/framework-t/api/system-lint-baseline.txt b/framework-t/api/system-lint-baseline.txt
new file mode 100644
index 0000000..9baf991
--- /dev/null
+++ b/framework-t/api/system-lint-baseline.txt
@@ -0,0 +1,7 @@
+// Baseline format: 1.0
+BuilderSetStyle: android.net.IpSecTransform.Builder#buildTunnelModeTransform(java.net.InetAddress, android.net.IpSecManager.SecurityParameterIndex):
+ Builder methods names should use setFoo() / addFoo() / clearFoo() style: method android.net.IpSecTransform.Builder.buildTunnelModeTransform(java.net.InetAddress,android.net.IpSecManager.SecurityParameterIndex)
+
+
+GenericException: android.net.IpSecManager.IpSecTunnelInterface#finalize():
+ Methods must not throw generic exceptions (`java.lang.Throwable`)
diff --git a/framework/Android.bp b/framework/Android.bp
index d3e46fa..da16a8d 100644
--- a/framework/Android.bp
+++ b/framework/Android.bp
@@ -131,12 +131,17 @@
"//cts/tests/tests/app.usage", // NetworkUsageStatsTest
"//external/sl4a:__subpackages__",
"//frameworks/base/packages/Connectivity/tests:__subpackages__",
+ "//frameworks/base/core/tests/bandwidthtests",
+ "//frameworks/base/core/tests/benchmarks",
+ "//frameworks/base/core/tests/utillib",
+ "//frameworks/base/tests/vcn",
"//frameworks/libs/net/common/testutils",
"//frameworks/libs/net/common/tests:__subpackages__",
"//frameworks/opt/telephony/tests/telephonytests",
"//packages/modules/CaptivePortalLogin/tests",
"//packages/modules/Connectivity/Tethering/tests:__subpackages__",
"//packages/modules/Connectivity/tests:__subpackages__",
+ "//packages/modules/IPsec/tests/iketests",
"//packages/modules/NetworkStack/tests:__subpackages__",
"//packages/modules/Wifi/service/tests/wifitests",
],
diff --git a/framework/aidl-export/android/net/NetworkAgentConfig.aidl b/framework/aidl-export/android/net/NetworkAgentConfig.aidl
index cb70bdd..02d50b7 100644
--- a/framework/aidl-export/android/net/NetworkAgentConfig.aidl
+++ b/framework/aidl-export/android/net/NetworkAgentConfig.aidl
@@ -16,4 +16,4 @@
package android.net;
-parcelable NetworkAgentConfig;
+@JavaOnlyStableParcelable parcelable NetworkAgentConfig;
diff --git a/framework/aidl-export/android/net/NetworkStateSnapshot.aidl b/framework/aidl-export/android/net/NetworkStateSnapshot.aidl
new file mode 100644
index 0000000..cb602d7
--- /dev/null
+++ b/framework/aidl-export/android/net/NetworkStateSnapshot.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+parcelable NetworkStateSnapshot;
diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt
index 5961e72..5579db6 100644
--- a/framework/api/module-lib-current.txt
+++ b/framework/api/module-lib-current.txt
@@ -10,6 +10,8 @@
method @NonNull @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public java.util.List<android.net.NetworkStateSnapshot> getAllNetworkStateSnapshots();
method @Nullable public android.net.ProxyInfo getGlobalProxy();
method @NonNull public static android.util.Range<java.lang.Integer> getIpSecNetIdRange();
+ method @Nullable @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public android.net.LinkProperties redactLinkPropertiesForPackage(@NonNull android.net.LinkProperties, int, @NonNull String);
+ method @Nullable @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public android.net.NetworkCapabilities redactNetworkCapabilitiesForPackage(@NonNull android.net.NetworkCapabilities, int, @NonNull String);
method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerDefaultNetworkCallbackForUid(int, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void replaceFirewallChain(int, @NonNull int[]);
@@ -69,6 +71,7 @@
method @NonNull public static java.time.Duration getDnsResolverSampleValidityDuration(@NonNull android.content.Context, @NonNull java.time.Duration);
method public static int getDnsResolverSuccessThresholdPercent(@NonNull android.content.Context, int);
method @Nullable public static android.net.ProxyInfo getGlobalProxy(@NonNull android.content.Context);
+ method public static long getIngressRateLimitInBytesPerSecond(@NonNull android.content.Context);
method @NonNull public static java.time.Duration getMobileDataActivityTimeout(@NonNull android.content.Context, @NonNull java.time.Duration);
method public static boolean getMobileDataAlwaysOn(@NonNull android.content.Context, boolean);
method @NonNull public static java.util.Set<java.lang.Integer> getMobileDataPreferredUids(@NonNull android.content.Context);
@@ -89,6 +92,7 @@
method public static void setDnsResolverSampleValidityDuration(@NonNull android.content.Context, @NonNull java.time.Duration);
method public static void setDnsResolverSuccessThresholdPercent(@NonNull android.content.Context, @IntRange(from=0, to=100) int);
method public static void setGlobalProxy(@NonNull android.content.Context, @NonNull android.net.ProxyInfo);
+ method public static void setIngressRateLimitInBytesPerSecond(@NonNull android.content.Context, @IntRange(from=0xffffffff, to=java.lang.Integer.MAX_VALUE) long);
method public static void setMobileDataActivityTimeout(@NonNull android.content.Context, @NonNull java.time.Duration);
method public static void setMobileDataAlwaysOn(@NonNull android.content.Context, boolean);
method public static void setMobileDataPreferredUids(@NonNull android.content.Context, @NonNull java.util.Set<java.lang.Integer>);
@@ -124,13 +128,15 @@
public final class NetworkAgentConfig implements android.os.Parcelable {
method @Nullable public String getSubscriberId();
+ method public boolean getVpnRequiresValidation();
method public boolean isBypassableVpn();
}
public static final class NetworkAgentConfig.Builder {
method @NonNull public android.net.NetworkAgentConfig.Builder setBypassableVpn(boolean);
- method @NonNull public android.net.NetworkAgentConfig.Builder setExcludeLocalRoutesVpn(boolean);
+ method @NonNull public android.net.NetworkAgentConfig.Builder setLocalRoutesExcludedForVpn(boolean);
method @NonNull public android.net.NetworkAgentConfig.Builder setSubscriberId(@Nullable String);
+ method @NonNull public android.net.NetworkAgentConfig.Builder setVpnRequiresValidation(boolean);
}
public final class NetworkCapabilities implements android.os.Parcelable {
diff --git a/framework/api/module-lib-lint-baseline.txt b/framework/api/module-lib-lint-baseline.txt
deleted file mode 100644
index c7b0db5..0000000
--- a/framework/api/module-lib-lint-baseline.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-// Baseline format: 1.0
-NoByteOrShort: android.net.DhcpOption#DhcpOption(byte, byte[]) parameter #0:
- Should avoid odd sized primitives; use `int` instead of `byte` in parameter type in android.net.DhcpOption(byte type, byte[] value)
-NoByteOrShort: android.net.DhcpOption#describeContents():
- Should avoid odd sized primitives; use `int` instead of `byte` in method android.net.DhcpOption.describeContents()
-NoByteOrShort: android.net.DhcpOption#getType():
- Should avoid odd sized primitives; use `int` instead of `byte` in method android.net.DhcpOption.getType()
diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java
index 5246623..e8e1efa 100644
--- a/framework/src/android/net/ConnectivityManager.java
+++ b/framework/src/android/net/ConnectivityManager.java
@@ -1625,16 +1625,45 @@
}
/**
- * Get the {@link NetworkCapabilities} for the given {@link Network}. This
- * will return {@code null} if the network is unknown or if the |network| argument is null.
+ * Redact {@link LinkProperties} for a given package
*
- * This will remove any location sensitive data in {@link TransportInfo} embedded in
- * {@link NetworkCapabilities#getTransportInfo()}. Some transport info instances like
- * {@link android.net.wifi.WifiInfo} contain location sensitive information. Retrieving
- * this location sensitive information (subject to app's location permissions) will be
- * noted by system. To include any location sensitive data in {@link TransportInfo},
- * use a {@link NetworkCallback} with
- * {@link NetworkCallback#FLAG_INCLUDE_LOCATION_INFO} flag.
+ * Returns an instance of the given {@link LinkProperties} appropriately redacted to send to the
+ * given package, considering its permissions.
+ *
+ * @param lp A {@link LinkProperties} which will be redacted.
+ * @param uid The target uid.
+ * @param packageName The name of the package, for appops logging.
+ * @return A redacted {@link LinkProperties} which is appropriate to send to the given uid,
+ * or null if the uid lacks the ACCESS_NETWORK_STATE permission.
+ * @hide
+ */
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_STACK,
+ android.Manifest.permission.NETWORK_SETTINGS})
+ @SystemApi(client = MODULE_LIBRARIES)
+ @Nullable
+ public LinkProperties redactLinkPropertiesForPackage(@NonNull LinkProperties lp, int uid,
+ @NonNull String packageName) {
+ try {
+ return mService.redactLinkPropertiesForPackage(
+ lp, uid, packageName, getAttributionTag());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Get the {@link NetworkCapabilities} for the given {@link Network}, or null.
+ *
+ * This will remove any location sensitive data in the returned {@link NetworkCapabilities}.
+ * Some {@link TransportInfo} instances like {@link android.net.wifi.WifiInfo} contain location
+ * sensitive information. To retrieve this location sensitive information (subject to
+ * the caller's location permissions), use a {@link NetworkCallback} with the
+ * {@link NetworkCallback#FLAG_INCLUDE_LOCATION_INFO} flag instead.
+ *
+ * This method returns {@code null} if the network is unknown or if the |network| argument
+ * is null.
*
* @param network The {@link Network} object identifying the network in question.
* @return The {@link NetworkCapabilities} for the network, or {@code null}.
@@ -1651,6 +1680,38 @@
}
/**
+ * Redact {@link NetworkCapabilities} for a given package.
+ *
+ * Returns an instance of {@link NetworkCapabilities} that is appropriately redacted to send
+ * to the given package, considering its permissions. Calling this method will blame the UID for
+ * retrieving the device location if the passed capabilities contain location-sensitive
+ * information.
+ *
+ * @param nc A {@link NetworkCapabilities} instance which will be redacted.
+ * @param uid The target uid.
+ * @param packageName The name of the package, for appops logging.
+ * @return A redacted {@link NetworkCapabilities} which is appropriate to send to the given uid,
+ * or null if the uid lacks the ACCESS_NETWORK_STATE permission.
+ * @hide
+ */
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_STACK,
+ android.Manifest.permission.NETWORK_SETTINGS})
+ @SystemApi(client = MODULE_LIBRARIES)
+ @Nullable
+ public NetworkCapabilities redactNetworkCapabilitiesForPackage(
+ @NonNull NetworkCapabilities nc,
+ int uid, @NonNull String packageName) {
+ try {
+ return mService.redactNetworkCapabilitiesForPackage(nc, uid, packageName,
+ getAttributionTag());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Gets a URL that can be used for resolving whether a captive portal is present.
* 1. This URL should respond with a 204 response to a GET request to indicate no captive
* portal is present.
@@ -3547,7 +3608,20 @@
* @hide
*/
public static final int FLAG_NONE = 0;
+
/**
+ * Inclusion of this flag means location-sensitive redaction requests keeping location info.
+ *
+ * Some objects like {@link NetworkCapabilities} may contain location-sensitive information.
+ * Prior to Android 12, this information is always returned to apps holding the appropriate
+ * permission, possibly noting that the app has used location.
+ * <p>In Android 12 and above, by default the sent objects do not contain any location
+ * information, even if the app holds the necessary permissions, and the system does not
+ * take note of location usage by the app. Apps can request that location information is
+ * included, in which case the system will check location permission and the location
+ * toggle state, and take note of location usage by the app if any such information is
+ * returned.
+ *
* Use this flag to include any location sensitive data in {@link NetworkCapabilities} sent
* via {@link #onCapabilitiesChanged(Network, NetworkCapabilities)}.
* <p>
@@ -3564,8 +3638,7 @@
* <li> Retrieving this location sensitive information (subject to app's location
* permissions) will be noted by system. </li>
* <li> Without this flag any {@link NetworkCapabilities} provided via the callback does
- * not include location sensitive info.
- * </p>
+ * not include location sensitive information.
*/
// Note: Some existing fields which are location sensitive may still be included without
// this flag if the app targets SDK < S (to maintain backwards compatibility).
diff --git a/framework/src/android/net/ConnectivitySettingsManager.java b/framework/src/android/net/ConnectivitySettingsManager.java
index 8fc0065..4e28b29 100644
--- a/framework/src/android/net/ConnectivitySettingsManager.java
+++ b/framework/src/android/net/ConnectivitySettingsManager.java
@@ -384,6 +384,14 @@
"uids_allowed_on_restricted_networks";
/**
+ * A global rate limit that applies to all networks with NET_CAPABILITY_INTERNET when enabled.
+ *
+ * @hide
+ */
+ public static final String INGRESS_RATE_LIMIT_BYTES_PER_SECOND =
+ "ingress_rate_limit_bytes_per_second";
+
+ /**
* Get mobile data activity timeout from {@link Settings}.
*
* @param context The {@link Context} to query the setting.
@@ -1071,4 +1079,37 @@
Settings.Global.putString(context.getContentResolver(), UIDS_ALLOWED_ON_RESTRICTED_NETWORKS,
uids);
}
+
+ /**
+ * Get the global network bandwidth rate limit.
+ *
+ * The limit is only applicable to networks that provide internet connectivity. If the setting
+ * is unset, it defaults to -1.
+ *
+ * @param context The {@link Context} to query the setting.
+ * @return The rate limit in number of bytes per second or -1 if disabled.
+ */
+ public static long getIngressRateLimitInBytesPerSecond(@NonNull Context context) {
+ return Settings.Global.getLong(context.getContentResolver(),
+ INGRESS_RATE_LIMIT_BYTES_PER_SECOND, -1);
+ }
+
+ /**
+ * Set the global network bandwidth rate limit.
+ *
+ * The limit is only applicable to networks that provide internet connectivity.
+ *
+ * @param context The {@link Context} to set the setting.
+ * @param rateLimitInBytesPerSec The rate limit in number of bytes per second or -1 to disable.
+ */
+ public static void setIngressRateLimitInBytesPerSecond(@NonNull Context context,
+ @IntRange(from = -1, to = Integer.MAX_VALUE) long rateLimitInBytesPerSec) {
+ if (rateLimitInBytesPerSec < -1) {
+ throw new IllegalArgumentException(
+ "Rate limit must be within the range [-1, Integer.MAX_VALUE]");
+ }
+ Settings.Global.putLong(context.getContentResolver(),
+ INGRESS_RATE_LIMIT_BYTES_PER_SECOND,
+ rateLimitInBytesPerSec);
+ }
}
diff --git a/framework/src/android/net/DhcpOption.java b/framework/src/android/net/DhcpOption.java
index a125290..b30470a 100644
--- a/framework/src/android/net/DhcpOption.java
+++ b/framework/src/android/net/DhcpOption.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -35,12 +36,13 @@
/**
* Constructs a DhcpOption object.
*
- * @param type the type of this option
+ * @param type the type of this option. For more information, see
+ * https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml.
* @param value the value of this option. If {@code null}, DHCP packets containing this option
* will include the option type in the Parameter Request List. Otherwise, DHCP
* packets containing this option will include the option in the options section.
*/
- public DhcpOption(byte type, @Nullable byte[] value) {
+ public DhcpOption(@SuppressLint("NoByteOrShort") byte type, @Nullable byte[] value) {
mType = type;
mValue = value;
}
@@ -69,6 +71,7 @@
};
/** Get the type of DHCP option */
+ @SuppressLint("NoByteOrShort")
public byte getType() {
return mType;
}
diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl
index df4663f..23a3850 100644
--- a/framework/src/android/net/IConnectivityManager.aidl
+++ b/framework/src/android/net/IConnectivityManager.aidl
@@ -76,10 +76,15 @@
LinkProperties getActiveLinkProperties();
LinkProperties getLinkPropertiesForType(int networkType);
LinkProperties getLinkProperties(in Network network);
+ LinkProperties redactLinkPropertiesForPackage(in LinkProperties lp, int uid, String packageName,
+ String callingAttributionTag);
NetworkCapabilities getNetworkCapabilities(in Network network, String callingPackageName,
String callingAttributionTag);
+ NetworkCapabilities redactNetworkCapabilitiesForPackage(in NetworkCapabilities nc, int uid,
+ String callingPackageName, String callingAttributionTag);
+
@UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
NetworkState[] getAllNetworkState();
diff --git a/framework/src/android/net/NetworkAgentConfig.java b/framework/src/android/net/NetworkAgentConfig.java
index 040bf31..1991a58 100644
--- a/framework/src/android/net/NetworkAgentConfig.java
+++ b/framework/src/android/net/NetworkAgentConfig.java
@@ -34,6 +34,8 @@
*/
@SystemApi
public final class NetworkAgentConfig implements Parcelable {
+ // TODO : make this object immutable. The fields that should stay mutable should likely
+ // migrate to NetworkAgentInfo.
/**
* If the {@link Network} is a VPN, whether apps are allowed to bypass the
@@ -242,10 +244,31 @@
* @return whether local traffic is excluded from the VPN network.
* @hide
*/
- public boolean getExcludeLocalRouteVpn() {
+ public boolean areLocalRoutesExcludedForVpn() {
return excludeLocalRouteVpn;
}
+ /**
+ * Whether network validation should be performed for this VPN network.
+ * {@see #getVpnRequiresValidation}
+ * @hide
+ */
+ private boolean mVpnRequiresValidation = false;
+
+ /**
+ * Whether network validation should be performed for this VPN network.
+ *
+ * If this network isn't a VPN this should always be {@code false}, and will be ignored
+ * if set.
+ * If this network is a VPN, false means this network should always be considered validated;
+ * true means it follows the same validation semantics as general internet networks.
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public boolean getVpnRequiresValidation() {
+ return mVpnRequiresValidation;
+ }
+
/** @hide */
public NetworkAgentConfig() {
}
@@ -266,6 +289,7 @@
legacySubTypeName = nac.legacySubTypeName;
mLegacyExtraInfo = nac.mLegacyExtraInfo;
excludeLocalRouteVpn = nac.excludeLocalRouteVpn;
+ mVpnRequiresValidation = nac.mVpnRequiresValidation;
}
}
@@ -409,6 +433,25 @@
}
/**
+ * Sets whether network validation should be performed for this VPN network.
+ *
+ * Only agents registering a VPN network should use this setter. On other network
+ * types it will be ignored.
+ * False means this network should always be considered validated;
+ * true means it follows the same validation semantics as general internet.
+ *
+ * @param vpnRequiresValidation whether this VPN requires validation.
+ * Default is {@code false}.
+ * @hide
+ */
+ @NonNull
+ @SystemApi(client = MODULE_LIBRARIES)
+ public Builder setVpnRequiresValidation(boolean vpnRequiresValidation) {
+ mConfig.mVpnRequiresValidation = vpnRequiresValidation;
+ return this;
+ }
+
+ /**
* Sets whether the apps can bypass the VPN connection.
*
* @return this builder, to facilitate chaining.
@@ -429,7 +472,7 @@
*/
@NonNull
@SystemApi(client = MODULE_LIBRARIES)
- public Builder setExcludeLocalRoutesVpn(boolean excludeLocalRoutes) {
+ public Builder setLocalRoutesExcludedForVpn(boolean excludeLocalRoutes) {
mConfig.excludeLocalRouteVpn = excludeLocalRoutes;
return this;
}
@@ -458,14 +501,16 @@
&& Objects.equals(subscriberId, that.subscriberId)
&& Objects.equals(legacyTypeName, that.legacyTypeName)
&& Objects.equals(mLegacyExtraInfo, that.mLegacyExtraInfo)
- && excludeLocalRouteVpn == that.excludeLocalRouteVpn;
+ && excludeLocalRouteVpn == that.excludeLocalRouteVpn
+ && mVpnRequiresValidation == that.mVpnRequiresValidation;
}
@Override
public int hashCode() {
return Objects.hash(allowBypass, explicitlySelected, acceptUnvalidated,
acceptPartialConnectivity, provisioningNotificationDisabled, subscriberId,
- skip464xlat, legacyType, legacyTypeName, mLegacyExtraInfo, excludeLocalRouteVpn);
+ skip464xlat, legacyType, legacyTypeName, mLegacyExtraInfo, excludeLocalRouteVpn,
+ mVpnRequiresValidation);
}
@Override
@@ -483,6 +528,7 @@
+ ", legacyTypeName = '" + legacyTypeName + '\''
+ ", legacyExtraInfo = '" + mLegacyExtraInfo + '\''
+ ", excludeLocalRouteVpn = '" + excludeLocalRouteVpn + '\''
+ + ", vpnRequiresValidation = '" + mVpnRequiresValidation + '\''
+ "}";
}
@@ -506,6 +552,7 @@
out.writeString(legacySubTypeName);
out.writeString(mLegacyExtraInfo);
out.writeInt(excludeLocalRouteVpn ? 1 : 0);
+ out.writeInt(mVpnRequiresValidation ? 1 : 0);
}
public static final @NonNull Creator<NetworkAgentConfig> CREATOR =
@@ -526,6 +573,7 @@
networkAgentConfig.legacySubTypeName = in.readString();
networkAgentConfig.mLegacyExtraInfo = in.readString();
networkAgentConfig.excludeLocalRouteVpn = in.readInt() != 0;
+ networkAgentConfig.mVpnRequiresValidation = in.readInt() != 0;
return networkAgentConfig;
}
diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java
index b6cd760..41be732 100644
--- a/framework/src/android/net/NetworkCapabilities.java
+++ b/framework/src/android/net/NetworkCapabilities.java
@@ -1536,9 +1536,12 @@
*/
public @NonNull NetworkCapabilities setNetworkSpecifier(
@NonNull NetworkSpecifier networkSpecifier) {
- if (networkSpecifier != null && Long.bitCount(mTransportTypes) != 1) {
- throw new IllegalStateException("Must have a single transport specified to use " +
- "setNetworkSpecifier");
+ if (networkSpecifier != null
+ // Transport can be test, or test + a single other transport
+ && mTransportTypes != (1L << TRANSPORT_TEST)
+ && Long.bitCount(mTransportTypes & ~(1L << TRANSPORT_TEST)) != 1) {
+ throw new IllegalStateException("Must have a single non-test transport specified to "
+ + "use setNetworkSpecifier");
}
mNetworkSpecifier = networkSpecifier;
diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java
index b7a6076..4f9d845 100644
--- a/framework/src/android/net/NetworkRequest.java
+++ b/framework/src/android/net/NetworkRequest.java
@@ -423,6 +423,7 @@
*
* @deprecated Use {@link #setNetworkSpecifier(NetworkSpecifier)} instead.
*/
+ @SuppressLint("NewApi") // TODO: b/193460475 remove once fixed
@Deprecated
public Builder setNetworkSpecifier(String networkSpecifier) {
try {
@@ -439,6 +440,15 @@
} else if (mNetworkCapabilities.hasTransport(TRANSPORT_TEST)) {
return setNetworkSpecifier(new TestNetworkSpecifier(networkSpecifier));
} else {
+ // TODO: b/193460475 remove comment once fixed
+ // @SuppressLint("NewApi") is due to EthernetNetworkSpecifier being changed
+ // from @SystemApi to public. EthernetNetworkSpecifier was introduced in Android
+ // 12 as @SystemApi(client = MODULE_LIBRARIES) and made public in Android 13.
+ // b/193460475 means in the above situation the tools will think
+ // EthernetNetworkSpecifier didn't exist in Android 12, causing the NewApi lint
+ // to fail. In this case, this is actually safe because this code was
+ // modularized in Android 12, so it can't run on SDKs before Android 12 and is
+ // therefore guaranteed to always have this class available to it.
return setNetworkSpecifier(new EthernetNetworkSpecifier(networkSpecifier));
}
}
diff --git a/nearby/OWNERS b/nearby/OWNERS
new file mode 100644
index 0000000..980c221
--- /dev/null
+++ b/nearby/OWNERS
@@ -0,0 +1,4 @@
+chunzhang@google.com
+weiwa@google.com
+weiwu@google.com
+xlythe@google.com
diff --git a/netd/Android.bp b/netd/Android.bp
index b98a859..5ac02d3 100644
--- a/netd/Android.bp
+++ b/netd/Android.bp
@@ -13,6 +13,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
cc_library {
name: "libnetd_updatable",
version_script: "libnetd_updatable.map.txt",
diff --git a/service-t/Android.bp b/service-t/Android.bp
index f33be63..8ba0768 100644
--- a/service-t/Android.bp
+++ b/service-t/Android.bp
@@ -37,7 +37,8 @@
libs: [
"framework-annotations-lib",
"framework-connectivity-pre-jarjar",
- "framework-connectivity-tiramisu.impl",
+ "framework-connectivity-tiramisu-pre-jarjar",
+ "framework-tethering.stubs.module_lib",
"service-connectivity-pre-jarjar",
"unsupportedappusage",
],
@@ -52,7 +53,9 @@
"com.android.tethering",
],
visibility: [
+ "//frameworks/base/tests/vcn",
"//packages/modules/Connectivity/service",
"//packages/modules/Connectivity/tests:__subpackages__",
+ "//packages/modules/IPsec/tests/iketests",
],
}
diff --git a/service-t/src/com/android/server/ConnectivityServiceInitializer.java b/service-t/src/com/android/server/ConnectivityServiceInitializer.java
index 23d8bdc..67757af 100644
--- a/service-t/src/com/android/server/ConnectivityServiceInitializer.java
+++ b/service-t/src/com/android/server/ConnectivityServiceInitializer.java
@@ -28,6 +28,7 @@
public final class ConnectivityServiceInitializer extends SystemService {
private static final String TAG = ConnectivityServiceInitializer.class.getSimpleName();
private final ConnectivityService mConnectivity;
+ private final IpSecService mIpSecService;
private final NsdService mNsdService;
public ConnectivityServiceInitializer(Context context) {
@@ -35,6 +36,7 @@
// Load JNI libraries used by ConnectivityService and its dependencies
System.loadLibrary("service-connectivity");
mConnectivity = new ConnectivityService(context);
+ mIpSecService = createIpSecService(context);
mNsdService = createNsdService(context);
}
@@ -43,12 +45,27 @@
Log.i(TAG, "Registering " + Context.CONNECTIVITY_SERVICE);
publishBinderService(Context.CONNECTIVITY_SERVICE, mConnectivity,
/* allowIsolated= */ false);
+
+ if (mIpSecService != null) {
+ Log.i(TAG, "Registering " + Context.IPSEC_SERVICE);
+ publishBinderService(Context.IPSEC_SERVICE, mIpSecService, /* allowIsolated= */ false);
+ }
+
if (mNsdService != null) {
Log.i(TAG, "Registering " + Context.NSD_SERVICE);
publishBinderService(Context.NSD_SERVICE, mNsdService, /* allowIsolated= */ false);
}
}
+ /**
+ * Return IpSecService instance, or null if current SDK is lower than T.
+ */
+ private IpSecService createIpSecService(final Context context) {
+ if (!SdkLevel.isAtLeastT()) return null;
+
+ return new IpSecService(context);
+ }
+
/** Return NsdService instance or null if current SDK is lower than T */
private NsdService createNsdService(final Context context) {
if (!SdkLevel.isAtLeastT()) return null;
diff --git a/service/jni/com_android_server_BpfNetMaps.cpp b/service/jni/com_android_server_BpfNetMaps.cpp
index e7b5522..85cfc09 100644
--- a/service/jni/com_android_server_BpfNetMaps.cpp
+++ b/service/jni/com_android_server_BpfNetMaps.cpp
@@ -186,24 +186,6 @@
mTc.setPermissionForUids(permission, data);
}
-static jint native_setCounterSet(JNIEnv* env, jobject clazz, jint setNum, jint uid) {
- uid_t callingUid = getuid();
- int res = mTc.setCounterSet(setNum, (uid_t)uid, callingUid);
- if (res) {
- ALOGE("%s failed, error code = %d", __func__, res);
- }
- return (jint)res;
-}
-
-static jint native_deleteTagData(JNIEnv* env, jobject clazz, jint tagNum, jint uid) {
- uid_t callingUid = getuid();
- int res = mTc.deleteTagData(tagNum, (uid_t)uid, callingUid);
- if (res) {
- ALOGE("%s failed, error code = %d", __func__, res);
- }
- return (jint)res;
-}
-
/*
* JNI registration.
*/
@@ -234,10 +216,6 @@
(void*)native_swapActiveStatsMap},
{"native_setPermissionForUids", "(I[I)V",
(void*)native_setPermissionForUids},
- {"native_setCounterSet", "(II)I",
- (void*)native_setCounterSet},
- {"native_deleteTagData", "(II)I",
- (void*)native_deleteTagData},
};
// clang-format on
diff --git a/service/native/TrafficController.cpp b/service/native/TrafficController.cpp
index 5981906..1cbfd94 100644
--- a/service/native/TrafficController.cpp
+++ b/service/native/TrafficController.cpp
@@ -54,7 +54,6 @@
using base::StringPrintf;
using base::unique_fd;
using bpf::BpfMap;
-using bpf::OVERFLOW_COUNTERSET;
using bpf::synchronizeKernelRCU;
using netdutils::DumpWriter;
using netdutils::getIfaceList;
@@ -239,99 +238,6 @@
return netdutils::status::ok;
}
-int TrafficController::setCounterSet(int counterSetNum, uid_t uid, uid_t callingUid) {
- if (counterSetNum < 0 || counterSetNum >= OVERFLOW_COUNTERSET) return -EINVAL;
-
- std::lock_guard guard(mMutex);
- if (!hasUpdateDeviceStatsPermission(callingUid)) return -EPERM;
-
- // The default counter set for all uid is 0, so deleting the current counterset for that uid
- // will automatically set it to 0.
- if (counterSetNum == 0) {
- Status res = mUidCounterSetMap.deleteValue(uid);
- if (isOk(res) || (!isOk(res) && res.code() == ENOENT)) {
- return 0;
- } else {
- ALOGE("Failed to delete the counterSet: %s\n", strerror(res.code()));
- return -res.code();
- }
- }
- uint8_t tmpCounterSetNum = (uint8_t)counterSetNum;
- Status res = mUidCounterSetMap.writeValue(uid, tmpCounterSetNum, BPF_ANY);
- if (!isOk(res)) {
- ALOGE("Failed to set the counterSet: %s, fd: %d", strerror(res.code()),
- mUidCounterSetMap.getMap().get());
- return -res.code();
- }
- return 0;
-}
-
-// This method only get called by system_server when an app get uinstalled, it
-// is called inside removeUidsLocked() while holding mStatsLock. So it is safe
-// to iterate and modify the stats maps.
-int TrafficController::deleteTagData(uint32_t tag, uid_t uid, uid_t callingUid) {
- std::lock_guard guard(mMutex);
- if (!hasUpdateDeviceStatsPermission(callingUid)) return -EPERM;
-
- // First we go through the cookieTagMap to delete the target uid tag combination. Or delete all
- // the tags related to the uid if the tag is 0.
- const auto deleteMatchedCookieEntries = [uid, tag](const uint64_t& key,
- const UidTagValue& value,
- BpfMap<uint64_t, UidTagValue>& map) {
- if (value.uid == uid && (value.tag == tag || tag == 0)) {
- auto res = map.deleteValue(key);
- if (res.ok() || (res.error().code() == ENOENT)) {
- return base::Result<void>();
- }
- ALOGE("Failed to delete data(cookie = %" PRIu64 "): %s\n", key,
- strerror(res.error().code()));
- }
- // Move forward to next cookie in the map.
- return base::Result<void>();
- };
- mCookieTagMap.iterateWithValue(deleteMatchedCookieEntries);
- // Now we go through the Tag stats map and delete the data entry with correct uid and tag
- // combination. Or all tag stats under that uid if the target tag is 0.
- const auto deleteMatchedUidTagEntries = [uid, tag](const StatsKey& key,
- BpfMap<StatsKey, StatsValue>& map) {
- if (key.uid == uid && (key.tag == tag || tag == 0)) {
- auto res = map.deleteValue(key);
- if (res.ok() || (res.error().code() == ENOENT)) {
- //Entry is deleted, use the current key to get a new nextKey;
- return base::Result<void>();
- }
- ALOGE("Failed to delete data(uid=%u, tag=%u): %s\n", key.uid, key.tag,
- strerror(res.error().code()));
- }
- return base::Result<void>();
- };
- mStatsMapB.iterate(deleteMatchedUidTagEntries);
- mStatsMapA.iterate(deleteMatchedUidTagEntries);
- // If the tag is not zero, we already deleted all the data entry required. If tag is 0, we also
- // need to delete the stats stored in uidStatsMap and counterSet map.
- if (tag != 0) return 0;
-
- auto res = mUidCounterSetMap.deleteValue(uid);
- if (!res.ok() && res.error().code() != ENOENT) {
- ALOGE("Failed to delete counterSet data(uid=%u, tag=%u): %s\n", uid, tag,
- strerror(res.error().code()));
- }
-
- auto deleteAppUidStatsEntry = [uid](const uint32_t& key,
- BpfMap<uint32_t, StatsValue>& map) -> base::Result<void> {
- if (key == uid) {
- auto res = map.deleteValue(key);
- if (res.ok() || (res.error().code() == ENOENT)) {
- return {};
- }
- ALOGE("Failed to delete data(uid=%u): %s", key, strerror(res.error().code()));
- }
- return {};
- };
- mAppUidStatsMap.iterate(deleteAppUidStatsEntry);
- return 0;
-}
-
int TrafficController::addInterface(const char* name, uint32_t ifaceIndex) {
IfaceValue iface;
if (ifaceIndex == 0) {
diff --git a/service/native/TrafficControllerTest.cpp b/service/native/TrafficControllerTest.cpp
index d0eca34..9529cae 100644
--- a/service/native/TrafficControllerTest.cpp
+++ b/service/native/TrafficControllerTest.cpp
@@ -55,7 +55,6 @@
constexpr uid_t TEST_UID3 = 98765;
constexpr uint32_t TEST_TAG = 42;
constexpr uint32_t TEST_COUNTERSET = 1;
-constexpr uint32_t DEFAULT_COUNTERSET = 0;
#define ASSERT_VALID(x) ASSERT_TRUE((x).isValid())
@@ -64,7 +63,6 @@
TrafficControllerTest() {}
TrafficController mTc;
BpfMap<uint64_t, UidTagValue> mFakeCookieTagMap;
- BpfMap<uint32_t, uint8_t> mFakeUidCounterSetMap;
BpfMap<uint32_t, StatsValue> mFakeAppUidStatsMap;
BpfMap<StatsKey, StatsValue> mFakeStatsMapA;
BpfMap<uint32_t, uint8_t> mFakeConfigurationMap;
@@ -79,10 +77,6 @@
TEST_MAP_SIZE, 0));
ASSERT_VALID(mFakeCookieTagMap);
- mFakeUidCounterSetMap.reset(
- createMap(BPF_MAP_TYPE_HASH, sizeof(uint32_t), sizeof(uint8_t), TEST_MAP_SIZE, 0));
- ASSERT_VALID(mFakeUidCounterSetMap);
-
mFakeAppUidStatsMap.reset(createMap(BPF_MAP_TYPE_HASH, sizeof(uint32_t), sizeof(StatsValue),
TEST_MAP_SIZE, 0));
ASSERT_VALID(mFakeAppUidStatsMap);
@@ -104,8 +98,6 @@
mTc.mCookieTagMap.reset(dupFd(mFakeCookieTagMap.getMap()));
ASSERT_VALID(mTc.mCookieTagMap);
- mTc.mUidCounterSetMap.reset(dupFd(mFakeUidCounterSetMap.getMap()));
- ASSERT_VALID(mTc.mUidCounterSetMap);
mTc.mAppUidStatsMap.reset(dupFd(mFakeAppUidStatsMap.getMap()));
ASSERT_VALID(mTc.mAppUidStatsMap);
mTc.mStatsMapA.reset(dupFd(mFakeStatsMapA.getMap()));
@@ -132,8 +124,6 @@
EXPECT_RESULT_OK(mFakeCookieTagMap.writeValue(cookie, cookieMapkey, BPF_ANY));
*key = {.uid = uid, .tag = tag, .counterSet = TEST_COUNTERSET, .ifaceIndex = 1};
StatsValue statsMapValue = {.rxPackets = 1, .rxBytes = 100};
- uint8_t counterSet = TEST_COUNTERSET;
- EXPECT_RESULT_OK(mFakeUidCounterSetMap.writeValue(uid, counterSet, BPF_ANY));
EXPECT_RESULT_OK(mFakeStatsMapA.writeValue(*key, statsMapValue, BPF_ANY));
key->tag = 0;
EXPECT_RESULT_OK(mFakeStatsMapA.writeValue(*key, statsMapValue, BPF_ANY));
@@ -259,9 +249,6 @@
EXPECT_RESULT_OK(cookieMapResult);
EXPECT_EQ(uid, cookieMapResult.value().uid);
EXPECT_EQ(tag, cookieMapResult.value().tag);
- Result<uint8_t> counterSetResult = mFakeUidCounterSetMap.readValue(uid);
- EXPECT_RESULT_OK(counterSetResult);
- EXPECT_EQ(TEST_COUNTERSET, counterSetResult.value());
Result<StatsValue> statsMapResult = mFakeStatsMapA.readValue(tagStatsMapKey);
EXPECT_RESULT_OK(statsMapResult);
EXPECT_EQ((uint64_t)1, statsMapResult.value().rxPackets);
@@ -289,157 +276,6 @@
};
-TEST_F(TrafficControllerTest, TestSetCounterSet) {
- uid_t callingUid = TEST_UID2;
- addPrivilegedUid(callingUid);
- ASSERT_EQ(0, mTc.setCounterSet(TEST_COUNTERSET, TEST_UID, callingUid));
- uid_t uid = TEST_UID;
- Result<uint8_t> counterSetResult = mFakeUidCounterSetMap.readValue(uid);
- ASSERT_RESULT_OK(counterSetResult);
- ASSERT_EQ(TEST_COUNTERSET, counterSetResult.value());
- ASSERT_EQ(0, mTc.setCounterSet(DEFAULT_COUNTERSET, TEST_UID, callingUid));
- ASSERT_FALSE(mFakeUidCounterSetMap.readValue(uid).ok());
- expectMapEmpty(mFakeUidCounterSetMap);
-}
-
-TEST_F(TrafficControllerTest, TestSetCounterSetWithoutPermission) {
- ASSERT_EQ(-EPERM, mTc.setCounterSet(TEST_COUNTERSET, TEST_UID, TEST_UID2));
- uid_t uid = TEST_UID;
- ASSERT_FALSE(mFakeUidCounterSetMap.readValue(uid).ok());
- expectMapEmpty(mFakeUidCounterSetMap);
-}
-
-TEST_F(TrafficControllerTest, TestSetInvalidCounterSet) {
- uid_t callingUid = TEST_UID2;
- addPrivilegedUid(callingUid);
- ASSERT_GT(0, mTc.setCounterSet(OVERFLOW_COUNTERSET, TEST_UID, callingUid));
- uid_t uid = TEST_UID;
- ASSERT_FALSE(mFakeUidCounterSetMap.readValue(uid).ok());
- expectMapEmpty(mFakeUidCounterSetMap);
-}
-
-TEST_F(TrafficControllerTest, TestDeleteTagDataWithoutPermission) {
- uint64_t cookie = 1;
- uid_t uid = TEST_UID;
- uint32_t tag = TEST_TAG;
- StatsKey tagStatsMapKey;
- populateFakeStats(cookie, uid, tag, &tagStatsMapKey);
- ASSERT_EQ(-EPERM, mTc.deleteTagData(0, TEST_UID, TEST_UID2));
-
- expectFakeStatsUnchanged(cookie, tag, uid, tagStatsMapKey);
-}
-
-TEST_F(TrafficControllerTest, TestDeleteTagData) {
- uid_t callingUid = TEST_UID2;
- addPrivilegedUid(callingUid);
- uint64_t cookie = 1;
- uid_t uid = TEST_UID;
- uint32_t tag = TEST_TAG;
- StatsKey tagStatsMapKey;
- populateFakeStats(cookie, uid, tag, &tagStatsMapKey);
- ASSERT_EQ(0, mTc.deleteTagData(TEST_TAG, TEST_UID, callingUid));
- ASSERT_FALSE(mFakeCookieTagMap.readValue(cookie).ok());
- Result<uint8_t> counterSetResult = mFakeUidCounterSetMap.readValue(uid);
- ASSERT_RESULT_OK(counterSetResult);
- ASSERT_EQ(TEST_COUNTERSET, counterSetResult.value());
- ASSERT_FALSE(mFakeStatsMapA.readValue(tagStatsMapKey).ok());
- tagStatsMapKey.tag = 0;
- Result<StatsValue> statsMapResult = mFakeStatsMapA.readValue(tagStatsMapKey);
- ASSERT_RESULT_OK(statsMapResult);
- ASSERT_EQ((uint64_t)1, statsMapResult.value().rxPackets);
- ASSERT_EQ((uint64_t)100, statsMapResult.value().rxBytes);
- auto appStatsResult = mFakeAppUidStatsMap.readValue(TEST_UID);
- ASSERT_RESULT_OK(appStatsResult);
- ASSERT_EQ((uint64_t)1, appStatsResult.value().rxPackets);
- ASSERT_EQ((uint64_t)100, appStatsResult.value().rxBytes);
-}
-
-TEST_F(TrafficControllerTest, TestDeleteAllUidData) {
- uid_t callingUid = TEST_UID2;
- addPrivilegedUid(callingUid);
- uint64_t cookie = 1;
- uid_t uid = TEST_UID;
- uint32_t tag = TEST_TAG;
- StatsKey tagStatsMapKey;
- populateFakeStats(cookie, uid, tag, &tagStatsMapKey);
- ASSERT_EQ(0, mTc.deleteTagData(0, TEST_UID, callingUid));
- ASSERT_FALSE(mFakeCookieTagMap.readValue(cookie).ok());
- ASSERT_FALSE(mFakeUidCounterSetMap.readValue(uid).ok());
- ASSERT_FALSE(mFakeStatsMapA.readValue(tagStatsMapKey).ok());
- tagStatsMapKey.tag = 0;
- ASSERT_FALSE(mFakeStatsMapA.readValue(tagStatsMapKey).ok());
- ASSERT_FALSE(mFakeAppUidStatsMap.readValue(TEST_UID).ok());
-}
-
-TEST_F(TrafficControllerTest, TestDeleteDataWithTwoTags) {
- uid_t callingUid = TEST_UID2;
- addPrivilegedUid(callingUid);
- uint64_t cookie1 = 1;
- uint64_t cookie2 = 2;
- uid_t uid = TEST_UID;
- uint32_t tag1 = TEST_TAG;
- uint32_t tag2 = TEST_TAG + 1;
- StatsKey tagStatsMapKey1;
- StatsKey tagStatsMapKey2;
- populateFakeStats(cookie1, uid, tag1, &tagStatsMapKey1);
- populateFakeStats(cookie2, uid, tag2, &tagStatsMapKey2);
- ASSERT_EQ(0, mTc.deleteTagData(TEST_TAG, TEST_UID, callingUid));
- ASSERT_FALSE(mFakeCookieTagMap.readValue(cookie1).ok());
- Result<UidTagValue> cookieMapResult = mFakeCookieTagMap.readValue(cookie2);
- ASSERT_RESULT_OK(cookieMapResult);
- ASSERT_EQ(TEST_UID, cookieMapResult.value().uid);
- ASSERT_EQ(TEST_TAG + 1, cookieMapResult.value().tag);
- Result<uint8_t> counterSetResult = mFakeUidCounterSetMap.readValue(uid);
- ASSERT_RESULT_OK(counterSetResult);
- ASSERT_EQ(TEST_COUNTERSET, counterSetResult.value());
- ASSERT_FALSE(mFakeStatsMapA.readValue(tagStatsMapKey1).ok());
- Result<StatsValue> statsMapResult = mFakeStatsMapA.readValue(tagStatsMapKey2);
- ASSERT_RESULT_OK(statsMapResult);
- ASSERT_EQ((uint64_t)1, statsMapResult.value().rxPackets);
- ASSERT_EQ((uint64_t)100, statsMapResult.value().rxBytes);
-}
-
-TEST_F(TrafficControllerTest, TestDeleteDataWithTwoUids) {
- uid_t callingUid = TEST_UID2;
- addPrivilegedUid(callingUid);
- uint64_t cookie1 = 1;
- uint64_t cookie2 = 2;
- uid_t uid1 = TEST_UID;
- uid_t uid2 = TEST_UID + 1;
- uint32_t tag = TEST_TAG;
- StatsKey tagStatsMapKey1;
- StatsKey tagStatsMapKey2;
- populateFakeStats(cookie1, uid1, tag, &tagStatsMapKey1);
- populateFakeStats(cookie2, uid2, tag, &tagStatsMapKey2);
-
- // Delete the stats of one of the uid. Check if it is properly collected by
- // removedStats.
- ASSERT_EQ(0, mTc.deleteTagData(0, uid2, callingUid));
- ASSERT_FALSE(mFakeCookieTagMap.readValue(cookie2).ok());
- Result<uint8_t> counterSetResult = mFakeUidCounterSetMap.readValue(uid1);
- ASSERT_RESULT_OK(counterSetResult);
- ASSERT_EQ(TEST_COUNTERSET, counterSetResult.value());
- ASSERT_FALSE(mFakeUidCounterSetMap.readValue(uid2).ok());
- ASSERT_FALSE(mFakeStatsMapA.readValue(tagStatsMapKey2).ok());
- tagStatsMapKey2.tag = 0;
- ASSERT_FALSE(mFakeStatsMapA.readValue(tagStatsMapKey2).ok());
- ASSERT_FALSE(mFakeAppUidStatsMap.readValue(uid2).ok());
- tagStatsMapKey1.tag = 0;
- Result<StatsValue> statsMapResult = mFakeStatsMapA.readValue(tagStatsMapKey1);
- ASSERT_RESULT_OK(statsMapResult);
- ASSERT_EQ((uint64_t)1, statsMapResult.value().rxPackets);
- ASSERT_EQ((uint64_t)100, statsMapResult.value().rxBytes);
- auto appStatsResult = mFakeAppUidStatsMap.readValue(uid1);
- ASSERT_RESULT_OK(appStatsResult);
- ASSERT_EQ((uint64_t)1, appStatsResult.value().rxPackets);
- ASSERT_EQ((uint64_t)100, appStatsResult.value().rxBytes);
-
- // Delete the stats of the other uid.
- ASSERT_EQ(0, mTc.deleteTagData(0, uid1, callingUid));
- ASSERT_FALSE(mFakeStatsMapA.readValue(tagStatsMapKey1).ok());
- ASSERT_FALSE(mFakeAppUidStatsMap.readValue(uid1).ok());
-}
-
TEST_F(TrafficControllerTest, TestUpdateOwnerMapEntry) {
uint32_t uid = TEST_UID;
ASSERT_TRUE(isOk(mTc.updateOwnerMapEntry(STANDBY_MATCH, uid, DENY, DENYLIST)));
diff --git a/service/native/include/TrafficController.h b/service/native/include/TrafficController.h
index e741dd6..6fe117f 100644
--- a/service/native/include/TrafficController.h
+++ b/service/native/include/TrafficController.h
@@ -40,18 +40,6 @@
*/
netdutils::Status start();
- int setCounterSet(int counterSetNum, uid_t uid, uid_t callingUid) EXCLUDES(mMutex);
-
- /*
- * When deleting a tag data, the qtaguid module will grab the spinlock of each
- * related rb_tree one by one and delete the tag information, counterSet
- * information, iface stats information and uid stats information one by one.
- * The new eBPF implementation is done similiarly by removing the entry on
- * each map one by one. And deleting processes are also protected by the
- * spinlock of the map. So no additional lock is required.
- */
- int deleteTagData(uint32_t tag, uid_t uid, uid_t callingUid) EXCLUDES(mMutex);
-
/*
* Swap the stats map config from current active stats map to the idle one.
*/
diff --git a/service/src/com/android/server/BpfNetMaps.java b/service/src/com/android/server/BpfNetMaps.java
index 7a3bab3..ddee275 100644
--- a/service/src/com/android/server/BpfNetMaps.java
+++ b/service/src/com/android/server/BpfNetMaps.java
@@ -273,32 +273,6 @@
native_setPermissionForUids(permissions, uids);
}
- /**
- * Set counter set for uid
- *
- * @param counterSet either SET_DEFAULT or SET_FOREGROUND
- * @param uid uid to foreground/background
- * @throws ServiceSpecificException in case of failure, with an error code indicating the
- * cause of the failure.
- */
- public void setCounterSet(final int counterSet, final int uid) {
- final int err = native_setCounterSet(counterSet, uid);
- maybeThrow(err, "setCounterSet failed");
- }
-
- /**
- * Reset Uid stats
- *
- * @param tag default 0
- * @param uid given uid to be clear
- * @throws ServiceSpecificException in case of failure, with an error code indicating the
- * cause of the failure.
- */
- public void deleteTagData(final int tag, final int uid) {
- final int err = native_deleteTagData(tag, uid);
- maybeThrow(err, "deleteTagData failed");
- }
-
private static native void native_init();
private native int native_addNaughtyApp(int uid);
private native int native_removeNaughtyApp(int uid);
@@ -311,6 +285,4 @@
private native int native_removeUidInterfaceRules(int[] uids);
private native int native_swapActiveStatsMap();
private native void native_setPermissionForUids(int permissions, int[] uids);
- private native int native_setCounterSet(int counterSet, int uid);
- private native int native_deleteTagData(int tag, int uid);
}
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index d833bc2..6024a2a 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -90,6 +90,7 @@
import static android.os.Process.INVALID_UID;
import static android.os.Process.VPN_UID;
import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
+import static android.system.OsConstants.ETH_P_ALL;
import static android.system.OsConstants.IPPROTO_TCP;
import static android.system.OsConstants.IPPROTO_UDP;
@@ -191,11 +192,13 @@
import android.net.netd.aidl.NativeUidRangeConfig;
import android.net.networkstack.ModuleNetworkStackClient;
import android.net.networkstack.NetworkStackClientBase;
+import android.net.networkstack.aidl.NetworkMonitorParameters;
import android.net.resolv.aidl.DnsHealthEventParcel;
import android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener;
import android.net.resolv.aidl.Nat64PrefixEventParcel;
import android.net.resolv.aidl.PrivateDnsValidationEventParcel;
import android.net.shared.PrivateDnsConfig;
+import android.net.util.InterfaceParams;
import android.net.util.MultinetworkPolicyTracker;
import android.os.BatteryStatsManager;
import android.os.Binder;
@@ -247,6 +250,7 @@
import com.android.net.module.util.LocationPermissionChecker;
import com.android.net.module.util.NetworkCapabilitiesUtils;
import com.android.net.module.util.PermissionUtils;
+import com.android.net.module.util.TcUtils;
import com.android.net.module.util.netlink.InetDiagMessage;
import com.android.server.connectivity.AutodestructReference;
import com.android.server.connectivity.CarrierPrivilegeAuthenticator;
@@ -273,6 +277,7 @@
import libcore.io.IoUtils;
import java.io.FileDescriptor;
+import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.net.Inet4Address;
@@ -708,6 +713,11 @@
private static final int EVENT_SET_TEST_ALLOW_BAD_WIFI_UNTIL = 55;
/**
+ * Used internally when INGRESS_RATE_LIMIT_BYTES_PER_SECOND setting changes.
+ */
+ private static final int EVENT_INGRESS_RATE_LIMIT_CHANGED = 56;
+
+ /**
* Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
* should be shown.
*/
@@ -724,6 +734,18 @@
*/
private static final long MAX_TEST_ALLOW_BAD_WIFI_UNTIL_MS = 5 * 60 * 1000L;
+ /**
+ * The priority of the tc police rate limiter -- smaller value is higher priority.
+ * This value needs to be coordinated with PRIO_CLAT, PRIO_TETHER4, and PRIO_TETHER6.
+ */
+ private static final short TC_PRIO_POLICE = 1;
+
+ /**
+ * The BPF program attached to the tc-police hook to account for to-be-dropped traffic.
+ */
+ private static final String TC_POLICE_BPF_PROG_PATH =
+ "/sys/fs/bpf/prog_netd_schedact_ingress_account";
+
private static String eventName(int what) {
return sMagicDecoderRing.get(what, Integer.toString(what));
}
@@ -814,6 +836,12 @@
final Map<IBinder, ConnectivityDiagnosticsCallbackInfo> mConnectivityDiagnosticsCallbacks =
new HashMap<>();
+ // Rate limit applicable to all internet capable networks (-1 = disabled). This value is
+ // configured via {@link
+ // ConnectivitySettingsManager#INGRESS_RATE_LIMIT_BYTES_PER_SECOND}
+ // Only the handler thread is allowed to access this field.
+ private long mIngressRateLimit = -1;
+
/**
* Implements support for the legacy "one network per network type" model.
*
@@ -1366,6 +1394,48 @@
public BpfNetMaps getBpfNetMaps(INetd netd) {
return new BpfNetMaps(netd);
}
+
+ /**
+ * Wraps {@link TcUtils#tcFilterAddDevIngressPolice}
+ */
+ public void enableIngressRateLimit(String iface, long rateInBytesPerSecond) {
+ final InterfaceParams params = InterfaceParams.getByName(iface);
+ if (params == null) {
+ // the interface might have disappeared.
+ logw("Failed to get interface params for interface " + iface);
+ return;
+ }
+ try {
+ // converting rateInBytesPerSecond from long to int is safe here because the
+ // setting's range is limited to INT_MAX.
+ // TODO: add long/uint64 support to tcFilterAddDevIngressPolice.
+ TcUtils.tcFilterAddDevIngressPolice(params.index, TC_PRIO_POLICE, (short) ETH_P_ALL,
+ (int) rateInBytesPerSecond, TC_POLICE_BPF_PROG_PATH);
+ } catch (IOException e) {
+ loge("TcUtils.tcFilterAddDevIngressPolice(ifaceIndex=" + params.index
+ + ", PRIO_POLICE, ETH_P_ALL, rateInBytesPerSecond="
+ + rateInBytesPerSecond + ", bpfProgPath=" + TC_POLICE_BPF_PROG_PATH
+ + ") failure: ", e);
+ }
+ }
+
+ /**
+ * Wraps {@link TcUtils#tcFilterDelDev}
+ */
+ public void disableIngressRateLimit(String iface) {
+ final InterfaceParams params = InterfaceParams.getByName(iface);
+ if (params == null) {
+ // the interface might have disappeared.
+ logw("Failed to get interface params for interface " + iface);
+ return;
+ }
+ try {
+ TcUtils.tcFilterDelDev(params.index, true, TC_PRIO_POLICE, (short) ETH_P_ALL);
+ } catch (IOException e) {
+ loge("TcUtils.tcFilterDelDev(ifaceIndex=" + params.index
+ + ", ingress=true, PRIO_POLICE, ETH_P_ALL) failure: ", e);
+ }
+ }
}
public ConnectivityService(Context context) {
@@ -1540,6 +1610,9 @@
} catch (ErrnoException e) {
loge("Unable to create DscpPolicyTracker");
}
+
+ mIngressRateLimit = ConnectivitySettingsManager.getIngressRateLimitInBytesPerSecond(
+ mContext);
}
private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) {
@@ -1610,6 +1683,11 @@
mHandler.sendEmptyMessage(EVENT_MOBILE_DATA_PREFERRED_UIDS_CHANGED);
}
+ @VisibleForTesting
+ void updateIngressRateLimit() {
+ mHandler.sendEmptyMessage(EVENT_INGRESS_RATE_LIMIT_CHANGED);
+ }
+
private void handleAlwaysOnNetworkRequest(NetworkRequest networkRequest, int id) {
final boolean enable = mContext.getResources().getBoolean(id);
handleAlwaysOnNetworkRequest(networkRequest, enable);
@@ -1671,6 +1749,12 @@
mSettingsObserver.observe(
Settings.Secure.getUriFor(ConnectivitySettingsManager.MOBILE_DATA_PREFERRED_UIDS),
EVENT_MOBILE_DATA_PREFERRED_UIDS_CHANGED);
+
+ // Watch for ingress rate limit changes.
+ mSettingsObserver.observe(
+ Settings.Secure.getUriFor(
+ ConnectivitySettingsManager.INGRESS_RATE_LIMIT_BYTES_PER_SECOND),
+ EVENT_INGRESS_RATE_LIMIT_CHANGED);
}
private void registerPrivateDnsSettingsCallbacks() {
@@ -2080,6 +2164,19 @@
}
}
+ @Override
+ @Nullable
+ public LinkProperties redactLinkPropertiesForPackage(@NonNull LinkProperties lp, int uid,
+ @NonNull String packageName, @Nullable String callingAttributionTag) {
+ Objects.requireNonNull(packageName);
+ Objects.requireNonNull(lp);
+ enforceNetworkStackOrSettingsPermission();
+ if (!checkAccessPermission(-1 /* pid */, uid)) {
+ return null;
+ }
+ return linkPropertiesRestrictedForCallerPermissions(lp, -1 /* callerPid */, uid);
+ }
+
private NetworkCapabilities getNetworkCapabilitiesInternal(Network network) {
return getNetworkCapabilitiesInternal(getNetworkAgentInfoForNetwork(network));
}
@@ -2103,13 +2200,34 @@
getCallingPid(), mDeps.getCallingUid(), callingPackageName, callingAttributionTag);
}
+ @Override
+ public NetworkCapabilities redactNetworkCapabilitiesForPackage(@NonNull NetworkCapabilities nc,
+ int uid, @NonNull String packageName, @Nullable String callingAttributionTag) {
+ Objects.requireNonNull(nc);
+ Objects.requireNonNull(packageName);
+ enforceNetworkStackOrSettingsPermission();
+ if (!checkAccessPermission(-1 /* pid */, uid)) {
+ return null;
+ }
+ return createWithLocationInfoSanitizedIfNecessaryWhenParceled(
+ networkCapabilitiesRestrictedForCallerPermissions(nc, -1 /* callerPid */, uid),
+ true /* includeLocationSensitiveInfo */, -1 /* callingPid */, uid, packageName,
+ callingAttributionTag);
+ }
+
@VisibleForTesting
NetworkCapabilities networkCapabilitiesRestrictedForCallerPermissions(
NetworkCapabilities nc, int callerPid, int callerUid) {
+ // Note : here it would be nice to check ACCESS_NETWORK_STATE and return null, but
+ // this would be expensive (one more permission check every time any NC callback is
+ // sent) and possibly dangerous : apps normally can't lose ACCESS_NETWORK_STATE, if
+ // it happens for some reason (e.g. the package is uninstalled while CS is trying to
+ // send the callback) it would crash the system server with NPE.
final NetworkCapabilities newNc = new NetworkCapabilities(nc);
if (!checkSettingsPermission(callerPid, callerUid)) {
newNc.setUids(null);
newNc.setSSID(null);
+ // TODO: Processes holding NETWORK_FACTORY should be able to see the underlying networks
newNc.setUnderlyingNetworks(null);
}
if (newNc.getNetworkSpecifier() != null) {
@@ -2127,7 +2245,7 @@
/**
* Wrapper used to cache the permission check results performed for the corresponding
- * app. This avoid performing multiple permission checks for different fields in
+ * app. This avoids performing multiple permission checks for different fields in
* NetworkCapabilities.
* Note: This wrapper does not support any sort of invalidation and thus must not be
* persistent or long-lived. It may only be used for the time necessary to
@@ -2255,6 +2373,8 @@
includeLocationSensitiveInfo);
final NetworkCapabilities newNc = new NetworkCapabilities(nc, redactions);
// Reset owner uid if not destined for the owner app.
+ // TODO : calling UID is redacted because apps should generally not know what UID is
+ // bringing up the VPN, but this should not apply to some very privileged apps like settings
if (callingUid != nc.getOwnerUid()) {
newNc.setOwnerUid(INVALID_UID);
return newNc;
@@ -2280,9 +2400,15 @@
return newNc;
}
+ @NonNull
private LinkProperties linkPropertiesRestrictedForCallerPermissions(
LinkProperties lp, int callerPid, int callerUid) {
if (lp == null) return new LinkProperties();
+ // Note : here it would be nice to check ACCESS_NETWORK_STATE and return null, but
+ // this would be expensive (one more permission check every time any LP callback is
+ // sent) and possibly dangerous : apps normally can't lose ACCESS_NETWORK_STATE, if
+ // it happens for some reason (e.g. the package is uninstalled while CS is trying to
+ // send the callback) it would crash the system server with NPE.
// Only do a permission check if sanitization is needed, to avoid unnecessary binder calls.
final boolean needsSanitization =
@@ -2653,6 +2779,11 @@
"ConnectivityService");
}
+ private boolean checkAccessPermission(int pid, int uid) {
+ return mContext.checkPermission(android.Manifest.permission.ACCESS_NETWORK_STATE, pid, uid)
+ == PERMISSION_GRANTED;
+ }
+
/**
* Performs a strict and comprehensive check of whether a calling package is allowed to
* change the state of network, as the condition differs for pre-M, M+, and
@@ -4090,6 +4221,11 @@
// for an unnecessarily long time.
destroyNativeNetwork(nai);
mDnsManager.removeNetwork(nai.network);
+
+ // clean up tc police filters on interface.
+ if (canNetworkBeRateLimited(nai) && mIngressRateLimit >= 0) {
+ mDeps.disableIngressRateLimit(nai.linkProperties.getInterfaceName());
+ }
}
mNetIdManager.releaseNetId(nai.network.getNetId());
nai.onNetworkDestroyed();
@@ -5157,6 +5293,9 @@
final long timeMs = ((Long) msg.obj).longValue();
mMultinetworkPolicyTracker.setTestAllowBadWifiUntil(timeMs);
break;
+ case EVENT_INGRESS_RATE_LIMIT_CHANGED:
+ handleIngressRateLimitChanged();
+ break;
}
}
}
@@ -8853,6 +8992,19 @@
// A network that has just connected has zero requests and is thus a foreground network.
networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
+ // If a rate limit has been configured and is applicable to this network (network
+ // provides internet connectivity), apply it.
+ // Note: in case of a system server crash, there is a very small chance that this
+ // leaves some interfaces rate limited (i.e. if the rate limit had been changed just
+ // before the crash and was never applied). One solution would be to delete all
+ // potential tc police filters every time this is called. Since this is an unlikely
+ // scenario in the first place (and worst case, the interface stays rate limited until
+ // the device is rebooted), this seems a little overkill.
+ if (canNetworkBeRateLimited(networkAgent) && mIngressRateLimit >= 0) {
+ mDeps.enableIngressRateLimit(networkAgent.linkProperties.getInterfaceName(),
+ mIngressRateLimit);
+ }
+
if (!createNativeNetwork(networkAgent)) return;
if (networkAgent.propagateUnderlyingCapabilities()) {
// Initialize the network's capabilities to their starting values according to the
@@ -8883,10 +9035,12 @@
if (networkAgent.networkAgentConfig.acceptPartialConnectivity) {
networkAgent.networkMonitor().setAcceptPartialConnectivity();
}
- networkAgent.networkMonitor().notifyNetworkConnected(
- new LinkProperties(networkAgent.linkProperties,
- true /* parcelSensitiveFields */),
- networkAgent.networkCapabilities);
+ final NetworkMonitorParameters params = new NetworkMonitorParameters();
+ params.networkAgentConfig = networkAgent.networkAgentConfig;
+ params.networkCapabilities = networkAgent.networkCapabilities;
+ params.linkProperties = new LinkProperties(networkAgent.linkProperties,
+ true /* parcelSensitiveFields */);
+ networkAgent.networkMonitor().notifyNetworkConnected(params);
scheduleUnvalidatedPrompt(networkAgent);
// Whether a particular NetworkRequest listen should cause signal strength thresholds to
@@ -10511,6 +10665,39 @@
rematchAllNetworksAndRequests();
}
+ private void handleIngressRateLimitChanged() {
+ final long oldIngressRateLimit = mIngressRateLimit;
+ mIngressRateLimit = ConnectivitySettingsManager.getIngressRateLimitInBytesPerSecond(
+ mContext);
+ for (final NetworkAgentInfo networkAgent : mNetworkAgentInfos) {
+ if (canNetworkBeRateLimited(networkAgent)) {
+ // If rate limit has previously been enabled, remove the old limit first.
+ if (oldIngressRateLimit >= 0) {
+ mDeps.disableIngressRateLimit(networkAgent.linkProperties.getInterfaceName());
+ }
+ if (mIngressRateLimit >= 0) {
+ mDeps.enableIngressRateLimit(networkAgent.linkProperties.getInterfaceName(),
+ mIngressRateLimit);
+ }
+ }
+ }
+ }
+
+ private boolean canNetworkBeRateLimited(@NonNull final NetworkAgentInfo networkAgent) {
+ if (!networkAgent.networkCapabilities.hasCapability(NET_CAPABILITY_INTERNET)) {
+ // rate limits only apply to networks that provide internet connectivity.
+ return false;
+ }
+
+ final String iface = networkAgent.linkProperties.getInterfaceName();
+ if (iface == null) {
+ // This can never happen.
+ logwtf("canNetworkBeRateLimited: LinkProperties#getInterfaceName returns null");
+ return false;
+ }
+ return true;
+ }
+
private void enforceAutomotiveDevice() {
PermissionUtils.enforceSystemFeature(mContext, PackageManager.FEATURE_AUTOMOTIVE,
"setOemNetworkPreference() is only available on automotive devices.");
diff --git a/tests/common/Android.bp b/tests/common/Android.bp
index acf04bf..8782684 100644
--- a/tests/common/Android.bp
+++ b/tests/common/Android.bp
@@ -88,6 +88,7 @@
"libstaticjvmtiagent",
// For NetworkStackUtils included in NetworkStackBase
"libnetworkstackutilsjni",
+ "libandroid_net_connectivity_com_android_net_module_util_jni",
"libcom_android_networkstack_tethering_util_jni",
// For framework tests
"libservice-connectivity",
diff --git a/tests/common/java/android/net/ConnectivitySettingsManagerTest.kt b/tests/common/java/android/net/ConnectivitySettingsManagerTest.kt
index ebaa787..8d8958d 100644
--- a/tests/common/java/android/net/ConnectivitySettingsManagerTest.kt
+++ b/tests/common/java/android/net/ConnectivitySettingsManagerTest.kt
@@ -39,6 +39,7 @@
import android.net.ConnectivitySettingsManager.getDnsResolverSampleRanges
import android.net.ConnectivitySettingsManager.getDnsResolverSampleValidityDuration
import android.net.ConnectivitySettingsManager.getDnsResolverSuccessThresholdPercent
+import android.net.ConnectivitySettingsManager.getIngressRateLimitInBytesPerSecond
import android.net.ConnectivitySettingsManager.getMobileDataActivityTimeout
import android.net.ConnectivitySettingsManager.getMobileDataAlwaysOn
import android.net.ConnectivitySettingsManager.getNetworkSwitchNotificationMaximumDailyCount
@@ -51,6 +52,7 @@
import android.net.ConnectivitySettingsManager.setDnsResolverSampleRanges
import android.net.ConnectivitySettingsManager.setDnsResolverSampleValidityDuration
import android.net.ConnectivitySettingsManager.setDnsResolverSuccessThresholdPercent
+import android.net.ConnectivitySettingsManager.setIngressRateLimitInBytesPerSecond
import android.net.ConnectivitySettingsManager.setMobileDataActivityTimeout
import android.net.ConnectivitySettingsManager.setMobileDataAlwaysOn
import android.net.ConnectivitySettingsManager.setNetworkSwitchNotificationMaximumDailyCount
@@ -292,4 +294,19 @@
setter = { setWifiAlwaysRequested(context, it) },
testIntValues = intArrayOf(0))
}
+
+ @Test
+ fun testInternetNetworkRateLimitInBytesPerSecond() {
+ val defaultRate = getIngressRateLimitInBytesPerSecond(context)
+ val testRate = 1000L
+ setIngressRateLimitInBytesPerSecond(context, testRate)
+ assertEquals(testRate, getIngressRateLimitInBytesPerSecond(context))
+
+ setIngressRateLimitInBytesPerSecond(context, defaultRate)
+ assertEquals(defaultRate, getIngressRateLimitInBytesPerSecond(context))
+
+ assertFailsWith<IllegalArgumentException>("Expected failure, but setting accepted") {
+ setIngressRateLimitInBytesPerSecond(context, -10)
+ }
+ }
}
\ No newline at end of file
diff --git a/tests/common/java/android/net/NetworkAgentConfigTest.kt b/tests/common/java/android/net/NetworkAgentConfigTest.kt
index b339a27..e5db09f 100644
--- a/tests/common/java/android/net/NetworkAgentConfigTest.kt
+++ b/tests/common/java/android/net/NetworkAgentConfigTest.kt
@@ -20,6 +20,7 @@
import androidx.test.filters.SmallTest
import androidx.test.runner.AndroidJUnit4
import com.android.modules.utils.build.SdkLevel.isAtLeastS
+import com.android.modules.utils.build.SdkLevel.isAtLeastT
import com.android.testutils.ConnectivityModuleTest
import com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
@@ -49,6 +50,10 @@
if (isAtLeastS()) {
setBypassableVpn(true)
}
+ if (isAtLeastT()) {
+ setLocalRoutesExcludedForVpn(true)
+ setVpnRequiresValidation(true)
+ }
}.build()
assertParcelingIsLossless(config)
}
@@ -69,6 +74,10 @@
setProvisioningNotificationEnabled(false)
setBypassableVpn(true)
}
+ if (isAtLeastT()) {
+ setLocalRoutesExcludedForVpn(true)
+ setVpnRequiresValidation(true)
+ }
}.build()
assertTrue(config.isExplicitlySelected())
@@ -77,6 +86,10 @@
assertFalse(config.isPartialConnectivityAcceptable())
assertTrue(config.isUnvalidatedConnectivityAcceptable())
assertEquals("TEST_NETWORK", config.getLegacyTypeName())
+ if (isAtLeastT()) {
+ assertTrue(config.areLocalRoutesExcludedForVpn())
+ assertTrue(config.getVpnRequiresValidation())
+ }
if (isAtLeastS()) {
assertEquals(testExtraInfo, config.getLegacyExtraInfo())
assertFalse(config.isNat64DetectionEnabled())
diff --git a/tests/common/java/android/net/NetworkCapabilitiesTest.java b/tests/common/java/android/net/NetworkCapabilitiesTest.java
index 742044b..b6926a8 100644
--- a/tests/common/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/common/java/android/net/NetworkCapabilitiesTest.java
@@ -49,6 +49,7 @@
import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
import static android.net.NetworkCapabilities.SIGNAL_STRENGTH_UNSPECIFIED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
import static android.net.NetworkCapabilities.TRANSPORT_TEST;
import static android.net.NetworkCapabilities.TRANSPORT_USB;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
@@ -727,25 +728,38 @@
@Test
public void testSetNetworkSpecifierOnMultiTransportNc() {
// Sequence 1: Transport + Transport + NetworkSpecifier
- NetworkCapabilities nc1 = new NetworkCapabilities();
+ NetworkCapabilities.Builder nc1 = new NetworkCapabilities.Builder();
nc1.addTransportType(TRANSPORT_CELLULAR).addTransportType(TRANSPORT_WIFI);
- try {
- nc1.setNetworkSpecifier(CompatUtil.makeEthernetNetworkSpecifier("eth0"));
- fail("Cannot set NetworkSpecifier on a NetworkCapability with multiple transports!");
- } catch (IllegalStateException expected) {
- // empty
- }
+ final NetworkSpecifier specifier = CompatUtil.makeEthernetNetworkSpecifier("eth0");
+ assertThrows("Cannot set NetworkSpecifier on a NetworkCapability with multiple transports!",
+ IllegalStateException.class,
+ () -> nc1.build().setNetworkSpecifier(specifier));
+ assertThrows("Cannot set NetworkSpecifier on a NetworkCapability with multiple transports!",
+ IllegalStateException.class,
+ () -> nc1.setNetworkSpecifier(specifier));
// Sequence 2: Transport + NetworkSpecifier + Transport
- NetworkCapabilities nc2 = new NetworkCapabilities();
- nc2.addTransportType(TRANSPORT_CELLULAR).setNetworkSpecifier(
- CompatUtil.makeEthernetNetworkSpecifier("testtap3"));
- try {
- nc2.addTransportType(TRANSPORT_WIFI);
- fail("Cannot set a second TransportType of a network which has a NetworkSpecifier!");
- } catch (IllegalStateException expected) {
- // empty
- }
+ NetworkCapabilities.Builder nc2 = new NetworkCapabilities.Builder();
+ nc2.addTransportType(TRANSPORT_CELLULAR).setNetworkSpecifier(specifier);
+
+ assertThrows("Cannot set a second TransportType of a network which has a NetworkSpecifier!",
+ IllegalStateException.class,
+ () -> nc2.build().addTransportType(TRANSPORT_WIFI));
+ assertThrows("Cannot set a second TransportType of a network which has a NetworkSpecifier!",
+ IllegalStateException.class,
+ () -> nc2.addTransportType(TRANSPORT_WIFI));
+ }
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.R) // New behavior in updatable NetworkCapabilities (S+)
+ public void testSetNetworkSpecifierOnTestMultiTransportNc() {
+ final NetworkSpecifier specifier = CompatUtil.makeEthernetNetworkSpecifier("eth0");
+ NetworkCapabilities nc = new NetworkCapabilities.Builder()
+ .addTransportType(TRANSPORT_TEST)
+ .addTransportType(TRANSPORT_ETHERNET)
+ .setNetworkSpecifier(specifier)
+ .build();
+ // Adding a specifier did not crash with 2 transports if one is TEST
+ assertEquals(specifier, nc.getNetworkSpecifier());
}
@Test
diff --git a/tests/cts/hostside/app2/Android.bp b/tests/cts/hostside/app2/Android.bp
index 4c9bccf..01c8cd2 100644
--- a/tests/cts/hostside/app2/Android.bp
+++ b/tests/cts/hostside/app2/Android.bp
@@ -22,7 +22,10 @@
name: "CtsHostsideNetworkTestsApp2",
defaults: ["cts_support_defaults"],
sdk_version: "test_current",
- static_libs: ["CtsHostsideNetworkTestsAidl"],
+ static_libs: [
+ "CtsHostsideNetworkTestsAidl",
+ "NetworkStackApiStableShims",
+ ],
srcs: ["src/**/*.java"],
// Tag this module as a cts test artifact
test_suites: [
diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyService.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyService.java
index 3b5e46f..f2a7b3f 100644
--- a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyService.java
+++ b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyService.java
@@ -21,6 +21,7 @@
import static com.android.cts.net.hostside.app2.Common.ACTION_SNOOZE_WARNING;
import static com.android.cts.net.hostside.app2.Common.DYNAMIC_RECEIVER;
import static com.android.cts.net.hostside.app2.Common.TAG;
+import static com.android.networkstack.apishim.ConstantsShim.RECEIVER_EXPORTED;
import android.app.NotificationChannel;
import android.app.NotificationManager;
@@ -40,6 +41,7 @@
import com.android.cts.net.hostside.IMyService;
import com.android.cts.net.hostside.INetworkCallback;
+import com.android.modules.utils.build.SdkLevel;
/**
* Service used to dynamically register a broadcast receiver.
@@ -64,11 +66,14 @@
return;
}
final Context context = getApplicationContext();
+ final int flags = SdkLevel.isAtLeastT() ? RECEIVER_EXPORTED : 0;
mReceiver = new MyBroadcastReceiver(DYNAMIC_RECEIVER);
- context.registerReceiver(mReceiver, new IntentFilter(ACTION_RECEIVER_READY));
context.registerReceiver(mReceiver,
- new IntentFilter(ACTION_RESTRICT_BACKGROUND_CHANGED));
- context.registerReceiver(mReceiver, new IntentFilter(ACTION_SNOOZE_WARNING));
+ new IntentFilter(ACTION_RECEIVER_READY), flags);
+ context.registerReceiver(mReceiver,
+ new IntentFilter(ACTION_RESTRICT_BACKGROUND_CHANGED), flags);
+ context.registerReceiver(mReceiver,
+ new IntentFilter(ACTION_SNOOZE_WARNING), flags);
Log.d(TAG, "receiver registered");
}
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index 53e4ab7..ea64252 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -16,9 +16,15 @@
package android.net.cts;
+import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
+import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+import static android.Manifest.permission.ACCESS_NETWORK_STATE;
import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
+import static android.Manifest.permission.NETWORK_FACTORY;
import static android.Manifest.permission.NETWORK_SETTINGS;
+import static android.Manifest.permission.NETWORK_SETUP_WIZARD;
+import static android.Manifest.permission.NETWORK_STACK;
import static android.Manifest.permission.READ_DEVICE_CONFIG;
import static android.content.pm.PackageManager.FEATURE_BLUETOOTH;
import static android.content.pm.PackageManager.FEATURE_ETHERNET;
@@ -54,7 +60,9 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_TEST;
+import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import static android.net.cts.util.CtsNetUtils.ConnectivityActionReceiver;
import static android.net.cts.util.CtsNetUtils.HTTP_PORT;
import static android.net.cts.util.CtsNetUtils.NETWORK_CALLBACK_ACTION;
@@ -64,6 +72,7 @@
import static android.net.util.NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTPS_URL;
import static android.net.util.NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTP_URL;
import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
+import static android.os.Process.INVALID_UID;
import static android.provider.Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
import static android.system.OsConstants.AF_INET;
import static android.system.OsConstants.AF_INET6;
@@ -76,6 +85,7 @@
import static com.android.networkstack.apishim.ConstantsShim.BLOCKED_REASON_LOCKDOWN_VPN;
import static com.android.networkstack.apishim.ConstantsShim.BLOCKED_REASON_NONE;
import static com.android.testutils.Cleanup.testAndCleanup;
+import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
import static com.android.testutils.MiscAsserts.assertThrows;
import static com.android.testutils.TestNetworkTrackerKt.initTestNetwork;
import static com.android.testutils.TestPermissionUtil.runAsShell;
@@ -103,6 +113,7 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
+import android.net.CaptivePortalData;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.ConnectivitySettingsManager;
@@ -132,6 +143,7 @@
import android.net.cts.util.CtsNetUtils;
import android.net.cts.util.CtsTetheringUtils;
import android.net.util.KeepaliveUtils;
+import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Binder;
import android.os.Build;
@@ -160,6 +172,7 @@
import com.android.internal.util.ArrayUtils;
import com.android.modules.utils.build.SdkLevel;
+import com.android.net.module.util.CollectionUtils;
import com.android.networkstack.apishim.ConnectivityManagerShimImpl;
import com.android.networkstack.apishim.ConstantsShim;
import com.android.networkstack.apishim.NetworkInformationShimImpl;
@@ -554,6 +567,223 @@
}
}
+ private boolean checkPermission(String perm, int uid) {
+ return mContext.checkPermission(perm, -1 /* pid */, uid) == PERMISSION_GRANTED;
+ }
+
+ private String findPackageByPermissions(@NonNull List<String> requiredPermissions,
+ @NonNull List<String> forbiddenPermissions) throws Exception {
+ final List<PackageInfo> packageInfos =
+ mPackageManager.getInstalledPackages(GET_PERMISSIONS);
+ for (PackageInfo packageInfo : packageInfos) {
+ final int uid = mPackageManager.getPackageUid(packageInfo.packageName, 0 /* flags */);
+ if (!CollectionUtils.all(requiredPermissions, perm -> checkPermission(perm, uid))) {
+ continue;
+ }
+ if (CollectionUtils.any(forbiddenPermissions, perm -> checkPermission(perm, uid))) {
+ continue;
+ }
+
+ return packageInfo.packageName;
+ }
+ return null;
+ }
+
+ @DevSdkIgnoreRule.IgnoreUpTo(SC_V2)
+ @Test
+ public void testRedactLinkPropertiesForPackage() throws Exception {
+ final String groundedPkg = findPackageByPermissions(
+ List.of(), /* requiredPermissions */
+ List.of(ACCESS_NETWORK_STATE) /* forbiddenPermissions */);
+ assertNotNull("Couldn't find any package without ACCESS_NETWORK_STATE", groundedPkg);
+ final int groundedUid = mPackageManager.getPackageUid(groundedPkg, 0 /* flags */);
+
+ final String normalPkg = findPackageByPermissions(
+ List.of(ACCESS_NETWORK_STATE) /* requiredPermissions */,
+ List.of(NETWORK_SETTINGS, NETWORK_STACK,
+ PERMISSION_MAINLINE_NETWORK_STACK) /* forbiddenPermissions */);
+ assertNotNull("Couldn't find any package with ACCESS_NETWORK_STATE but"
+ + " without NETWORK_SETTINGS", normalPkg);
+ final int normalUid = mPackageManager.getPackageUid(normalPkg, 0 /* flags */);
+
+ // There are some privileged packages on the system, like the phone process, the network
+ // stack and the system server.
+ final String privilegedPkg = findPackageByPermissions(
+ List.of(ACCESS_NETWORK_STATE, NETWORK_SETTINGS), /* requiredPermissions */
+ List.of() /* forbiddenPermissions */);
+ assertNotNull("Couldn't find a package with sufficient permissions", privilegedPkg);
+ final int privilegedUid = mPackageManager.getPackageUid(privilegedPkg, 0);
+
+ // Set parcelSensitiveFields to true to preserve CaptivePortalApiUrl & CaptivePortalData
+ // when parceling.
+ final LinkProperties lp = new LinkProperties(new LinkProperties(),
+ true /* parcelSensitiveFields */);
+ final Uri capportUrl = Uri.parse("https://capport.example.com/api");
+ final CaptivePortalData capportData = new CaptivePortalData.Builder().build();
+ final int mtu = 12345;
+ lp.setMtu(mtu);
+ lp.setCaptivePortalApiUrl(capportUrl);
+ lp.setCaptivePortalData(capportData);
+
+ // No matter what the given uid is, a SecurityException will be thrown if the caller
+ // doesn't hold the NETWORK_SETTINGS permission.
+ assertThrows(SecurityException.class,
+ () -> mCm.redactLinkPropertiesForPackage(lp, groundedUid, groundedPkg));
+ assertThrows(SecurityException.class,
+ () -> mCm.redactLinkPropertiesForPackage(lp, normalUid, normalPkg));
+ assertThrows(SecurityException.class,
+ () -> mCm.redactLinkPropertiesForPackage(lp, privilegedUid, privilegedPkg));
+
+ runAsShell(NETWORK_SETTINGS, () -> {
+ // No matter what the given uid is, if the given LinkProperties is null, then
+ // NullPointerException will be thrown.
+ assertThrows(NullPointerException.class,
+ () -> mCm.redactLinkPropertiesForPackage(null, groundedUid, groundedPkg));
+ assertThrows(NullPointerException.class,
+ () -> mCm.redactLinkPropertiesForPackage(null, normalUid, normalPkg));
+ assertThrows(NullPointerException.class,
+ () -> mCm.redactLinkPropertiesForPackage(null, privilegedUid, privilegedPkg));
+
+ // Make sure null is returned for a UID without ACCESS_NETWORK_STATE.
+ assertNull(mCm.redactLinkPropertiesForPackage(lp, groundedUid, groundedPkg));
+
+ // CaptivePortalApiUrl & CaptivePortalData will be set to null if given uid doesn't hold
+ // the NETWORK_SETTINGS permission.
+ assertNull(mCm.redactLinkPropertiesForPackage(lp, normalUid, normalPkg)
+ .getCaptivePortalApiUrl());
+ assertNull(mCm.redactLinkPropertiesForPackage(lp, normalUid, normalPkg)
+ .getCaptivePortalData());
+ // MTU is not sensitive and is not redacted.
+ assertEquals(mtu, mCm.redactLinkPropertiesForPackage(lp, normalUid, normalPkg)
+ .getMtu());
+
+ // CaptivePortalApiUrl & CaptivePortalData will be preserved if the given uid holds the
+ // NETWORK_SETTINGS permission.
+ assertEquals(capportUrl,
+ mCm.redactLinkPropertiesForPackage(lp, privilegedUid, privilegedPkg)
+ .getCaptivePortalApiUrl());
+ assertEquals(capportData,
+ mCm.redactLinkPropertiesForPackage(lp, privilegedUid, privilegedPkg)
+ .getCaptivePortalData());
+ });
+ }
+
+ private NetworkCapabilities redactNc(@NonNull final NetworkCapabilities nc, int uid,
+ @NonNull String packageName) {
+ return mCm.redactNetworkCapabilitiesForPackage(nc, uid, packageName);
+ }
+
+ @DevSdkIgnoreRule.IgnoreUpTo(SC_V2)
+ @Test
+ public void testRedactNetworkCapabilitiesForPackage() throws Exception {
+ final String groundedPkg = findPackageByPermissions(
+ List.of(), /* requiredPermissions */
+ List.of(ACCESS_NETWORK_STATE) /* forbiddenPermissions */);
+ assertNotNull("Couldn't find any package without ACCESS_NETWORK_STATE", groundedPkg);
+ final int groundedUid = mPackageManager.getPackageUid(groundedPkg, 0 /* flags */);
+
+ // A package which doesn't have any of the permissions below, but has NETWORK_STATE.
+ // There should be a number of packages like this on the device; AOSP has many,
+ // including contacts, webview, the keyboard, pacprocessor, messaging.
+ final String normalPkg = findPackageByPermissions(
+ List.of(ACCESS_NETWORK_STATE) /* requiredPermissions */,
+ List.of(NETWORK_SETTINGS, NETWORK_FACTORY, NETWORK_SETUP_WIZARD,
+ NETWORK_STACK, PERMISSION_MAINLINE_NETWORK_STACK,
+ ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION) /* forbiddenPermissions */);
+ assertNotNull("Can't find a package with ACCESS_NETWORK_STATE but without any of"
+ + " the forbidden permissions", normalPkg);
+ final int normalUid = mPackageManager.getPackageUid(normalPkg, 0 /* flags */);
+
+ // There are some privileged packages on the system, like the phone process, the network
+ // stack and the system server.
+ final String privilegedPkg = findPackageByPermissions(
+ List.of(ACCESS_NETWORK_STATE, NETWORK_SETTINGS, NETWORK_FACTORY,
+ ACCESS_FINE_LOCATION), /* requiredPermissions */
+ List.of() /* forbiddenPermissions */);
+ assertNotNull("Couldn't find a package with sufficient permissions", privilegedPkg);
+ final int privilegedUid = mPackageManager.getPackageUid(privilegedPkg, 0);
+
+ final Set<Range<Integer>> uids = new ArraySet<>();
+ uids.add(new Range<>(10000, 10100));
+ uids.add(new Range<>(10200, 10300));
+ final String ssid = "My-WiFi";
+ // This test will set underlying networks in the capabilities to redact to see if they
+ // are appropriately redacted, so fetch the default network to put in there as an example.
+ final Network defaultNetwork = mCm.getActiveNetwork();
+ assertNotNull("CTS requires a working Internet connection", defaultNetwork);
+ final int subId1 = 1;
+ final int subId2 = 2;
+ final int[] administratorUids = {normalUid};
+ final String bssid = "location sensitive";
+ final int rssi = 43; // not location sensitive
+ final WifiInfo wifiInfo = new WifiInfo.Builder()
+ .setBssid(bssid)
+ .setRssi(rssi)
+ .build();
+ final NetworkCapabilities nc = new NetworkCapabilities.Builder()
+ .setUids(uids)
+ .setSsid(ssid)
+ .setUnderlyingNetworks(List.of(defaultNetwork))
+ .setSubscriptionIds(Set.of(subId1, subId2))
+ .setAdministratorUids(administratorUids)
+ .setOwnerUid(normalUid)
+ .setTransportInfo(wifiInfo)
+ .build();
+
+ // No matter what the given uid is, a SecurityException will be thrown if the caller
+ // doesn't hold the NETWORK_SETTINGS permission.
+ assertThrows(SecurityException.class, () -> redactNc(nc, groundedUid, groundedPkg));
+ assertThrows(SecurityException.class, () -> redactNc(nc, normalUid, normalPkg));
+ assertThrows(SecurityException.class, () -> redactNc(nc, privilegedUid, privilegedPkg));
+
+ runAsShell(NETWORK_SETTINGS, () -> {
+ // Make sure that the NC is null if the package doesn't hold ACCESS_NETWORK_STATE.
+ assertNull(redactNc(nc, groundedUid, groundedPkg));
+
+ // Uids, ssid, underlying networks & subscriptionIds will be redacted if the given uid
+ // doesn't hold the associated permissions. The wifi transport info is also suitably
+ // redacted.
+ final NetworkCapabilities redactedNormal = redactNc(nc, normalUid, normalPkg);
+ assertNull(redactedNormal.getUids());
+ assertNull(redactedNormal.getSsid());
+ assertNull(redactedNormal.getUnderlyingNetworks());
+ assertEquals(0, redactedNormal.getSubscriptionIds().size());
+ assertEquals(WifiInfo.DEFAULT_MAC_ADDRESS,
+ ((WifiInfo) redactedNormal.getTransportInfo()).getBSSID());
+ assertEquals(rssi, ((WifiInfo) redactedNormal.getTransportInfo()).getRssi());
+
+ // Uids, ssid, underlying networks & subscriptionIds will be preserved if the given uid
+ // holds the associated permissions.
+ final NetworkCapabilities redactedPrivileged =
+ redactNc(nc, privilegedUid, privilegedPkg);
+ assertEquals(uids, redactedPrivileged.getUids());
+ assertEquals(ssid, redactedPrivileged.getSsid());
+ assertEquals(List.of(defaultNetwork), redactedPrivileged.getUnderlyingNetworks());
+ assertEquals(Set.of(subId1, subId2), redactedPrivileged.getSubscriptionIds());
+ assertEquals(bssid, ((WifiInfo) redactedPrivileged.getTransportInfo()).getBSSID());
+ assertEquals(rssi, ((WifiInfo) redactedPrivileged.getTransportInfo()).getRssi());
+
+ // The owner uid is only preserved when the network is a VPN and the uid is the
+ // same as the owner uid.
+ nc.addTransportType(TRANSPORT_VPN);
+ assertEquals(normalUid, redactNc(nc, normalUid, normalPkg).getOwnerUid());
+ assertEquals(INVALID_UID, redactNc(nc, privilegedUid, privilegedPkg).getOwnerUid());
+ nc.removeTransportType(TRANSPORT_VPN);
+
+ // If the given uid doesn't hold location permissions, the owner uid will be set to
+ // INVALID_UID even when sent to that UID (this avoids a wifi suggestor knowing where
+ // the device is by virtue of the device connecting to its own network).
+ assertEquals(INVALID_UID, redactNc(nc, normalUid, normalPkg).getOwnerUid());
+
+ // If the given uid holds location permissions, the owner uid is preserved. This works
+ // because the shell holds ACCESS_FINE_LOCATION.
+ final int[] administratorUids2 = { privilegedUid };
+ nc.setAdministratorUids(administratorUids2);
+ nc.setOwnerUid(privilegedUid);
+ assertEquals(privilegedUid, redactNc(nc, privilegedUid, privilegedPkg).getOwnerUid());
+ });
+ }
+
/**
* Tests that connections can be opened on WiFi and cellphone networks,
* and that they are made from different IP addresses.
diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp
index 25b391a..fde7bac 100644
--- a/tests/unit/Android.bp
+++ b/tests/unit/Android.bp
@@ -27,7 +27,6 @@
"libbase",
"libbinder",
"libbpf_bcc",
- "libbpf_android",
"libc++",
"libcgrouprc",
"libcrypto",
@@ -107,8 +106,8 @@
visibility: ["//visibility:private"],
}
-android_library {
- name: "FrameworksNetTestsLib",
+java_defaults {
+ name: "FrameworksNetTestsDefaults",
min_sdk_version: "30",
defaults: [
"framework-connectivity-test-defaults",
@@ -117,8 +116,6 @@
"java/**/*.java",
"java/**/*.kt",
],
- exclude_srcs: [":non-connectivity-module-test"],
- jarjar_rules: "jarjar-rules.txt",
static_libs: [
"androidx.test.rules",
"androidx.test.uiautomator",
@@ -144,31 +141,33 @@
"android.test.mock",
"ServiceConnectivityResources",
],
- visibility: ["//packages/modules/Connectivity/tests:__subpackages__"],
exclude_kotlinc_generated_files: false,
}
+android_library {
+ name: "FrameworksNetTestsLib",
+ defaults: [
+ "FrameworksNetTestsDefaults",
+ ],
+ exclude_srcs: [":non-connectivity-module-test"],
+ visibility: ["//packages/modules/Connectivity/tests:__subpackages__"],
+}
+
android_test {
name: "FrameworksNetTests",
enabled: enable_frameworks_net_tests,
- min_sdk_version: "30",
defaults: [
- "framework-connectivity-test-defaults",
+ "FrameworksNetTestsDefaults",
"FrameworksNetTests-jni-defaults",
],
- // this is in addition to FrameworksNetTestsLib.
- srcs: [":non-connectivity-module-test"],
+ jarjar_rules: ":connectivity-jarjar-rules",
test_suites: ["device-tests"],
static_libs: [
"services.core",
"services.net",
- "FrameworksNetTestsLib",
- ],
- libs: [
- "android.test.mock",
- "android.test.base",
],
jni_libs: [
"libservice-connectivity",
- ]
+ "libandroid_net_connectivity_com_android_net_module_util_jni",
+ ],
}
diff --git a/tests/unit/java/android/net/Ikev2VpnProfileTest.java b/tests/unit/java/android/net/Ikev2VpnProfileTest.java
index a151f03..8559c20 100644
--- a/tests/unit/java/android/net/Ikev2VpnProfileTest.java
+++ b/tests/unit/java/android/net/Ikev2VpnProfileTest.java
@@ -16,6 +16,8 @@
package android.net;
+import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
+
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -264,17 +266,17 @@
}
- // TODO: Refer to Build.VERSION_CODES.SC_V2 when it's available in AOSP
- @DevSdkIgnoreRule.IgnoreUpTo(32)
+ // TODO: Refer to Build.VERSION_CODES.SC_V2 when it's available in AOSP and mainline branch
+ @DevSdkIgnoreRule.IgnoreUpTo(SC_V2)
@Test
public void testBuildExcludeLocalRoutesSet() throws Exception {
final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
builder.setAuthPsk(PSK_BYTES);
- builder.setExcludeLocalRoutes(true);
+ builder.setLocalRoutesExcluded(true);
final Ikev2VpnProfile profile = builder.build();
assertNotNull(profile);
- assertTrue(profile.getExcludeLocalRoutes());
+ assertTrue(profile.areLocalRoutesExcluded());
builder.setBypassable(false);
try {
diff --git a/tests/unit/java/com/android/internal/net/VpnProfileTest.java b/tests/unit/java/com/android/internal/net/VpnProfileTest.java
index 960a9f1..943a559 100644
--- a/tests/unit/java/com/android/internal/net/VpnProfileTest.java
+++ b/tests/unit/java/com/android/internal/net/VpnProfileTest.java
@@ -50,6 +50,7 @@
private static final int ENCODED_INDEX_AUTH_PARAMS_INLINE = 23;
private static final int ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS = 24;
private static final int ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE = 25;
+ private static final int ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION = 26;
@Test
public void testDefaults() throws Exception {
@@ -78,10 +79,13 @@
assertEquals(1360, p.maxMtu);
assertFalse(p.areAuthParamsInline);
assertFalse(p.isRestrictedToTestNetworks);
+ assertFalse(p.excludeLocalRoutes);
+ assertFalse(p.requiresInternetValidation);
}
private VpnProfile getSampleIkev2Profile(String key) {
- final VpnProfile p = new VpnProfile(key, true /* isRestrictedToTestNetworks */);
+ final VpnProfile p = new VpnProfile(key, true /* isRestrictedToTestNetworks */,
+ false /* excludesLocalRoutes */, true /* requiresPlatformValidation */);
p.name = "foo";
p.type = VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS;
@@ -129,8 +133,8 @@
@Test
public void testParcelUnparcel() {
if (isAtLeastT()) {
- // excludeLocalRoutes is added in T.
- assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 24);
+ // excludeLocalRoutes, requiresPlatformValidation were added in T.
+ assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 25);
} else {
assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 23);
}
@@ -174,7 +178,8 @@
getEncodedDecodedIkev2ProfileMissingValues(
ENCODED_INDEX_AUTH_PARAMS_INLINE,
ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS,
- ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE /* missingIndices */);
+ ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE,
+ ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION /* missingIndices */);
assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes()));
}
@@ -194,14 +199,26 @@
public void testEncodeDecodeMissingExcludeLocalRoutes() {
final String tooFewValues =
getEncodedDecodedIkev2ProfileMissingValues(
- ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE /* missingIndices */);
+ ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE,
+ ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION /* missingIndices */);
- // Verify decoding without isRestrictedToTestNetworks defaults to false
+ // Verify decoding without excludeLocalRoutes defaults to false
final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes());
assertFalse(decoded.excludeLocalRoutes);
}
@Test
+ public void testEncodeDecodeMissingRequiresValidation() {
+ final String tooFewValues =
+ getEncodedDecodedIkev2ProfileMissingValues(
+ ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION /* missingIndices */);
+
+ // Verify decoding without requiresValidation defaults to false
+ final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes());
+ assertFalse(decoded.requiresInternetValidation);
+ }
+
+ @Test
public void testEncodeDecodeLoginsNotSaved() {
final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
profile.saveLogin = false;
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 0132525..16b3d5a 100644
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -179,7 +179,6 @@
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
import static java.util.Arrays.asList;
@@ -388,6 +387,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
@@ -907,7 +907,7 @@
return null;
};
- doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any());
+ doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnectedParcel(any());
doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
final ArgumentCaptor<Network> nmNetworkCaptor = ArgumentCaptor.forClass(Network.class);
@@ -1963,6 +1963,25 @@
public BpfNetMaps getBpfNetMaps(INetd netd) {
return mBpfNetMaps;
}
+
+ final ArrayTrackRecord<Pair<String, Long>> mRateLimitHistory = new ArrayTrackRecord<>();
+ final Map<String, Long> mActiveRateLimit = new HashMap<>();
+
+ @Override
+ public void enableIngressRateLimit(final String iface, final long rateInBytesPerSecond) {
+ mRateLimitHistory.add(new Pair<>(iface, rateInBytesPerSecond));
+ // Due to a TC limitation, the rate limit needs to be removed before it can be
+ // updated. Check that this happened.
+ assertEquals(-1L, (long) mActiveRateLimit.getOrDefault(iface, -1L));
+ mActiveRateLimit.put(iface, rateInBytesPerSecond);
+ }
+
+ @Override
+ public void disableIngressRateLimit(final String iface) {
+ mRateLimitHistory.add(new Pair<>(iface, -1L));
+ assertNotEquals(-1L, (long) mActiveRateLimit.getOrDefault(iface, -1L));
+ mActiveRateLimit.put(iface, -1L);
+ }
}
private static void initAlarmManager(final AlarmManager am, final Handler alarmHandler) {
@@ -5027,6 +5046,13 @@
waitForIdle();
}
+ private void setIngressRateLimit(int rateLimitInBytesPerSec) {
+ ConnectivitySettingsManager.setIngressRateLimitInBytesPerSecond(mServiceContext,
+ rateLimitInBytesPerSec);
+ mService.updateIngressRateLimit();
+ waitForIdle();
+ }
+
private boolean isForegroundNetwork(TestNetworkAgentWrapper network) {
NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
assertNotNull(nc);
@@ -15339,4 +15365,153 @@
ConnectivityManager.TYPE_NONE, null /* hostAddress */, "com.not.package.owner",
null /* callingAttributionTag */));
}
+
+ @Test
+ public void testUpdateRateLimit_EnableDisable() throws Exception {
+ final LinkProperties wifiLp = new LinkProperties();
+ wifiLp.setInterfaceName(WIFI_IFNAME);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
+ mWiFiNetworkAgent.connect(true);
+
+ final LinkProperties cellLp = new LinkProperties();
+ cellLp.setInterfaceName(MOBILE_IFNAME);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
+ mCellNetworkAgent.connect(false);
+
+ waitForIdle();
+
+ final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadWifi =
+ mDeps.mRateLimitHistory.newReadHead();
+ final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadCell =
+ mDeps.mRateLimitHistory.newReadHead();
+
+ // set rate limit to 8MBit/s => 1MB/s
+ final int rateLimitInBytesPerSec = 1 * 1000 * 1000;
+ setIngressRateLimit(rateLimitInBytesPerSec);
+
+ assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
+ it -> it.first == wifiLp.getInterfaceName()
+ && it.second == rateLimitInBytesPerSec));
+ assertNotNull(readHeadCell.poll(TIMEOUT_MS,
+ it -> it.first == cellLp.getInterfaceName()
+ && it.second == rateLimitInBytesPerSec));
+
+ // disable rate limiting
+ setIngressRateLimit(-1);
+
+ assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
+ it -> it.first == wifiLp.getInterfaceName() && it.second == -1));
+ assertNotNull(readHeadCell.poll(TIMEOUT_MS,
+ it -> it.first == cellLp.getInterfaceName() && it.second == -1));
+ }
+
+ @Test
+ public void testUpdateRateLimit_WhenNewNetworkIsAdded() throws Exception {
+ final LinkProperties wifiLp = new LinkProperties();
+ wifiLp.setInterfaceName(WIFI_IFNAME);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
+ mWiFiNetworkAgent.connect(true);
+
+ waitForIdle();
+
+ final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHead =
+ mDeps.mRateLimitHistory.newReadHead();
+
+ // set rate limit to 8MBit/s => 1MB/s
+ final int rateLimitInBytesPerSec = 1 * 1000 * 1000;
+ setIngressRateLimit(rateLimitInBytesPerSec);
+ assertNotNull(readHead.poll(TIMEOUT_MS, it -> it.first == wifiLp.getInterfaceName()
+ && it.second == rateLimitInBytesPerSec));
+
+ final LinkProperties cellLp = new LinkProperties();
+ cellLp.setInterfaceName(MOBILE_IFNAME);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
+ mCellNetworkAgent.connect(false);
+ assertNotNull(readHead.poll(TIMEOUT_MS, it -> it.first == cellLp.getInterfaceName()
+ && it.second == rateLimitInBytesPerSec));
+ }
+
+ @Test
+ public void testUpdateRateLimit_OnlyAffectsInternetCapableNetworks() throws Exception {
+ final LinkProperties wifiLp = new LinkProperties();
+ wifiLp.setInterfaceName(WIFI_IFNAME);
+
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
+ mWiFiNetworkAgent.connectWithoutInternet();
+
+ waitForIdle();
+
+ setIngressRateLimit(1000);
+ setIngressRateLimit(-1);
+
+ final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadWifi =
+ mDeps.mRateLimitHistory.newReadHead();
+ assertNull(readHeadWifi.poll(TIMEOUT_MS, it -> it.first == wifiLp.getInterfaceName()));
+ }
+
+ @Test
+ public void testUpdateRateLimit_DisconnectingResetsRateLimit()
+ throws Exception {
+ // Steps:
+ // - connect network
+ // - set rate limit
+ // - disconnect network (interface still exists)
+ // - disable rate limit
+ // - connect network
+ // - ensure network interface is not rate limited
+ final LinkProperties wifiLp = new LinkProperties();
+ wifiLp.setInterfaceName(WIFI_IFNAME);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
+ mWiFiNetworkAgent.connect(true);
+ waitForIdle();
+
+ final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadWifi =
+ mDeps.mRateLimitHistory.newReadHead();
+
+ int rateLimitInBytesPerSec = 1000;
+ setIngressRateLimit(rateLimitInBytesPerSec);
+ assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
+ it -> it.first == wifiLp.getInterfaceName()
+ && it.second == rateLimitInBytesPerSec));
+
+ mWiFiNetworkAgent.disconnect();
+ assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
+ it -> it.first == wifiLp.getInterfaceName() && it.second == -1));
+
+ setIngressRateLimit(-1);
+
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
+ mWiFiNetworkAgent.connect(true);
+ assertNull(readHeadWifi.poll(TIMEOUT_MS, it -> it.first == wifiLp.getInterfaceName()));
+ }
+
+ @Test
+ public void testUpdateRateLimit_UpdateExistingRateLimit() throws Exception {
+ final LinkProperties wifiLp = new LinkProperties();
+ wifiLp.setInterfaceName(WIFI_IFNAME);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
+ mWiFiNetworkAgent.connect(true);
+ waitForIdle();
+
+ final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadWifi =
+ mDeps.mRateLimitHistory.newReadHead();
+
+ // update an active ingress rate limit
+ setIngressRateLimit(1000);
+ setIngressRateLimit(2000);
+
+ // verify the following order of execution:
+ // 1. ingress rate limit set to 1000.
+ // 2. ingress rate limit disabled (triggered by updating active rate limit).
+ // 3. ingress rate limit set to 2000.
+ assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
+ it -> it.first == wifiLp.getInterfaceName()
+ && it.second == 1000));
+ assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
+ it -> it.first == wifiLp.getInterfaceName()
+ && it.second == -1));
+ assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
+ it -> it.first == wifiLp.getInterfaceName()
+ && it.second == 2000));
+ }
}
diff --git a/tests/unit/java/com/android/server/NetworkManagementServiceTest.java b/tests/unit/java/com/android/server/NetworkManagementServiceTest.java
index 0c58582..a3b0e7c 100644
--- a/tests/unit/java/com/android/server/NetworkManagementServiceTest.java
+++ b/tests/unit/java/com/android/server/NetworkManagementServiceTest.java
@@ -16,6 +16,11 @@
package com.android.server;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY;
import static android.util.DebugUtils.valueToString;
import static org.junit.Assert.assertEquals;
@@ -277,31 +282,38 @@
isRestrictedForDozable.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, true);
isRestrictedForDozable.put(INetd.FIREWALL_RULE_ALLOW, false);
isRestrictedForDozable.put(INetd.FIREWALL_RULE_DENY, true);
- expected.put(INetd.FIREWALL_CHAIN_DOZABLE, isRestrictedForDozable);
+ expected.put(FIREWALL_CHAIN_DOZABLE, isRestrictedForDozable);
// Powersaver chain
final ArrayMap<Integer, Boolean> isRestrictedForPowerSave = new ArrayMap<>();
isRestrictedForPowerSave.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, true);
isRestrictedForPowerSave.put(INetd.FIREWALL_RULE_ALLOW, false);
isRestrictedForPowerSave.put(INetd.FIREWALL_RULE_DENY, true);
- expected.put(INetd.FIREWALL_CHAIN_POWERSAVE, isRestrictedForPowerSave);
+ expected.put(FIREWALL_CHAIN_POWERSAVE, isRestrictedForPowerSave);
// Standby chain
final ArrayMap<Integer, Boolean> isRestrictedForStandby = new ArrayMap<>();
isRestrictedForStandby.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, false);
isRestrictedForStandby.put(INetd.FIREWALL_RULE_ALLOW, false);
isRestrictedForStandby.put(INetd.FIREWALL_RULE_DENY, true);
- expected.put(INetd.FIREWALL_CHAIN_STANDBY, isRestrictedForStandby);
+ expected.put(FIREWALL_CHAIN_STANDBY, isRestrictedForStandby);
// Restricted mode chain
final ArrayMap<Integer, Boolean> isRestrictedForRestrictedMode = new ArrayMap<>();
isRestrictedForRestrictedMode.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, true);
isRestrictedForRestrictedMode.put(INetd.FIREWALL_RULE_ALLOW, false);
isRestrictedForRestrictedMode.put(INetd.FIREWALL_RULE_DENY, true);
- expected.put(INetd.FIREWALL_CHAIN_RESTRICTED, isRestrictedForRestrictedMode);
+ expected.put(FIREWALL_CHAIN_RESTRICTED, isRestrictedForRestrictedMode);
+ // Low Power Standby chain
+ final ArrayMap<Integer, Boolean> isRestrictedForLowPowerStandby = new ArrayMap<>();
+ isRestrictedForLowPowerStandby.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, true);
+ isRestrictedForLowPowerStandby.put(INetd.FIREWALL_RULE_ALLOW, false);
+ isRestrictedForLowPowerStandby.put(INetd.FIREWALL_RULE_DENY, true);
+ expected.put(FIREWALL_CHAIN_LOW_POWER_STANDBY, isRestrictedForLowPowerStandby);
final int[] chains = {
- INetd.FIREWALL_CHAIN_STANDBY,
- INetd.FIREWALL_CHAIN_POWERSAVE,
- INetd.FIREWALL_CHAIN_DOZABLE,
- INetd.FIREWALL_CHAIN_RESTRICTED
+ FIREWALL_CHAIN_STANDBY,
+ FIREWALL_CHAIN_POWERSAVE,
+ FIREWALL_CHAIN_DOZABLE,
+ FIREWALL_CHAIN_RESTRICTED,
+ FIREWALL_CHAIN_LOW_POWER_STANDBY
};
final int[] states = {
INetd.FIREWALL_RULE_ALLOW,
diff --git a/tests/unit/jni/Android.bp b/tests/unit/jni/Android.bp
index 04ba98f..616da81 100644
--- a/tests/unit/jni/Android.bp
+++ b/tests/unit/jni/Android.bp
@@ -21,7 +21,6 @@
],
shared_libs: [
- "libbpf_android",
"liblog",
"libnativehelper",
"libnetdutils",