Merge "Fix the comments from aosp/1719018" into sc-dev
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index ebc1264..83619d6 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -2,3 +2,5 @@
checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT}
ktlint_hook = ${REPO_ROOT}/prebuilts/ktlint/ktlint.py -f ${PREUPLOAD_FILES}
+
+hidden_api_txt_checksorted_hook = ${REPO_ROOT}/tools/platform-compat/hiddenapi/checksorted_sha.sh ${PREUPLOAD_COMMIT} ${REPO_ROOT}
diff --git a/TEST_MAPPING b/TEST_MAPPING
index d7d4bcb..030a4c7 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -27,8 +27,7 @@
// Tests on physical devices with SIM cards: postsubmit only for capacity constraints
"mainline-postsubmit": [
{
- // TODO: add back the tethering module when updatable in this branch
- "name": "CtsNetTestCasesLatestSdk[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex]",
+ "name": "CtsNetTestCasesLatestSdk[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex+com.google.android.tethering.apex]",
"keywords": ["sim"]
}
],
diff --git a/Tethering/apex/Android.bp b/Tethering/apex/Android.bp
index 2a9e31a..f86a79d 100644
--- a/Tethering/apex/Android.bp
+++ b/Tethering/apex/Android.bp
@@ -31,11 +31,11 @@
],
multilib: {
first: {
- jni_libs: ["libservice-connectivity"]
+ jni_libs: ["libservice-connectivity"],
},
both: {
jni_libs: ["libframework-connectivity-jni"],
- }
+ },
},
bpfs: [
"offload.o",
@@ -74,6 +74,27 @@
"framework-tethering",
],
apex_available: ["com.android.tethering"],
+
+ // The bootclasspath_fragments that provide APIs on which this depends.
+ fragments: [
+ {
+ apex: "com.android.art",
+ module: "art-bootclasspath-fragment",
+ },
+ ],
+
+ // Additional stubs libraries that this fragment's contents use which are
+ // not provided by another bootclasspath_fragment.
+ additional_stubs: [
+ "android-non-updatable",
+ ],
+
+ // Additional hidden API flag files to override the defaults. This must only be
+ // modified by the Soong or platform compat team.
+ hidden_api: {
+ max_target_o_low_priority: ["hiddenapi/hiddenapi-max-target-o-low-priority.txt"],
+ unsupported: ["hiddenapi/hiddenapi-unsupported.txt"],
+ },
}
override_apex {
diff --git a/Tethering/apex/hiddenapi/OWNERS b/Tethering/apex/hiddenapi/OWNERS
new file mode 100644
index 0000000..82b599d
--- /dev/null
+++ b/Tethering/apex/hiddenapi/OWNERS
@@ -0,0 +1,9 @@
+# These files are only intended to be changed by platform-compat and
+# the soong teams.
+set noparent
+
+# soong-team@ as the hiddenapi files are tightly coupled with Soong
+file:platform/build/soong:/OWNERS
+
+# compat-team@ for changes to hiddenapi files
+file:tools/platform-compat:/OWNERS
diff --git a/Tethering/apex/hiddenapi/hiddenapi-max-target-o-low-priority.txt b/Tethering/apex/hiddenapi/hiddenapi-max-target-o-low-priority.txt
new file mode 100644
index 0000000..1f49d1b
--- /dev/null
+++ b/Tethering/apex/hiddenapi/hiddenapi-max-target-o-low-priority.txt
@@ -0,0 +1,1216 @@
+Landroid/net/CaptivePortal;-><init>(Landroid/os/IBinder;)V
+Landroid/net/CaptivePortal;->APP_RETURN_DISMISSED:I
+Landroid/net/CaptivePortal;->APP_RETURN_UNWANTED:I
+Landroid/net/CaptivePortal;->APP_RETURN_WANTED_AS_IS:I
+Landroid/net/CaptivePortal;->mBinder:Landroid/os/IBinder;
+Landroid/net/CaptivePortal;->useNetwork()V
+Landroid/net/ConnectivityManager$CallbackHandler;->DBG:Z
+Landroid/net/ConnectivityManager$CallbackHandler;->getObject(Landroid/os/Message;Ljava/lang/Class;)Ljava/lang/Object;
+Landroid/net/ConnectivityManager$CallbackHandler;->TAG:Ljava/lang/String;
+Landroid/net/ConnectivityManager$Errors;->TOO_MANY_REQUESTS:I
+Landroid/net/ConnectivityManager$LegacyRequest;-><init>()V
+Landroid/net/ConnectivityManager$LegacyRequest;->clearDnsBinding()V
+Landroid/net/ConnectivityManager$LegacyRequest;->currentNetwork:Landroid/net/Network;
+Landroid/net/ConnectivityManager$LegacyRequest;->delay:I
+Landroid/net/ConnectivityManager$LegacyRequest;->expireSequenceNumber:I
+Landroid/net/ConnectivityManager$LegacyRequest;->networkCallback:Landroid/net/ConnectivityManager$NetworkCallback;
+Landroid/net/ConnectivityManager$LegacyRequest;->networkCapabilities:Landroid/net/NetworkCapabilities;
+Landroid/net/ConnectivityManager$LegacyRequest;->networkRequest:Landroid/net/NetworkRequest;
+Landroid/net/ConnectivityManager$NetworkCallback;->networkRequest:Landroid/net/NetworkRequest;
+Landroid/net/ConnectivityManager$NetworkCallback;->onAvailable(Landroid/net/Network;Landroid/net/NetworkCapabilities;Landroid/net/LinkProperties;)V
+Landroid/net/ConnectivityManager$NetworkCallback;->onNetworkResumed(Landroid/net/Network;)V
+Landroid/net/ConnectivityManager$NetworkCallback;->onNetworkSuspended(Landroid/net/Network;)V
+Landroid/net/ConnectivityManager$NetworkCallback;->onPreCheck(Landroid/net/Network;)V
+Landroid/net/ConnectivityManager$PacketKeepalive;->BINDER_DIED:I
+Landroid/net/ConnectivityManager$PacketKeepalive;->ERROR_HARDWARE_ERROR:I
+Landroid/net/ConnectivityManager$PacketKeepalive;->ERROR_HARDWARE_UNSUPPORTED:I
+Landroid/net/ConnectivityManager$PacketKeepalive;->ERROR_INVALID_INTERVAL:I
+Landroid/net/ConnectivityManager$PacketKeepalive;->ERROR_INVALID_IP_ADDRESS:I
+Landroid/net/ConnectivityManager$PacketKeepalive;->ERROR_INVALID_LENGTH:I
+Landroid/net/ConnectivityManager$PacketKeepalive;->ERROR_INVALID_NETWORK:I
+Landroid/net/ConnectivityManager$PacketKeepalive;->ERROR_INVALID_PORT:I
+Landroid/net/ConnectivityManager$PacketKeepalive;->mCallback:Landroid/net/ConnectivityManager$PacketKeepaliveCallback;
+Landroid/net/ConnectivityManager$PacketKeepalive;->MIN_INTERVAL:I
+Landroid/net/ConnectivityManager$PacketKeepalive;->mLooper:Landroid/os/Looper;
+Landroid/net/ConnectivityManager$PacketKeepalive;->mMessenger:Landroid/os/Messenger;
+Landroid/net/ConnectivityManager$PacketKeepalive;->mNetwork:Landroid/net/Network;
+Landroid/net/ConnectivityManager$PacketKeepalive;->mSlot:Ljava/lang/Integer;
+Landroid/net/ConnectivityManager$PacketKeepalive;->NATT_PORT:I
+Landroid/net/ConnectivityManager$PacketKeepalive;->NO_KEEPALIVE:I
+Landroid/net/ConnectivityManager$PacketKeepalive;->stopLooper()V
+Landroid/net/ConnectivityManager$PacketKeepalive;->SUCCESS:I
+Landroid/net/ConnectivityManager$PacketKeepalive;->TAG:Ljava/lang/String;
+Landroid/net/ConnectivityManager$TooManyRequestsException;-><init>()V
+Landroid/net/ConnectivityManager;-><init>(Landroid/content/Context;Landroid/net/IConnectivityManager;)V
+Landroid/net/ConnectivityManager;->ACTION_CAPTIVE_PORTAL_TEST_COMPLETED:Ljava/lang/String;
+Landroid/net/ConnectivityManager;->ACTION_DATA_ACTIVITY_CHANGE:Ljava/lang/String;
+Landroid/net/ConnectivityManager;->ACTION_PROMPT_LOST_VALIDATION:Ljava/lang/String;
+Landroid/net/ConnectivityManager;->ACTION_PROMPT_UNVALIDATED:Ljava/lang/String;
+Landroid/net/ConnectivityManager;->ALREADY_UNREGISTERED:Landroid/net/NetworkRequest;
+Landroid/net/ConnectivityManager;->BASE:I
+Landroid/net/ConnectivityManager;->CALLBACK_AVAILABLE:I
+Landroid/net/ConnectivityManager;->CALLBACK_CAP_CHANGED:I
+Landroid/net/ConnectivityManager;->CALLBACK_IP_CHANGED:I
+Landroid/net/ConnectivityManager;->CALLBACK_LOSING:I
+Landroid/net/ConnectivityManager;->CALLBACK_LOST:I
+Landroid/net/ConnectivityManager;->CALLBACK_PRECHECK:I
+Landroid/net/ConnectivityManager;->CALLBACK_RESUMED:I
+Landroid/net/ConnectivityManager;->CALLBACK_SUSPENDED:I
+Landroid/net/ConnectivityManager;->CALLBACK_UNAVAIL:I
+Landroid/net/ConnectivityManager;->checkCallbackNotNull(Landroid/net/ConnectivityManager$NetworkCallback;)V
+Landroid/net/ConnectivityManager;->checkLegacyRoutingApiAccess()V
+Landroid/net/ConnectivityManager;->checkMobileProvisioning(I)I
+Landroid/net/ConnectivityManager;->checkPendingIntentNotNull(Landroid/app/PendingIntent;)V
+Landroid/net/ConnectivityManager;->checkTimeout(I)V
+Landroid/net/ConnectivityManager;->CONNECTIVITY_ACTION_SUPL:Ljava/lang/String;
+Landroid/net/ConnectivityManager;->convertServiceException(Landroid/os/ServiceSpecificException;)Ljava/lang/RuntimeException;
+Landroid/net/ConnectivityManager;->enforceChangePermission(Landroid/content/Context;)V
+Landroid/net/ConnectivityManager;->enforceTetherChangePermission(Landroid/content/Context;Ljava/lang/String;)V
+Landroid/net/ConnectivityManager;->expireRequest(Landroid/net/NetworkCapabilities;I)V
+Landroid/net/ConnectivityManager;->EXPIRE_LEGACY_REQUEST:I
+Landroid/net/ConnectivityManager;->EXTRA_ACTIVE_LOCAL_ONLY:Ljava/lang/String;
+Landroid/net/ConnectivityManager;->EXTRA_ADD_TETHER_TYPE:Ljava/lang/String;
+Landroid/net/ConnectivityManager;->EXTRA_CAPTIVE_PORTAL_PROBE_SPEC:Ljava/lang/String;
+Landroid/net/ConnectivityManager;->EXTRA_CAPTIVE_PORTAL_USER_AGENT:Ljava/lang/String;
+Landroid/net/ConnectivityManager;->EXTRA_DEVICE_TYPE:Ljava/lang/String;
+Landroid/net/ConnectivityManager;->EXTRA_INET_CONDITION:Ljava/lang/String;
+Landroid/net/ConnectivityManager;->EXTRA_IS_ACTIVE:Ljava/lang/String;
+Landroid/net/ConnectivityManager;->EXTRA_IS_CAPTIVE_PORTAL:Ljava/lang/String;
+Landroid/net/ConnectivityManager;->EXTRA_PROVISION_CALLBACK:Ljava/lang/String;
+Landroid/net/ConnectivityManager;->EXTRA_REALTIME_NS:Ljava/lang/String;
+Landroid/net/ConnectivityManager;->EXTRA_REM_TETHER_TYPE:Ljava/lang/String;
+Landroid/net/ConnectivityManager;->EXTRA_RUN_PROVISION:Ljava/lang/String;
+Landroid/net/ConnectivityManager;->EXTRA_SET_ALARM:Ljava/lang/String;
+Landroid/net/ConnectivityManager;->factoryReset()V
+Landroid/net/ConnectivityManager;->findRequestForFeature(Landroid/net/NetworkCapabilities;)Landroid/net/NetworkRequest;
+Landroid/net/ConnectivityManager;->getActiveNetworkForUid(I)Landroid/net/Network;
+Landroid/net/ConnectivityManager;->getActiveNetworkForUid(IZ)Landroid/net/Network;
+Landroid/net/ConnectivityManager;->getActiveNetworkInfoForUid(IZ)Landroid/net/NetworkInfo;
+Landroid/net/ConnectivityManager;->getAlwaysOnVpnPackageForUser(I)Ljava/lang/String;
+Landroid/net/ConnectivityManager;->getCallbackName(I)Ljava/lang/String;
+Landroid/net/ConnectivityManager;->getDefaultHandler()Landroid/net/ConnectivityManager$CallbackHandler;
+Landroid/net/ConnectivityManager;->getGlobalProxy()Landroid/net/ProxyInfo;
+Landroid/net/ConnectivityManager;->getInstanceOrNull()Landroid/net/ConnectivityManager;
+Landroid/net/ConnectivityManager;->getMobileProvisioningUrl()Ljava/lang/String;
+Landroid/net/ConnectivityManager;->getNetworkInfoForUid(Landroid/net/Network;IZ)Landroid/net/NetworkInfo;
+Landroid/net/ConnectivityManager;->getNetworkManagementService()Landroid/os/INetworkManagementService;
+Landroid/net/ConnectivityManager;->getNetworkPolicyManager()Landroid/net/INetworkPolicyManager;
+Landroid/net/ConnectivityManager;->getProxyForNetwork(Landroid/net/Network;)Landroid/net/ProxyInfo;
+Landroid/net/ConnectivityManager;->getTetheredDhcpRanges()[Ljava/lang/String;
+Landroid/net/ConnectivityManager;->inferLegacyTypeForNetworkCapabilities(Landroid/net/NetworkCapabilities;)I
+Landroid/net/ConnectivityManager;->isAlwaysOnVpnPackageSupportedForUser(ILjava/lang/String;)Z
+Landroid/net/ConnectivityManager;->isNetworkTypeWifi(I)Z
+Landroid/net/ConnectivityManager;->legacyTypeForNetworkCapabilities(Landroid/net/NetworkCapabilities;)I
+Landroid/net/ConnectivityManager;->LISTEN:I
+Landroid/net/ConnectivityManager;->MAX_NETWORK_TYPE:I
+Landroid/net/ConnectivityManager;->MAX_RADIO_TYPE:I
+Landroid/net/ConnectivityManager;->mContext:Landroid/content/Context;
+Landroid/net/ConnectivityManager;->MIN_NETWORK_TYPE:I
+Landroid/net/ConnectivityManager;->mNetworkActivityListeners:Landroid/util/ArrayMap;
+Landroid/net/ConnectivityManager;->mNMService:Landroid/os/INetworkManagementService;
+Landroid/net/ConnectivityManager;->mNPManager:Landroid/net/INetworkPolicyManager;
+Landroid/net/ConnectivityManager;->MULTIPATH_PREFERENCE_UNMETERED:I
+Landroid/net/ConnectivityManager;->NETID_UNSET:I
+Landroid/net/ConnectivityManager;->networkCapabilitiesForType(I)Landroid/net/NetworkCapabilities;
+Landroid/net/ConnectivityManager;->PRIVATE_DNS_DEFAULT_MODE_FALLBACK:Ljava/lang/String;
+Landroid/net/ConnectivityManager;->PRIVATE_DNS_MODE_OFF:Ljava/lang/String;
+Landroid/net/ConnectivityManager;->PRIVATE_DNS_MODE_OPPORTUNISTIC:Ljava/lang/String;
+Landroid/net/ConnectivityManager;->PRIVATE_DNS_MODE_PROVIDER_HOSTNAME:Ljava/lang/String;
+Landroid/net/ConnectivityManager;->registerNetworkAgent(Landroid/os/Messenger;Landroid/net/NetworkInfo;Landroid/net/LinkProperties;Landroid/net/NetworkCapabilities;ILandroid/net/NetworkMisc;)I
+Landroid/net/ConnectivityManager;->renewRequestLocked(Landroid/net/ConnectivityManager$LegacyRequest;)V
+Landroid/net/ConnectivityManager;->reportInetCondition(II)V
+Landroid/net/ConnectivityManager;->REQUEST:I
+Landroid/net/ConnectivityManager;->requestNetwork(Landroid/net/NetworkRequest;Landroid/net/ConnectivityManager$NetworkCallback;IILandroid/os/Handler;)V
+Landroid/net/ConnectivityManager;->REQUEST_ID_UNSET:I
+Landroid/net/ConnectivityManager;->sCallbackHandler:Landroid/net/ConnectivityManager$CallbackHandler;
+Landroid/net/ConnectivityManager;->sCallbacks:Ljava/util/HashMap;
+Landroid/net/ConnectivityManager;->sendExpireMsgForFeature(Landroid/net/NetworkCapabilities;II)V
+Landroid/net/ConnectivityManager;->sendRequestForNetwork(Landroid/net/NetworkCapabilities;Landroid/net/ConnectivityManager$NetworkCallback;IIILandroid/net/ConnectivityManager$CallbackHandler;)Landroid/net/NetworkRequest;
+Landroid/net/ConnectivityManager;->setAcceptUnvalidated(Landroid/net/Network;ZZ)V
+Landroid/net/ConnectivityManager;->setAlwaysOnVpnPackageForUser(ILjava/lang/String;Z)Z
+Landroid/net/ConnectivityManager;->setAvoidUnvalidated(Landroid/net/Network;)V
+Landroid/net/ConnectivityManager;->setGlobalProxy(Landroid/net/ProxyInfo;)V
+Landroid/net/ConnectivityManager;->setProvisioningNotificationVisible(ZILjava/lang/String;)V
+Landroid/net/ConnectivityManager;->sInstance:Landroid/net/ConnectivityManager;
+Landroid/net/ConnectivityManager;->sLegacyTypeToCapability:Landroid/util/SparseIntArray;
+Landroid/net/ConnectivityManager;->sLegacyTypeToTransport:Landroid/util/SparseIntArray;
+Landroid/net/ConnectivityManager;->startCaptivePortalApp(Landroid/net/Network;)V
+Landroid/net/ConnectivityManager;->TAG:Ljava/lang/String;
+Landroid/net/ConnectivityManager;->TETHERING_INVALID:I
+Landroid/net/ConnectivityManager;->TETHER_ERROR_DISABLE_NAT_ERROR:I
+Landroid/net/ConnectivityManager;->TETHER_ERROR_ENABLE_NAT_ERROR:I
+Landroid/net/ConnectivityManager;->TETHER_ERROR_IFACE_CFG_ERROR:I
+Landroid/net/ConnectivityManager;->TETHER_ERROR_MASTER_ERROR:I
+Landroid/net/ConnectivityManager;->TETHER_ERROR_NO_ERROR:I
+Landroid/net/ConnectivityManager;->TETHER_ERROR_PROVISION_FAILED:I
+Landroid/net/ConnectivityManager;->TETHER_ERROR_SERVICE_UNAVAIL:I
+Landroid/net/ConnectivityManager;->TETHER_ERROR_TETHER_IFACE_ERROR:I
+Landroid/net/ConnectivityManager;->TETHER_ERROR_UNAVAIL_IFACE:I
+Landroid/net/ConnectivityManager;->TETHER_ERROR_UNKNOWN_IFACE:I
+Landroid/net/ConnectivityManager;->TETHER_ERROR_UNSUPPORTED:I
+Landroid/net/ConnectivityManager;->TETHER_ERROR_UNTETHER_IFACE_ERROR:I
+Landroid/net/ConnectivityManager;->unsupportedStartingFrom(I)V
+Landroid/net/ConnectivityManager;->updateLockdownVpn()Z
+Landroid/net/ConnectivityThread$Singleton;-><init>()V
+Landroid/net/ConnectivityThread$Singleton;->INSTANCE:Landroid/net/ConnectivityThread;
+Landroid/net/ConnectivityThread;-><init>()V
+Landroid/net/ConnectivityThread;->createInstance()Landroid/net/ConnectivityThread;
+Landroid/net/ConnectivityThread;->get()Landroid/net/ConnectivityThread;
+Landroid/net/ConnectivityThread;->getInstanceLooper()Landroid/os/Looper;
+Landroid/net/DhcpInfo;-><init>(Landroid/net/DhcpInfo;)V
+Landroid/net/DhcpInfo;->CREATOR:Landroid/os/Parcelable$Creator;
+Landroid/net/DhcpInfo;->putAddress(Ljava/lang/StringBuffer;I)V
+Landroid/net/ICaptivePortal$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Landroid/net/ICaptivePortal$Stub$Proxy;->appResponse(I)V
+Landroid/net/ICaptivePortal$Stub$Proxy;->getInterfaceDescriptor()Ljava/lang/String;
+Landroid/net/ICaptivePortal$Stub$Proxy;->mRemote:Landroid/os/IBinder;
+Landroid/net/ICaptivePortal$Stub;-><init>()V
+Landroid/net/ICaptivePortal$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/ICaptivePortal;
+Landroid/net/ICaptivePortal$Stub;->DESCRIPTOR:Ljava/lang/String;
+Landroid/net/ICaptivePortal$Stub;->TRANSACTION_appResponse:I
+Landroid/net/ICaptivePortal;->appResponse(I)V
+Landroid/net/IConnectivityManager$Stub$Proxy;->addVpnAddress(Ljava/lang/String;I)Z
+Landroid/net/IConnectivityManager$Stub$Proxy;->checkMobileProvisioning(I)I
+Landroid/net/IConnectivityManager$Stub$Proxy;->establishVpn(Lcom/android/internal/net/VpnConfig;)Landroid/os/ParcelFileDescriptor;
+Landroid/net/IConnectivityManager$Stub$Proxy;->factoryReset()V
+Landroid/net/IConnectivityManager$Stub$Proxy;->getActiveNetwork()Landroid/net/Network;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getActiveNetworkForUid(IZ)Landroid/net/Network;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getActiveNetworkInfoForUid(IZ)Landroid/net/NetworkInfo;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getActiveNetworkQuotaInfo()Landroid/net/NetworkQuotaInfo;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getAllNetworkState()[Landroid/net/NetworkState;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getAllVpnInfo()[Lcom/android/internal/net/VpnInfo;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getAlwaysOnVpnPackage(I)Ljava/lang/String;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getCaptivePortalServerUrl()Ljava/lang/String;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getDefaultNetworkCapabilitiesForUser(I)[Landroid/net/NetworkCapabilities;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getGlobalProxy()Landroid/net/ProxyInfo;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getInterfaceDescriptor()Ljava/lang/String;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getLastTetherError(Ljava/lang/String;)I
+Landroid/net/IConnectivityManager$Stub$Proxy;->getLegacyVpnInfo(I)Lcom/android/internal/net/LegacyVpnInfo;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getLinkProperties(Landroid/net/Network;)Landroid/net/LinkProperties;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getLinkPropertiesForType(I)Landroid/net/LinkProperties;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getMobileProvisioningUrl()Ljava/lang/String;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getMultipathPreference(Landroid/net/Network;)I
+Landroid/net/IConnectivityManager$Stub$Proxy;->getNetworkCapabilities(Landroid/net/Network;)Landroid/net/NetworkCapabilities;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getNetworkForType(I)Landroid/net/Network;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getNetworkInfo(I)Landroid/net/NetworkInfo;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getNetworkInfoForUid(Landroid/net/Network;IZ)Landroid/net/NetworkInfo;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getNetworkWatchlistConfigHash()[B
+Landroid/net/IConnectivityManager$Stub$Proxy;->getProxyForNetwork(Landroid/net/Network;)Landroid/net/ProxyInfo;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getRestoreDefaultNetworkDelay(I)I
+Landroid/net/IConnectivityManager$Stub$Proxy;->getTetherableBluetoothRegexs()[Ljava/lang/String;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getTetherableWifiRegexs()[Ljava/lang/String;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getTetheredDhcpRanges()[Ljava/lang/String;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getTetheringErroredIfaces()[Ljava/lang/String;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getVpnConfig(I)Lcom/android/internal/net/VpnConfig;
+Landroid/net/IConnectivityManager$Stub$Proxy;->isActiveNetworkMetered()Z
+Landroid/net/IConnectivityManager$Stub$Proxy;->isAlwaysOnVpnPackageSupported(ILjava/lang/String;)Z
+Landroid/net/IConnectivityManager$Stub$Proxy;->isNetworkSupported(I)Z
+Landroid/net/IConnectivityManager$Stub$Proxy;->isTetheringSupported(Ljava/lang/String;)Z
+Landroid/net/IConnectivityManager$Stub$Proxy;->listenForNetwork(Landroid/net/NetworkCapabilities;Landroid/os/Messenger;Landroid/os/IBinder;)Landroid/net/NetworkRequest;
+Landroid/net/IConnectivityManager$Stub$Proxy;->pendingListenForNetwork(Landroid/net/NetworkCapabilities;Landroid/app/PendingIntent;)V
+Landroid/net/IConnectivityManager$Stub$Proxy;->pendingRequestForNetwork(Landroid/net/NetworkCapabilities;Landroid/app/PendingIntent;)Landroid/net/NetworkRequest;
+Landroid/net/IConnectivityManager$Stub$Proxy;->prepareVpn(Ljava/lang/String;Ljava/lang/String;I)Z
+Landroid/net/IConnectivityManager$Stub$Proxy;->registerNetworkAgent(Landroid/os/Messenger;Landroid/net/NetworkInfo;Landroid/net/LinkProperties;Landroid/net/NetworkCapabilities;ILandroid/net/NetworkMisc;)I
+Landroid/net/IConnectivityManager$Stub$Proxy;->registerNetworkFactory(Landroid/os/Messenger;Ljava/lang/String;)V
+Landroid/net/IConnectivityManager$Stub$Proxy;->releaseNetworkRequest(Landroid/net/NetworkRequest;)V
+Landroid/net/IConnectivityManager$Stub$Proxy;->releasePendingNetworkRequest(Landroid/app/PendingIntent;)V
+Landroid/net/IConnectivityManager$Stub$Proxy;->removeVpnAddress(Ljava/lang/String;I)Z
+Landroid/net/IConnectivityManager$Stub$Proxy;->reportInetCondition(II)V
+Landroid/net/IConnectivityManager$Stub$Proxy;->reportNetworkConnectivity(Landroid/net/Network;Z)V
+Landroid/net/IConnectivityManager$Stub$Proxy;->requestBandwidthUpdate(Landroid/net/Network;)Z
+Landroid/net/IConnectivityManager$Stub$Proxy;->requestNetwork(Landroid/net/NetworkCapabilities;Landroid/os/Messenger;ILandroid/os/IBinder;I)Landroid/net/NetworkRequest;
+Landroid/net/IConnectivityManager$Stub$Proxy;->requestRouteToHostAddress(I[B)Z
+Landroid/net/IConnectivityManager$Stub$Proxy;->setAcceptUnvalidated(Landroid/net/Network;ZZ)V
+Landroid/net/IConnectivityManager$Stub$Proxy;->setAirplaneMode(Z)V
+Landroid/net/IConnectivityManager$Stub$Proxy;->setAlwaysOnVpnPackage(ILjava/lang/String;Z)Z
+Landroid/net/IConnectivityManager$Stub$Proxy;->setAvoidUnvalidated(Landroid/net/Network;)V
+Landroid/net/IConnectivityManager$Stub$Proxy;->setGlobalProxy(Landroid/net/ProxyInfo;)V
+Landroid/net/IConnectivityManager$Stub$Proxy;->setProvisioningNotificationVisible(ZILjava/lang/String;)V
+Landroid/net/IConnectivityManager$Stub$Proxy;->setUnderlyingNetworksForVpn([Landroid/net/Network;)Z
+Landroid/net/IConnectivityManager$Stub$Proxy;->setUsbTethering(ZLjava/lang/String;)I
+Landroid/net/IConnectivityManager$Stub$Proxy;->setVpnPackageAuthorization(Ljava/lang/String;IZ)V
+Landroid/net/IConnectivityManager$Stub$Proxy;->startCaptivePortalApp(Landroid/net/Network;)V
+Landroid/net/IConnectivityManager$Stub$Proxy;->startLegacyVpn(Lcom/android/internal/net/VpnProfile;)V
+Landroid/net/IConnectivityManager$Stub$Proxy;->startNattKeepalive(Landroid/net/Network;ILandroid/os/Messenger;Landroid/os/IBinder;Ljava/lang/String;ILjava/lang/String;)V
+Landroid/net/IConnectivityManager$Stub$Proxy;->startTethering(ILandroid/os/ResultReceiver;ZLjava/lang/String;)V
+Landroid/net/IConnectivityManager$Stub$Proxy;->stopKeepalive(Landroid/net/Network;I)V
+Landroid/net/IConnectivityManager$Stub$Proxy;->stopTethering(ILjava/lang/String;)V
+Landroid/net/IConnectivityManager$Stub$Proxy;->tether(Ljava/lang/String;Ljava/lang/String;)I
+Landroid/net/IConnectivityManager$Stub$Proxy;->unregisterNetworkFactory(Landroid/os/Messenger;)V
+Landroid/net/IConnectivityManager$Stub$Proxy;->untether(Ljava/lang/String;Ljava/lang/String;)I
+Landroid/net/IConnectivityManager$Stub$Proxy;->updateLockdownVpn()Z
+Landroid/net/IConnectivityManager$Stub;->DESCRIPTOR:Ljava/lang/String;
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_addVpnAddress:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_checkMobileProvisioning:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_establishVpn:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_factoryReset:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getActiveLinkProperties:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getActiveNetwork:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getActiveNetworkForUid:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getActiveNetworkInfo:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getActiveNetworkInfoForUid:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getActiveNetworkQuotaInfo:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getAllNetworkInfo:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getAllNetworks:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getAllNetworkState:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getAllVpnInfo:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getAlwaysOnVpnPackage:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getCaptivePortalServerUrl:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getDefaultNetworkCapabilitiesForUser:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getGlobalProxy:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getLastTetherError:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getLegacyVpnInfo:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getLinkProperties:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getLinkPropertiesForType:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getMobileProvisioningUrl:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getMultipathPreference:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getNetworkCapabilities:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getNetworkForType:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getNetworkInfo:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getNetworkInfoForUid:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getNetworkWatchlistConfigHash:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getProxyForNetwork:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getRestoreDefaultNetworkDelay:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getTetherableBluetoothRegexs:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getTetherableIfaces:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getTetherableUsbRegexs:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getTetherableWifiRegexs:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getTetheredDhcpRanges:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getTetheredIfaces:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getTetheringErroredIfaces:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_getVpnConfig:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_isActiveNetworkMetered:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_isAlwaysOnVpnPackageSupported:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_isNetworkSupported:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_isTetheringSupported:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_listenForNetwork:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_pendingListenForNetwork:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_pendingRequestForNetwork:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_prepareVpn:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_registerNetworkAgent:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_registerNetworkFactory:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_releaseNetworkRequest:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_releasePendingNetworkRequest:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_removeVpnAddress:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_reportInetCondition:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_reportNetworkConnectivity:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_requestBandwidthUpdate:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_requestNetwork:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_requestRouteToHostAddress:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_setAcceptUnvalidated:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_setAirplaneMode:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_setAlwaysOnVpnPackage:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_setAvoidUnvalidated:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_setGlobalProxy:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_setProvisioningNotificationVisible:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_setUnderlyingNetworksForVpn:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_setUsbTethering:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_setVpnPackageAuthorization:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_startCaptivePortalApp:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_startLegacyVpn:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_startNattKeepalive:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_startTethering:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_stopKeepalive:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_stopTethering:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_tether:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_unregisterNetworkFactory:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_untether:I
+Landroid/net/IConnectivityManager$Stub;->TRANSACTION_updateLockdownVpn:I
+Landroid/net/IConnectivityManager;->addVpnAddress(Ljava/lang/String;I)Z
+Landroid/net/IConnectivityManager;->checkMobileProvisioning(I)I
+Landroid/net/IConnectivityManager;->establishVpn(Lcom/android/internal/net/VpnConfig;)Landroid/os/ParcelFileDescriptor;
+Landroid/net/IConnectivityManager;->factoryReset()V
+Landroid/net/IConnectivityManager;->getActiveNetwork()Landroid/net/Network;
+Landroid/net/IConnectivityManager;->getActiveNetworkForUid(IZ)Landroid/net/Network;
+Landroid/net/IConnectivityManager;->getActiveNetworkInfoForUid(IZ)Landroid/net/NetworkInfo;
+Landroid/net/IConnectivityManager;->getActiveNetworkQuotaInfo()Landroid/net/NetworkQuotaInfo;
+Landroid/net/IConnectivityManager;->getAllNetworks()[Landroid/net/Network;
+Landroid/net/IConnectivityManager;->getAllVpnInfo()[Lcom/android/internal/net/VpnInfo;
+Landroid/net/IConnectivityManager;->getAlwaysOnVpnPackage(I)Ljava/lang/String;
+Landroid/net/IConnectivityManager;->getCaptivePortalServerUrl()Ljava/lang/String;
+Landroid/net/IConnectivityManager;->getDefaultNetworkCapabilitiesForUser(I)[Landroid/net/NetworkCapabilities;
+Landroid/net/IConnectivityManager;->getGlobalProxy()Landroid/net/ProxyInfo;
+Landroid/net/IConnectivityManager;->getLegacyVpnInfo(I)Lcom/android/internal/net/LegacyVpnInfo;
+Landroid/net/IConnectivityManager;->getLinkProperties(Landroid/net/Network;)Landroid/net/LinkProperties;
+Landroid/net/IConnectivityManager;->getLinkPropertiesForType(I)Landroid/net/LinkProperties;
+Landroid/net/IConnectivityManager;->getMobileProvisioningUrl()Ljava/lang/String;
+Landroid/net/IConnectivityManager;->getMultipathPreference(Landroid/net/Network;)I
+Landroid/net/IConnectivityManager;->getNetworkCapabilities(Landroid/net/Network;)Landroid/net/NetworkCapabilities;
+Landroid/net/IConnectivityManager;->getNetworkForType(I)Landroid/net/Network;
+Landroid/net/IConnectivityManager;->getNetworkInfoForUid(Landroid/net/Network;IZ)Landroid/net/NetworkInfo;
+Landroid/net/IConnectivityManager;->getNetworkWatchlistConfigHash()[B
+Landroid/net/IConnectivityManager;->getProxyForNetwork(Landroid/net/Network;)Landroid/net/ProxyInfo;
+Landroid/net/IConnectivityManager;->getRestoreDefaultNetworkDelay(I)I
+Landroid/net/IConnectivityManager;->getTetherableBluetoothRegexs()[Ljava/lang/String;
+Landroid/net/IConnectivityManager;->getTetheredDhcpRanges()[Ljava/lang/String;
+Landroid/net/IConnectivityManager;->getVpnConfig(I)Lcom/android/internal/net/VpnConfig;
+Landroid/net/IConnectivityManager;->isActiveNetworkMetered()Z
+Landroid/net/IConnectivityManager;->isAlwaysOnVpnPackageSupported(ILjava/lang/String;)Z
+Landroid/net/IConnectivityManager;->isNetworkSupported(I)Z
+Landroid/net/IConnectivityManager;->isTetheringSupported(Ljava/lang/String;)Z
+Landroid/net/IConnectivityManager;->listenForNetwork(Landroid/net/NetworkCapabilities;Landroid/os/Messenger;Landroid/os/IBinder;)Landroid/net/NetworkRequest;
+Landroid/net/IConnectivityManager;->pendingListenForNetwork(Landroid/net/NetworkCapabilities;Landroid/app/PendingIntent;)V
+Landroid/net/IConnectivityManager;->pendingRequestForNetwork(Landroid/net/NetworkCapabilities;Landroid/app/PendingIntent;)Landroid/net/NetworkRequest;
+Landroid/net/IConnectivityManager;->prepareVpn(Ljava/lang/String;Ljava/lang/String;I)Z
+Landroid/net/IConnectivityManager;->registerNetworkAgent(Landroid/os/Messenger;Landroid/net/NetworkInfo;Landroid/net/LinkProperties;Landroid/net/NetworkCapabilities;ILandroid/net/NetworkMisc;)I
+Landroid/net/IConnectivityManager;->registerNetworkFactory(Landroid/os/Messenger;Ljava/lang/String;)V
+Landroid/net/IConnectivityManager;->releaseNetworkRequest(Landroid/net/NetworkRequest;)V
+Landroid/net/IConnectivityManager;->releasePendingNetworkRequest(Landroid/app/PendingIntent;)V
+Landroid/net/IConnectivityManager;->removeVpnAddress(Ljava/lang/String;I)Z
+Landroid/net/IConnectivityManager;->reportNetworkConnectivity(Landroid/net/Network;Z)V
+Landroid/net/IConnectivityManager;->requestBandwidthUpdate(Landroid/net/Network;)Z
+Landroid/net/IConnectivityManager;->requestNetwork(Landroid/net/NetworkCapabilities;Landroid/os/Messenger;ILandroid/os/IBinder;I)Landroid/net/NetworkRequest;
+Landroid/net/IConnectivityManager;->requestRouteToHostAddress(I[B)Z
+Landroid/net/IConnectivityManager;->setAcceptUnvalidated(Landroid/net/Network;ZZ)V
+Landroid/net/IConnectivityManager;->setAlwaysOnVpnPackage(ILjava/lang/String;Z)Z
+Landroid/net/IConnectivityManager;->setAvoidUnvalidated(Landroid/net/Network;)V
+Landroid/net/IConnectivityManager;->setGlobalProxy(Landroid/net/ProxyInfo;)V
+Landroid/net/IConnectivityManager;->setProvisioningNotificationVisible(ZILjava/lang/String;)V
+Landroid/net/IConnectivityManager;->setUnderlyingNetworksForVpn([Landroid/net/Network;)Z
+Landroid/net/IConnectivityManager;->setUsbTethering(ZLjava/lang/String;)I
+Landroid/net/IConnectivityManager;->setVpnPackageAuthorization(Ljava/lang/String;IZ)V
+Landroid/net/IConnectivityManager;->startCaptivePortalApp(Landroid/net/Network;)V
+Landroid/net/IConnectivityManager;->startNattKeepalive(Landroid/net/Network;ILandroid/os/Messenger;Landroid/os/IBinder;Ljava/lang/String;ILjava/lang/String;)V
+Landroid/net/IConnectivityManager;->startTethering(ILandroid/os/ResultReceiver;ZLjava/lang/String;)V
+Landroid/net/IConnectivityManager;->stopKeepalive(Landroid/net/Network;I)V
+Landroid/net/IConnectivityManager;->stopTethering(ILjava/lang/String;)V
+Landroid/net/IConnectivityManager;->tether(Ljava/lang/String;Ljava/lang/String;)I
+Landroid/net/IConnectivityManager;->unregisterNetworkFactory(Landroid/os/Messenger;)V
+Landroid/net/IConnectivityManager;->untether(Ljava/lang/String;Ljava/lang/String;)I
+Landroid/net/IConnectivityManager;->updateLockdownVpn()Z
+Landroid/net/IpConfiguration$IpAssignment;->DHCP:Landroid/net/IpConfiguration$IpAssignment;
+Landroid/net/IpConfiguration$IpAssignment;->UNASSIGNED:Landroid/net/IpConfiguration$IpAssignment;
+Landroid/net/IpConfiguration$IpAssignment;->valueOf(Ljava/lang/String;)Landroid/net/IpConfiguration$IpAssignment;
+Landroid/net/IpConfiguration$IpAssignment;->values()[Landroid/net/IpConfiguration$IpAssignment;
+Landroid/net/IpConfiguration$ProxySettings;->PAC:Landroid/net/IpConfiguration$ProxySettings;
+Landroid/net/IpConfiguration$ProxySettings;->STATIC:Landroid/net/IpConfiguration$ProxySettings;
+Landroid/net/IpConfiguration$ProxySettings;->UNASSIGNED:Landroid/net/IpConfiguration$ProxySettings;
+Landroid/net/IpConfiguration$ProxySettings;->valueOf(Ljava/lang/String;)Landroid/net/IpConfiguration$ProxySettings;
+Landroid/net/IpConfiguration$ProxySettings;->values()[Landroid/net/IpConfiguration$ProxySettings;
+Landroid/net/IpConfiguration;-><init>()V
+Landroid/net/IpConfiguration;-><init>(Landroid/net/IpConfiguration;)V
+Landroid/net/IpConfiguration;->CREATOR:Landroid/os/Parcelable$Creator;
+Landroid/net/IpConfiguration;->getHttpProxy()Landroid/net/ProxyInfo;
+Landroid/net/IpConfiguration;->getIpAssignment()Landroid/net/IpConfiguration$IpAssignment;
+Landroid/net/IpConfiguration;->getProxySettings()Landroid/net/IpConfiguration$ProxySettings;
+Landroid/net/IpConfiguration;->getStaticIpConfiguration()Landroid/net/StaticIpConfiguration;
+Landroid/net/IpConfiguration;->init(Landroid/net/IpConfiguration$IpAssignment;Landroid/net/IpConfiguration$ProxySettings;Landroid/net/StaticIpConfiguration;Landroid/net/ProxyInfo;)V
+Landroid/net/IpConfiguration;->ipAssignment:Landroid/net/IpConfiguration$IpAssignment;
+Landroid/net/IpConfiguration;->proxySettings:Landroid/net/IpConfiguration$ProxySettings;
+Landroid/net/IpConfiguration;->setHttpProxy(Landroid/net/ProxyInfo;)V
+Landroid/net/IpConfiguration;->setIpAssignment(Landroid/net/IpConfiguration$IpAssignment;)V
+Landroid/net/IpConfiguration;->setProxySettings(Landroid/net/IpConfiguration$ProxySettings;)V
+Landroid/net/IpConfiguration;->setStaticIpConfiguration(Landroid/net/StaticIpConfiguration;)V
+Landroid/net/IpConfiguration;->staticIpConfiguration:Landroid/net/StaticIpConfiguration;
+Landroid/net/IpConfiguration;->TAG:Ljava/lang/String;
+Landroid/net/IpPrefix;-><init>(Ljava/lang/String;)V
+Landroid/net/IpPrefix;-><init>(Ljava/net/InetAddress;I)V
+Landroid/net/IpPrefix;-><init>([BI)V
+Landroid/net/IpPrefix;->address:[B
+Landroid/net/IpPrefix;->checkAndMaskAddressAndPrefixLength()V
+Landroid/net/IpPrefix;->containsPrefix(Landroid/net/IpPrefix;)Z
+Landroid/net/IpPrefix;->isIPv4()Z
+Landroid/net/IpPrefix;->isIPv6()Z
+Landroid/net/IpPrefix;->lengthComparator()Ljava/util/Comparator;
+Landroid/net/IpPrefix;->prefixLength:I
+Landroid/net/KeepalivePacketData$InvalidPacketException;-><init>(I)V
+Landroid/net/KeepalivePacketData$InvalidPacketException;->error:I
+Landroid/net/KeepalivePacketData;-><init>(Landroid/os/Parcel;)V
+Landroid/net/KeepalivePacketData;-><init>(Ljava/net/InetAddress;ILjava/net/InetAddress;I[B)V
+Landroid/net/KeepalivePacketData;->CREATOR:Landroid/os/Parcelable$Creator;
+Landroid/net/KeepalivePacketData;->dstAddress:Ljava/net/InetAddress;
+Landroid/net/KeepalivePacketData;->dstPort:I
+Landroid/net/KeepalivePacketData;->getPacket()[B
+Landroid/net/KeepalivePacketData;->IPV4_HEADER_LENGTH:I
+Landroid/net/KeepalivePacketData;->mPacket:[B
+Landroid/net/KeepalivePacketData;->nattKeepalivePacket(Ljava/net/InetAddress;ILjava/net/InetAddress;I)Landroid/net/KeepalivePacketData;
+Landroid/net/KeepalivePacketData;->srcAddress:Ljava/net/InetAddress;
+Landroid/net/KeepalivePacketData;->srcPort:I
+Landroid/net/KeepalivePacketData;->TAG:Ljava/lang/String;
+Landroid/net/KeepalivePacketData;->UDP_HEADER_LENGTH:I
+Landroid/net/LinkAddress;-><init>(Ljava/lang/String;II)V
+Landroid/net/LinkAddress;-><init>(Ljava/net/InetAddress;III)V
+Landroid/net/LinkAddress;-><init>(Ljava/net/InterfaceAddress;)V
+Landroid/net/LinkAddress;->flags:I
+Landroid/net/LinkAddress;->init(Ljava/net/InetAddress;III)V
+Landroid/net/LinkAddress;->isGlobalPreferred()Z
+Landroid/net/LinkAddress;->isIPv4()Z
+Landroid/net/LinkAddress;->isIPv6ULA()Z
+Landroid/net/LinkAddress;->scope:I
+Landroid/net/LinkAddress;->scopeForUnicastAddress(Ljava/net/InetAddress;)I
+Landroid/net/LinkProperties$CompareResult;-><init>()V
+Landroid/net/LinkProperties$CompareResult;-><init>(Ljava/util/Collection;Ljava/util/Collection;)V
+Landroid/net/LinkProperties$CompareResult;->added:Ljava/util/List;
+Landroid/net/LinkProperties$CompareResult;->removed:Ljava/util/List;
+Landroid/net/LinkProperties$ProvisioningChange;->valueOf(Ljava/lang/String;)Landroid/net/LinkProperties$ProvisioningChange;
+Landroid/net/LinkProperties;->addValidatedPrivateDnsServer(Ljava/net/InetAddress;)Z
+Landroid/net/LinkProperties;->compareAddresses(Landroid/net/LinkProperties;)Landroid/net/LinkProperties$CompareResult;
+Landroid/net/LinkProperties;->compareAllInterfaceNames(Landroid/net/LinkProperties;)Landroid/net/LinkProperties$CompareResult;
+Landroid/net/LinkProperties;->compareAllRoutes(Landroid/net/LinkProperties;)Landroid/net/LinkProperties$CompareResult;
+Landroid/net/LinkProperties;->compareDnses(Landroid/net/LinkProperties;)Landroid/net/LinkProperties$CompareResult;
+Landroid/net/LinkProperties;->compareValidatedPrivateDnses(Landroid/net/LinkProperties;)Landroid/net/LinkProperties$CompareResult;
+Landroid/net/LinkProperties;->ensureDirectlyConnectedRoutes()V
+Landroid/net/LinkProperties;->findLinkAddressIndex(Landroid/net/LinkAddress;)I
+Landroid/net/LinkProperties;->getValidatedPrivateDnsServers()Ljava/util/List;
+Landroid/net/LinkProperties;->hasIPv4AddressOnInterface(Ljava/lang/String;)Z
+Landroid/net/LinkProperties;->isIdenticalMtu(Landroid/net/LinkProperties;)Z
+Landroid/net/LinkProperties;->isIdenticalPrivateDns(Landroid/net/LinkProperties;)Z
+Landroid/net/LinkProperties;->isIdenticalTcpBufferSizes(Landroid/net/LinkProperties;)Z
+Landroid/net/LinkProperties;->isIdenticalValidatedPrivateDnses(Landroid/net/LinkProperties;)Z
+Landroid/net/LinkProperties;->isIPv4Provisioned()Z
+Landroid/net/LinkProperties;->isValidMtu(IZ)Z
+Landroid/net/LinkProperties;->MAX_MTU:I
+Landroid/net/LinkProperties;->mDnses:Ljava/util/ArrayList;
+Landroid/net/LinkProperties;->mDomains:Ljava/lang/String;
+Landroid/net/LinkProperties;->mHttpProxy:Landroid/net/ProxyInfo;
+Landroid/net/LinkProperties;->MIN_MTU:I
+Landroid/net/LinkProperties;->MIN_MTU_V6:I
+Landroid/net/LinkProperties;->mLinkAddresses:Ljava/util/ArrayList;
+Landroid/net/LinkProperties;->mMtu:I
+Landroid/net/LinkProperties;->mPrivateDnsServerName:Ljava/lang/String;
+Landroid/net/LinkProperties;->mRoutes:Ljava/util/ArrayList;
+Landroid/net/LinkProperties;->mStackedLinks:Ljava/util/Hashtable;
+Landroid/net/LinkProperties;->mTcpBufferSizes:Ljava/lang/String;
+Landroid/net/LinkProperties;->mUsePrivateDns:Z
+Landroid/net/LinkProperties;->mValidatedPrivateDnses:Ljava/util/ArrayList;
+Landroid/net/LinkProperties;->removeLinkAddress(Landroid/net/LinkAddress;)Z
+Landroid/net/LinkProperties;->removeStackedLink(Ljava/lang/String;)Z
+Landroid/net/LinkProperties;->removeValidatedPrivateDnsServer(Ljava/net/InetAddress;)Z
+Landroid/net/LinkProperties;->routeWithInterface(Landroid/net/RouteInfo;)Landroid/net/RouteInfo;
+Landroid/net/LinkProperties;->setPrivateDnsServerName(Ljava/lang/String;)V
+Landroid/net/LinkProperties;->setUsePrivateDns(Z)V
+Landroid/net/LinkProperties;->setValidatedPrivateDnsServers(Ljava/util/Collection;)V
+Landroid/net/MacAddress;-><init>(J)V
+Landroid/net/MacAddress;->BASE_GOOGLE_MAC:Landroid/net/MacAddress;
+Landroid/net/MacAddress;->byteAddrFromLongAddr(J)[B
+Landroid/net/MacAddress;->byteAddrFromStringAddr(Ljava/lang/String;)[B
+Landroid/net/MacAddress;->createRandomUnicastAddress()Landroid/net/MacAddress;
+Landroid/net/MacAddress;->createRandomUnicastAddress(Landroid/net/MacAddress;Ljava/util/Random;)Landroid/net/MacAddress;
+Landroid/net/MacAddress;->createRandomUnicastAddressWithGoogleBase()Landroid/net/MacAddress;
+Landroid/net/MacAddress;->ETHER_ADDR_BROADCAST:[B
+Landroid/net/MacAddress;->ETHER_ADDR_LEN:I
+Landroid/net/MacAddress;->isMacAddress([B)Z
+Landroid/net/MacAddress;->isMulticastAddress()Z
+Landroid/net/MacAddress;->LOCALLY_ASSIGNED_MASK:J
+Landroid/net/MacAddress;->longAddrFromByteAddr([B)J
+Landroid/net/MacAddress;->longAddrFromStringAddr(Ljava/lang/String;)J
+Landroid/net/MacAddress;->macAddressType([B)I
+Landroid/net/MacAddress;->mAddr:J
+Landroid/net/MacAddress;->MULTICAST_MASK:J
+Landroid/net/MacAddress;->NIC_MASK:J
+Landroid/net/MacAddress;->OUI_MASK:J
+Landroid/net/MacAddress;->stringAddrFromByteAddr([B)Ljava/lang/String;
+Landroid/net/MacAddress;->stringAddrFromLongAddr(J)Ljava/lang/String;
+Landroid/net/MacAddress;->TYPE_UNKNOWN:I
+Landroid/net/MacAddress;->VALID_LONG_MASK:J
+Landroid/net/Network$NetworkBoundSocketFactory;->connectToHost(Ljava/lang/String;ILjava/net/SocketAddress;)Ljava/net/Socket;
+Landroid/net/Network$NetworkBoundSocketFactory;->mNetId:I
+Landroid/net/Network;-><init>(Landroid/net/Network;)V
+Landroid/net/Network;->getNetIdForResolv()I
+Landroid/net/Network;->HANDLE_MAGIC:J
+Landroid/net/Network;->HANDLE_MAGIC_SIZE:I
+Landroid/net/Network;->httpKeepAlive:Z
+Landroid/net/Network;->httpKeepAliveDurationMs:J
+Landroid/net/Network;->httpMaxConnections:I
+Landroid/net/Network;->maybeInitUrlConnectionFactory()V
+Landroid/net/Network;->mLock:Ljava/lang/Object;
+Landroid/net/Network;->mNetworkBoundSocketFactory:Landroid/net/Network$NetworkBoundSocketFactory;
+Landroid/net/Network;->mPrivateDnsBypass:Z
+Landroid/net/Network;->mUrlConnectionFactory:Lcom/android/okhttp/internalandroidapi/HttpURLConnectionFactory;
+Landroid/net/Network;->setPrivateDnsBypass(Z)V
+Landroid/net/Network;->writeToProto(Landroid/util/proto/ProtoOutputStream;J)V
+Landroid/net/NetworkAgent;-><init>(Landroid/os/Looper;Landroid/content/Context;Ljava/lang/String;Landroid/net/NetworkInfo;Landroid/net/NetworkCapabilities;Landroid/net/LinkProperties;I)V
+Landroid/net/NetworkAgent;-><init>(Landroid/os/Looper;Landroid/content/Context;Ljava/lang/String;Landroid/net/NetworkInfo;Landroid/net/NetworkCapabilities;Landroid/net/LinkProperties;ILandroid/net/NetworkMisc;)V
+Landroid/net/NetworkAgent;->BASE:I
+Landroid/net/NetworkAgent;->BW_REFRESH_MIN_WIN_MS:J
+Landroid/net/NetworkAgent;->CMD_PREVENT_AUTOMATIC_RECONNECT:I
+Landroid/net/NetworkAgent;->CMD_REPORT_NETWORK_STATUS:I
+Landroid/net/NetworkAgent;->CMD_REQUEST_BANDWIDTH_UPDATE:I
+Landroid/net/NetworkAgent;->CMD_SAVE_ACCEPT_UNVALIDATED:I
+Landroid/net/NetworkAgent;->CMD_SET_SIGNAL_STRENGTH_THRESHOLDS:I
+Landroid/net/NetworkAgent;->CMD_START_PACKET_KEEPALIVE:I
+Landroid/net/NetworkAgent;->CMD_STOP_PACKET_KEEPALIVE:I
+Landroid/net/NetworkAgent;->CMD_SUSPECT_BAD:I
+Landroid/net/NetworkAgent;->DBG:Z
+Landroid/net/NetworkAgent;->EVENT_NETWORK_CAPABILITIES_CHANGED:I
+Landroid/net/NetworkAgent;->EVENT_NETWORK_INFO_CHANGED:I
+Landroid/net/NetworkAgent;->EVENT_NETWORK_PROPERTIES_CHANGED:I
+Landroid/net/NetworkAgent;->EVENT_NETWORK_SCORE_CHANGED:I
+Landroid/net/NetworkAgent;->EVENT_PACKET_KEEPALIVE:I
+Landroid/net/NetworkAgent;->EVENT_SET_EXPLICITLY_SELECTED:I
+Landroid/net/NetworkAgent;->explicitlySelected(Z)V
+Landroid/net/NetworkAgent;->INVALID_NETWORK:I
+Landroid/net/NetworkAgent;->log(Ljava/lang/String;)V
+Landroid/net/NetworkAgent;->LOG_TAG:Ljava/lang/String;
+Landroid/net/NetworkAgent;->mAsyncChannel:Lcom/android/internal/util/AsyncChannel;
+Landroid/net/NetworkAgent;->mContext:Landroid/content/Context;
+Landroid/net/NetworkAgent;->mLastBwRefreshTime:J
+Landroid/net/NetworkAgent;->mPollLcePending:Ljava/util/concurrent/atomic/AtomicBoolean;
+Landroid/net/NetworkAgent;->mPollLceScheduled:Z
+Landroid/net/NetworkAgent;->mPreConnectedQueue:Ljava/util/ArrayList;
+Landroid/net/NetworkAgent;->netId:I
+Landroid/net/NetworkAgent;->networkStatus(ILjava/lang/String;)V
+Landroid/net/NetworkAgent;->onPacketKeepaliveEvent(II)V
+Landroid/net/NetworkAgent;->pollLceData()V
+Landroid/net/NetworkAgent;->preventAutomaticReconnect()V
+Landroid/net/NetworkAgent;->queueOrSendMessage(III)V
+Landroid/net/NetworkAgent;->queueOrSendMessage(IIILjava/lang/Object;)V
+Landroid/net/NetworkAgent;->queueOrSendMessage(ILjava/lang/Object;)V
+Landroid/net/NetworkAgent;->queueOrSendMessage(Landroid/os/Message;)V
+Landroid/net/NetworkAgent;->REDIRECT_URL_KEY:Ljava/lang/String;
+Landroid/net/NetworkAgent;->saveAcceptUnvalidated(Z)V
+Landroid/net/NetworkAgent;->sendLinkProperties(Landroid/net/LinkProperties;)V
+Landroid/net/NetworkAgent;->sendNetworkCapabilities(Landroid/net/NetworkCapabilities;)V
+Landroid/net/NetworkAgent;->sendNetworkScore(I)V
+Landroid/net/NetworkAgent;->setSignalStrengthThresholds([I)V
+Landroid/net/NetworkAgent;->startPacketKeepalive(Landroid/os/Message;)V
+Landroid/net/NetworkAgent;->stopPacketKeepalive(Landroid/os/Message;)V
+Landroid/net/NetworkAgent;->unwanted()V
+Landroid/net/NetworkAgent;->VALID_NETWORK:I
+Landroid/net/NetworkAgent;->VDBG:Z
+Landroid/net/NetworkAgent;->WIFI_BASE_SCORE:I
+Landroid/net/NetworkBadging;-><init>()V
+Landroid/net/NetworkBadging;->getBadgedWifiSignalResource(I)I
+Landroid/net/NetworkBadging;->getWifiSignalResource(I)I
+Landroid/net/NetworkCapabilities$NameOf;->nameOf(I)Ljava/lang/String;
+Landroid/net/NetworkCapabilities;->addUnwantedCapability(I)V
+Landroid/net/NetworkCapabilities;->appendStringRepresentationOfBitMaskToStringBuilder(Ljava/lang/StringBuilder;JLandroid/net/NetworkCapabilities$NameOf;Ljava/lang/String;)V
+Landroid/net/NetworkCapabilities;->appliesToUid(I)Z
+Landroid/net/NetworkCapabilities;->appliesToUidRange(Landroid/net/UidRange;)Z
+Landroid/net/NetworkCapabilities;->capabilityNameOf(I)Ljava/lang/String;
+Landroid/net/NetworkCapabilities;->capabilityNamesOf([I)Ljava/lang/String;
+Landroid/net/NetworkCapabilities;->checkValidCapability(I)V
+Landroid/net/NetworkCapabilities;->checkValidTransportType(I)V
+Landroid/net/NetworkCapabilities;->clearAll()V
+Landroid/net/NetworkCapabilities;->combineCapabilities(Landroid/net/NetworkCapabilities;)V
+Landroid/net/NetworkCapabilities;->combineLinkBandwidths(Landroid/net/NetworkCapabilities;)V
+Landroid/net/NetworkCapabilities;->combineNetCapabilities(Landroid/net/NetworkCapabilities;)V
+Landroid/net/NetworkCapabilities;->combineSignalStrength(Landroid/net/NetworkCapabilities;)V
+Landroid/net/NetworkCapabilities;->combineSpecifiers(Landroid/net/NetworkCapabilities;)V
+Landroid/net/NetworkCapabilities;->combineSSIDs(Landroid/net/NetworkCapabilities;)V
+Landroid/net/NetworkCapabilities;->combineTransportTypes(Landroid/net/NetworkCapabilities;)V
+Landroid/net/NetworkCapabilities;->combineUids(Landroid/net/NetworkCapabilities;)V
+Landroid/net/NetworkCapabilities;->DEFAULT_CAPABILITIES:J
+Landroid/net/NetworkCapabilities;->describeFirstNonRequestableCapability()Ljava/lang/String;
+Landroid/net/NetworkCapabilities;->describeImmutableDifferences(Landroid/net/NetworkCapabilities;)Ljava/lang/String;
+Landroid/net/NetworkCapabilities;->equalRequestableCapabilities(Landroid/net/NetworkCapabilities;)Z
+Landroid/net/NetworkCapabilities;->equalsLinkBandwidths(Landroid/net/NetworkCapabilities;)Z
+Landroid/net/NetworkCapabilities;->equalsNetCapabilities(Landroid/net/NetworkCapabilities;)Z
+Landroid/net/NetworkCapabilities;->equalsNetCapabilitiesRequestable(Landroid/net/NetworkCapabilities;)Z
+Landroid/net/NetworkCapabilities;->equalsSignalStrength(Landroid/net/NetworkCapabilities;)Z
+Landroid/net/NetworkCapabilities;->equalsSpecifier(Landroid/net/NetworkCapabilities;)Z
+Landroid/net/NetworkCapabilities;->equalsSSID(Landroid/net/NetworkCapabilities;)Z
+Landroid/net/NetworkCapabilities;->equalsTransportTypes(Landroid/net/NetworkCapabilities;)Z
+Landroid/net/NetworkCapabilities;->equalsUids(Landroid/net/NetworkCapabilities;)Z
+Landroid/net/NetworkCapabilities;->FORCE_RESTRICTED_CAPABILITIES:J
+Landroid/net/NetworkCapabilities;->getSSID()Ljava/lang/String;
+Landroid/net/NetworkCapabilities;->getUids()Ljava/util/Set;
+Landroid/net/NetworkCapabilities;->getUnwantedCapabilities()[I
+Landroid/net/NetworkCapabilities;->hasUnwantedCapability(I)Z
+Landroid/net/NetworkCapabilities;->INVALID_UID:I
+Landroid/net/NetworkCapabilities;->isValidCapability(I)Z
+Landroid/net/NetworkCapabilities;->isValidTransport(I)Z
+Landroid/net/NetworkCapabilities;->LINK_BANDWIDTH_UNSPECIFIED:I
+Landroid/net/NetworkCapabilities;->maxBandwidth(II)I
+Landroid/net/NetworkCapabilities;->MAX_NET_CAPABILITY:I
+Landroid/net/NetworkCapabilities;->MAX_TRANSPORT:I
+Landroid/net/NetworkCapabilities;->maybeMarkCapabilitiesRestricted()V
+Landroid/net/NetworkCapabilities;->mEstablishingVpnAppUid:I
+Landroid/net/NetworkCapabilities;->minBandwidth(II)I
+Landroid/net/NetworkCapabilities;->MIN_NET_CAPABILITY:I
+Landroid/net/NetworkCapabilities;->MIN_TRANSPORT:I
+Landroid/net/NetworkCapabilities;->mLinkDownBandwidthKbps:I
+Landroid/net/NetworkCapabilities;->mLinkUpBandwidthKbps:I
+Landroid/net/NetworkCapabilities;->mNetworkSpecifier:Landroid/net/NetworkSpecifier;
+Landroid/net/NetworkCapabilities;->mSSID:Ljava/lang/String;
+Landroid/net/NetworkCapabilities;->mTransportTypes:J
+Landroid/net/NetworkCapabilities;->mUids:Landroid/util/ArraySet;
+Landroid/net/NetworkCapabilities;->mUnwantedNetworkCapabilities:J
+Landroid/net/NetworkCapabilities;->MUTABLE_CAPABILITIES:J
+Landroid/net/NetworkCapabilities;->NON_REQUESTABLE_CAPABILITIES:J
+Landroid/net/NetworkCapabilities;->removeTransportType(I)Landroid/net/NetworkCapabilities;
+Landroid/net/NetworkCapabilities;->RESTRICTED_CAPABILITIES:J
+Landroid/net/NetworkCapabilities;->satisfiedByImmutableNetworkCapabilities(Landroid/net/NetworkCapabilities;)Z
+Landroid/net/NetworkCapabilities;->satisfiedByLinkBandwidths(Landroid/net/NetworkCapabilities;)Z
+Landroid/net/NetworkCapabilities;->satisfiedByNetCapabilities(Landroid/net/NetworkCapabilities;Z)Z
+Landroid/net/NetworkCapabilities;->satisfiedByNetworkCapabilities(Landroid/net/NetworkCapabilities;)Z
+Landroid/net/NetworkCapabilities;->satisfiedByNetworkCapabilities(Landroid/net/NetworkCapabilities;Z)Z
+Landroid/net/NetworkCapabilities;->satisfiedBySignalStrength(Landroid/net/NetworkCapabilities;)Z
+Landroid/net/NetworkCapabilities;->satisfiedBySpecifier(Landroid/net/NetworkCapabilities;)Z
+Landroid/net/NetworkCapabilities;->satisfiedBySSID(Landroid/net/NetworkCapabilities;)Z
+Landroid/net/NetworkCapabilities;->satisfiedByTransportTypes(Landroid/net/NetworkCapabilities;)Z
+Landroid/net/NetworkCapabilities;->satisfiedByUids(Landroid/net/NetworkCapabilities;)Z
+Landroid/net/NetworkCapabilities;->set(Landroid/net/NetworkCapabilities;)V
+Landroid/net/NetworkCapabilities;->setCapabilities([I)V
+Landroid/net/NetworkCapabilities;->setCapabilities([I[I)V
+Landroid/net/NetworkCapabilities;->setCapability(IZ)Landroid/net/NetworkCapabilities;
+Landroid/net/NetworkCapabilities;->setEstablishingVpnAppUid(I)V
+Landroid/net/NetworkCapabilities;->setLinkDownstreamBandwidthKbps(I)Landroid/net/NetworkCapabilities;
+Landroid/net/NetworkCapabilities;->setLinkUpstreamBandwidthKbps(I)Landroid/net/NetworkCapabilities;
+Landroid/net/NetworkCapabilities;->setNetworkSpecifier(Landroid/net/NetworkSpecifier;)Landroid/net/NetworkCapabilities;
+Landroid/net/NetworkCapabilities;->setSingleUid(I)Landroid/net/NetworkCapabilities;
+Landroid/net/NetworkCapabilities;->setSSID(Ljava/lang/String;)Landroid/net/NetworkCapabilities;
+Landroid/net/NetworkCapabilities;->setTransportType(IZ)Landroid/net/NetworkCapabilities;
+Landroid/net/NetworkCapabilities;->setTransportTypes([I)V
+Landroid/net/NetworkCapabilities;->setUids(Ljava/util/Set;)Landroid/net/NetworkCapabilities;
+Landroid/net/NetworkCapabilities;->SIGNAL_STRENGTH_UNSPECIFIED:I
+Landroid/net/NetworkCapabilities;->TAG:Ljava/lang/String;
+Landroid/net/NetworkCapabilities;->transportNameOf(I)Ljava/lang/String;
+Landroid/net/NetworkCapabilities;->TRANSPORT_NAMES:[Ljava/lang/String;
+Landroid/net/NetworkCapabilities;->UNRESTRICTED_CAPABILITIES:J
+Landroid/net/NetworkCapabilities;->writeToProto(Landroid/util/proto/ProtoOutputStream;J)V
+Landroid/net/NetworkCapabilitiesProto;-><init>()V
+Landroid/net/NetworkCapabilitiesProto;->CAN_REPORT_SIGNAL_STRENGTH:J
+Landroid/net/NetworkCapabilitiesProto;->CAPABILITIES:J
+Landroid/net/NetworkCapabilitiesProto;->LINK_DOWN_BANDWIDTH_KBPS:J
+Landroid/net/NetworkCapabilitiesProto;->LINK_UP_BANDWIDTH_KBPS:J
+Landroid/net/NetworkCapabilitiesProto;->NETWORK_SPECIFIER:J
+Landroid/net/NetworkCapabilitiesProto;->NET_CAPABILITY_CAPTIVE_PORTAL:I
+Landroid/net/NetworkCapabilitiesProto;->NET_CAPABILITY_CBS:I
+Landroid/net/NetworkCapabilitiesProto;->NET_CAPABILITY_DUN:I
+Landroid/net/NetworkCapabilitiesProto;->NET_CAPABILITY_EIMS:I
+Landroid/net/NetworkCapabilitiesProto;->NET_CAPABILITY_FOREGROUND:I
+Landroid/net/NetworkCapabilitiesProto;->NET_CAPABILITY_FOTA:I
+Landroid/net/NetworkCapabilitiesProto;->NET_CAPABILITY_IA:I
+Landroid/net/NetworkCapabilitiesProto;->NET_CAPABILITY_IMS:I
+Landroid/net/NetworkCapabilitiesProto;->NET_CAPABILITY_INTERNET:I
+Landroid/net/NetworkCapabilitiesProto;->NET_CAPABILITY_MMS:I
+Landroid/net/NetworkCapabilitiesProto;->NET_CAPABILITY_NOT_METERED:I
+Landroid/net/NetworkCapabilitiesProto;->NET_CAPABILITY_NOT_RESTRICTED:I
+Landroid/net/NetworkCapabilitiesProto;->NET_CAPABILITY_NOT_ROAMING:I
+Landroid/net/NetworkCapabilitiesProto;->NET_CAPABILITY_NOT_VPN:I
+Landroid/net/NetworkCapabilitiesProto;->NET_CAPABILITY_RCS:I
+Landroid/net/NetworkCapabilitiesProto;->NET_CAPABILITY_SUPL:I
+Landroid/net/NetworkCapabilitiesProto;->NET_CAPABILITY_TRUSTED:I
+Landroid/net/NetworkCapabilitiesProto;->NET_CAPABILITY_VALIDATED:I
+Landroid/net/NetworkCapabilitiesProto;->NET_CAPABILITY_WIFI_P2P:I
+Landroid/net/NetworkCapabilitiesProto;->NET_CAPABILITY_XCAP:I
+Landroid/net/NetworkCapabilitiesProto;->SIGNAL_STRENGTH:J
+Landroid/net/NetworkCapabilitiesProto;->TRANSPORTS:J
+Landroid/net/NetworkCapabilitiesProto;->TRANSPORT_BLUETOOTH:I
+Landroid/net/NetworkCapabilitiesProto;->TRANSPORT_CELLULAR:I
+Landroid/net/NetworkCapabilitiesProto;->TRANSPORT_ETHERNET:I
+Landroid/net/NetworkCapabilitiesProto;->TRANSPORT_LOWPAN:I
+Landroid/net/NetworkCapabilitiesProto;->TRANSPORT_VPN:I
+Landroid/net/NetworkCapabilitiesProto;->TRANSPORT_WIFI:I
+Landroid/net/NetworkCapabilitiesProto;->TRANSPORT_WIFI_AWARE:I
+Landroid/net/NetworkConfig;-><init>(Ljava/lang/String;)V
+Landroid/net/NetworkConfig;->dependencyMet:Z
+Landroid/net/NetworkConfig;->isDefault()Z
+Landroid/net/NetworkConfig;->name:Ljava/lang/String;
+Landroid/net/NetworkConfig;->priority:I
+Landroid/net/NetworkConfig;->radio:I
+Landroid/net/NetworkConfig;->restoreTime:I
+Landroid/net/NetworkConfig;->type:I
+Landroid/net/NetworkFactory$NetworkRequestInfo;->request:Landroid/net/NetworkRequest;
+Landroid/net/NetworkFactory$NetworkRequestInfo;->requested:Z
+Landroid/net/NetworkFactory$NetworkRequestInfo;->score:I
+Landroid/net/NetworkFactory;->acceptRequest(Landroid/net/NetworkRequest;I)Z
+Landroid/net/NetworkFactory;->addNetworkRequest(Landroid/net/NetworkRequest;I)V
+Landroid/net/NetworkFactory;->BASE:I
+Landroid/net/NetworkFactory;->CMD_CANCEL_REQUEST:I
+Landroid/net/NetworkFactory;->CMD_REQUEST_NETWORK:I
+Landroid/net/NetworkFactory;->CMD_SET_FILTER:I
+Landroid/net/NetworkFactory;->CMD_SET_SCORE:I
+Landroid/net/NetworkFactory;->DBG:Z
+Landroid/net/NetworkFactory;->evalRequest(Landroid/net/NetworkFactory$NetworkRequestInfo;)V
+Landroid/net/NetworkFactory;->evalRequests()V
+Landroid/net/NetworkFactory;->getRequestCount()I
+Landroid/net/NetworkFactory;->handleAddRequest(Landroid/net/NetworkRequest;I)V
+Landroid/net/NetworkFactory;->handleRemoveRequest(Landroid/net/NetworkRequest;)V
+Landroid/net/NetworkFactory;->handleSetFilter(Landroid/net/NetworkCapabilities;)V
+Landroid/net/NetworkFactory;->handleSetScore(I)V
+Landroid/net/NetworkFactory;->log(Ljava/lang/String;)V
+Landroid/net/NetworkFactory;->LOG_TAG:Ljava/lang/String;
+Landroid/net/NetworkFactory;->mCapabilityFilter:Landroid/net/NetworkCapabilities;
+Landroid/net/NetworkFactory;->mContext:Landroid/content/Context;
+Landroid/net/NetworkFactory;->mMessenger:Landroid/os/Messenger;
+Landroid/net/NetworkFactory;->mNetworkRequests:Landroid/util/SparseArray;
+Landroid/net/NetworkFactory;->mRefCount:I
+Landroid/net/NetworkFactory;->mScore:I
+Landroid/net/NetworkFactory;->needNetworkFor(Landroid/net/NetworkRequest;I)V
+Landroid/net/NetworkFactory;->reevaluateAllRequests()V
+Landroid/net/NetworkFactory;->register()V
+Landroid/net/NetworkFactory;->releaseNetworkFor(Landroid/net/NetworkRequest;)V
+Landroid/net/NetworkFactory;->removeNetworkRequest(Landroid/net/NetworkRequest;)V
+Landroid/net/NetworkFactory;->setCapabilityFilter(Landroid/net/NetworkCapabilities;)V
+Landroid/net/NetworkFactory;->startNetwork()V
+Landroid/net/NetworkFactory;->stopNetwork()V
+Landroid/net/NetworkFactory;->unregister()V
+Landroid/net/NetworkFactory;->VDBG:Z
+Landroid/net/NetworkIdentity;-><init>(IILjava/lang/String;Ljava/lang/String;ZZZ)V
+Landroid/net/NetworkIdentity;->buildNetworkIdentity(Landroid/content/Context;Landroid/net/NetworkState;Z)Landroid/net/NetworkIdentity;
+Landroid/net/NetworkIdentity;->COMBINE_SUBTYPE_ENABLED:Z
+Landroid/net/NetworkIdentity;->compareTo(Landroid/net/NetworkIdentity;)I
+Landroid/net/NetworkIdentity;->getDefaultNetwork()Z
+Landroid/net/NetworkIdentity;->getMetered()Z
+Landroid/net/NetworkIdentity;->getNetworkId()Ljava/lang/String;
+Landroid/net/NetworkIdentity;->getRoaming()Z
+Landroid/net/NetworkIdentity;->getSubscriberId()Ljava/lang/String;
+Landroid/net/NetworkIdentity;->getSubType()I
+Landroid/net/NetworkIdentity;->getType()I
+Landroid/net/NetworkIdentity;->mDefaultNetwork:Z
+Landroid/net/NetworkIdentity;->mMetered:Z
+Landroid/net/NetworkIdentity;->mNetworkId:Ljava/lang/String;
+Landroid/net/NetworkIdentity;->mRoaming:Z
+Landroid/net/NetworkIdentity;->mSubscriberId:Ljava/lang/String;
+Landroid/net/NetworkIdentity;->mSubType:I
+Landroid/net/NetworkIdentity;->mType:I
+Landroid/net/NetworkIdentity;->scrubSubscriberId(Ljava/lang/String;)Ljava/lang/String;
+Landroid/net/NetworkIdentity;->scrubSubscriberId([Ljava/lang/String;)[Ljava/lang/String;
+Landroid/net/NetworkIdentity;->SUBTYPE_COMBINED:I
+Landroid/net/NetworkIdentity;->TAG:Ljava/lang/String;
+Landroid/net/NetworkIdentity;->writeToProto(Landroid/util/proto/ProtoOutputStream;J)V
+Landroid/net/NetworkInfo;->mDetailedState:Landroid/net/NetworkInfo$DetailedState;
+Landroid/net/NetworkInfo;->mExtraInfo:Ljava/lang/String;
+Landroid/net/NetworkInfo;->mIsAvailable:Z
+Landroid/net/NetworkInfo;->mIsFailover:Z
+Landroid/net/NetworkInfo;->mIsRoaming:Z
+Landroid/net/NetworkInfo;->mNetworkType:I
+Landroid/net/NetworkInfo;->mReason:Ljava/lang/String;
+Landroid/net/NetworkInfo;->mState:Landroid/net/NetworkInfo$State;
+Landroid/net/NetworkInfo;->mSubtype:I
+Landroid/net/NetworkInfo;->mSubtypeName:Ljava/lang/String;
+Landroid/net/NetworkInfo;->mTypeName:Ljava/lang/String;
+Landroid/net/NetworkInfo;->setExtraInfo(Ljava/lang/String;)V
+Landroid/net/NetworkInfo;->setType(I)V
+Landroid/net/NetworkInfo;->stateMap:Ljava/util/EnumMap;
+Landroid/net/NetworkKey;-><init>(Landroid/os/Parcel;)V
+Landroid/net/NetworkKey;->createFromScanResult(Landroid/net/wifi/ScanResult;)Landroid/net/NetworkKey;
+Landroid/net/NetworkKey;->createFromWifiInfo(Landroid/net/wifi/WifiInfo;)Landroid/net/NetworkKey;
+Landroid/net/NetworkKey;->TAG:Ljava/lang/String;
+Landroid/net/NetworkMisc;-><init>()V
+Landroid/net/NetworkMisc;-><init>(Landroid/net/NetworkMisc;)V
+Landroid/net/NetworkMisc;->acceptUnvalidated:Z
+Landroid/net/NetworkMisc;->allowBypass:Z
+Landroid/net/NetworkMisc;->CREATOR:Landroid/os/Parcelable$Creator;
+Landroid/net/NetworkMisc;->explicitlySelected:Z
+Landroid/net/NetworkMisc;->provisioningNotificationDisabled:Z
+Landroid/net/NetworkMisc;->subscriberId:Ljava/lang/String;
+Landroid/net/NetworkPolicy;-><init>(Landroid/net/NetworkTemplate;ILjava/lang/String;JJZ)V
+Landroid/net/NetworkPolicy;-><init>(Landroid/net/NetworkTemplate;Landroid/util/RecurrenceRule;JJJJJZZ)V
+Landroid/net/NetworkPolicy;-><init>(Landroid/net/NetworkTemplate;Landroid/util/RecurrenceRule;JJJJZZ)V
+Landroid/net/NetworkPolicy;-><init>(Landroid/os/Parcel;)V
+Landroid/net/NetworkPolicy;->buildRule(ILjava/time/ZoneId;)Landroid/util/RecurrenceRule;
+Landroid/net/NetworkPolicy;->cycleIterator()Ljava/util/Iterator;
+Landroid/net/NetworkPolicy;->cycleRule:Landroid/util/RecurrenceRule;
+Landroid/net/NetworkPolicy;->CYCLE_NONE:I
+Landroid/net/NetworkPolicy;->DEFAULT_MTU:J
+Landroid/net/NetworkPolicy;->getBytesForBackup()[B
+Landroid/net/NetworkPolicy;->getNetworkPolicyFromBackup(Ljava/io/DataInputStream;)Landroid/net/NetworkPolicy;
+Landroid/net/NetworkPolicy;->hasCycle()Z
+Landroid/net/NetworkPolicy;->lastLimitSnooze:J
+Landroid/net/NetworkPolicy;->lastRapidSnooze:J
+Landroid/net/NetworkPolicy;->lastWarningSnooze:J
+Landroid/net/NetworkPolicy;->LIMIT_DISABLED:J
+Landroid/net/NetworkPolicy;->SNOOZE_NEVER:J
+Landroid/net/NetworkPolicy;->VERSION_INIT:I
+Landroid/net/NetworkPolicy;->VERSION_RAPID:I
+Landroid/net/NetworkPolicy;->VERSION_RULE:I
+Landroid/net/NetworkPolicy;->WARNING_DISABLED:J
+Landroid/net/NetworkPolicyManager$Listener;-><init>()V
+Landroid/net/NetworkPolicyManager$Listener;->onMeteredIfacesChanged([Ljava/lang/String;)V
+Landroid/net/NetworkPolicyManager$Listener;->onRestrictBackgroundChanged(Z)V
+Landroid/net/NetworkPolicyManager$Listener;->onSubscriptionOverride(III)V
+Landroid/net/NetworkPolicyManager$Listener;->onUidPoliciesChanged(II)V
+Landroid/net/NetworkPolicyManager$Listener;->onUidRulesChanged(II)V
+Landroid/net/NetworkPolicyManager;-><init>(Landroid/content/Context;Landroid/net/INetworkPolicyManager;)V
+Landroid/net/NetworkPolicyManager;->addUidPolicy(II)V
+Landroid/net/NetworkPolicyManager;->ALLOW_PLATFORM_APP_POLICY:Z
+Landroid/net/NetworkPolicyManager;->cycleIterator(Landroid/net/NetworkPolicy;)Ljava/util/Iterator;
+Landroid/net/NetworkPolicyManager;->EXTRA_NETWORK_TEMPLATE:Ljava/lang/String;
+Landroid/net/NetworkPolicyManager;->factoryReset(Ljava/lang/String;)V
+Landroid/net/NetworkPolicyManager;->FIREWALL_CHAIN_DOZABLE:I
+Landroid/net/NetworkPolicyManager;->FIREWALL_CHAIN_NAME_DOZABLE:Ljava/lang/String;
+Landroid/net/NetworkPolicyManager;->FIREWALL_CHAIN_NAME_NONE:Ljava/lang/String;
+Landroid/net/NetworkPolicyManager;->FIREWALL_CHAIN_NAME_POWERSAVE:Ljava/lang/String;
+Landroid/net/NetworkPolicyManager;->FIREWALL_CHAIN_NAME_STANDBY:Ljava/lang/String;
+Landroid/net/NetworkPolicyManager;->FIREWALL_CHAIN_NONE:I
+Landroid/net/NetworkPolicyManager;->FIREWALL_CHAIN_POWERSAVE:I
+Landroid/net/NetworkPolicyManager;->FIREWALL_CHAIN_STANDBY:I
+Landroid/net/NetworkPolicyManager;->FIREWALL_RULE_ALLOW:I
+Landroid/net/NetworkPolicyManager;->FIREWALL_RULE_DEFAULT:I
+Landroid/net/NetworkPolicyManager;->FIREWALL_RULE_DENY:I
+Landroid/net/NetworkPolicyManager;->FIREWALL_TYPE_BLACKLIST:I
+Landroid/net/NetworkPolicyManager;->FIREWALL_TYPE_WHITELIST:I
+Landroid/net/NetworkPolicyManager;->FOREGROUND_THRESHOLD_STATE:I
+Landroid/net/NetworkPolicyManager;->isProcStateAllowedWhileIdleOrPowerSaveMode(I)Z
+Landroid/net/NetworkPolicyManager;->isProcStateAllowedWhileOnRestrictBackground(I)Z
+Landroid/net/NetworkPolicyManager;->isUidValidForPolicy(Landroid/content/Context;I)Z
+Landroid/net/NetworkPolicyManager;->MASK_ALL_NETWORKS:I
+Landroid/net/NetworkPolicyManager;->MASK_METERED_NETWORKS:I
+Landroid/net/NetworkPolicyManager;->mContext:Landroid/content/Context;
+Landroid/net/NetworkPolicyManager;->OVERRIDE_CONGESTED:I
+Landroid/net/NetworkPolicyManager;->OVERRIDE_UNMETERED:I
+Landroid/net/NetworkPolicyManager;->POLICY_ALLOW_METERED_BACKGROUND:I
+Landroid/net/NetworkPolicyManager;->POLICY_NONE:I
+Landroid/net/NetworkPolicyManager;->POLICY_REJECT_METERED_BACKGROUND:I
+Landroid/net/NetworkPolicyManager;->removeUidPolicy(II)V
+Landroid/net/NetworkPolicyManager;->resolveNetworkId(Landroid/net/wifi/WifiConfiguration;)Ljava/lang/String;
+Landroid/net/NetworkPolicyManager;->resolveNetworkId(Ljava/lang/String;)Ljava/lang/String;
+Landroid/net/NetworkPolicyManager;->RULE_ALLOW_ALL:I
+Landroid/net/NetworkPolicyManager;->RULE_ALLOW_METERED:I
+Landroid/net/NetworkPolicyManager;->RULE_NONE:I
+Landroid/net/NetworkPolicyManager;->RULE_REJECT_ALL:I
+Landroid/net/NetworkPolicyManager;->RULE_REJECT_METERED:I
+Landroid/net/NetworkPolicyManager;->RULE_TEMPORARY_ALLOW_METERED:I
+Landroid/net/NetworkPolicyManager;->setNetworkPolicies([Landroid/net/NetworkPolicy;)V
+Landroid/net/NetworkPolicyManager;->uidPoliciesToString(I)Ljava/lang/String;
+Landroid/net/NetworkPolicyManager;->uidRulesToString(I)Ljava/lang/String;
+Landroid/net/NetworkProto;-><init>()V
+Landroid/net/NetworkProto;->NET_ID:J
+Landroid/net/NetworkQuotaInfo;-><init>()V
+Landroid/net/NetworkQuotaInfo;-><init>(Landroid/os/Parcel;)V
+Landroid/net/NetworkQuotaInfo;->NO_LIMIT:J
+Landroid/net/NetworkRecommendationProvider$ServiceWrapper;->enforceCallingPermission()V
+Landroid/net/NetworkRecommendationProvider$ServiceWrapper;->execute(Ljava/lang/Runnable;)V
+Landroid/net/NetworkRecommendationProvider$ServiceWrapper;->mContext:Landroid/content/Context;
+Landroid/net/NetworkRecommendationProvider$ServiceWrapper;->mExecutor:Ljava/util/concurrent/Executor;
+Landroid/net/NetworkRecommendationProvider$ServiceWrapper;->mHandler:Landroid/os/Handler;
+Landroid/net/NetworkRecommendationProvider$ServiceWrapper;->requestScores([Landroid/net/NetworkKey;)V
+Landroid/net/NetworkRecommendationProvider;->mService:Landroid/os/IBinder;
+Landroid/net/NetworkRecommendationProvider;->TAG:Ljava/lang/String;
+Landroid/net/NetworkRecommendationProvider;->VERBOSE:Z
+Landroid/net/NetworkRequest$Builder;->addUnwantedCapability(I)Landroid/net/NetworkRequest$Builder;
+Landroid/net/NetworkRequest$Builder;->mNetworkCapabilities:Landroid/net/NetworkCapabilities;
+Landroid/net/NetworkRequest$Builder;->setCapabilities(Landroid/net/NetworkCapabilities;)Landroid/net/NetworkRequest$Builder;
+Landroid/net/NetworkRequest$Builder;->setLinkDownstreamBandwidthKbps(I)Landroid/net/NetworkRequest$Builder;
+Landroid/net/NetworkRequest$Builder;->setLinkUpstreamBandwidthKbps(I)Landroid/net/NetworkRequest$Builder;
+Landroid/net/NetworkRequest$Builder;->setUids(Ljava/util/Set;)Landroid/net/NetworkRequest$Builder;
+Landroid/net/NetworkRequest$Type;->BACKGROUND_REQUEST:Landroid/net/NetworkRequest$Type;
+Landroid/net/NetworkRequest$Type;->LISTEN:Landroid/net/NetworkRequest$Type;
+Landroid/net/NetworkRequest$Type;->NONE:Landroid/net/NetworkRequest$Type;
+Landroid/net/NetworkRequest$Type;->REQUEST:Landroid/net/NetworkRequest$Type;
+Landroid/net/NetworkRequest$Type;->TRACK_DEFAULT:Landroid/net/NetworkRequest$Type;
+Landroid/net/NetworkRequest$Type;->valueOf(Ljava/lang/String;)Landroid/net/NetworkRequest$Type;
+Landroid/net/NetworkRequest$Type;->values()[Landroid/net/NetworkRequest$Type;
+Landroid/net/NetworkRequest;-><init>(Landroid/net/NetworkCapabilities;IILandroid/net/NetworkRequest$Type;)V
+Landroid/net/NetworkRequest;-><init>(Landroid/net/NetworkRequest;)V
+Landroid/net/NetworkRequest;->hasUnwantedCapability(I)Z
+Landroid/net/NetworkRequest;->isBackgroundRequest()Z
+Landroid/net/NetworkRequest;->isForegroundRequest()Z
+Landroid/net/NetworkRequest;->isListen()Z
+Landroid/net/NetworkRequest;->isRequest()Z
+Landroid/net/NetworkRequest;->type:Landroid/net/NetworkRequest$Type;
+Landroid/net/NetworkRequest;->typeToProtoEnum(Landroid/net/NetworkRequest$Type;)I
+Landroid/net/NetworkRequest;->writeToProto(Landroid/util/proto/ProtoOutputStream;J)V
+Landroid/net/NetworkRequestProto;-><init>()V
+Landroid/net/NetworkRequestProto;->LEGACY_TYPE:J
+Landroid/net/NetworkRequestProto;->NETWORK_CAPABILITIES:J
+Landroid/net/NetworkRequestProto;->REQUEST_ID:J
+Landroid/net/NetworkRequestProto;->TYPE:J
+Landroid/net/NetworkRequestProto;->TYPE_BACKGROUND_REQUEST:I
+Landroid/net/NetworkRequestProto;->TYPE_LISTEN:I
+Landroid/net/NetworkRequestProto;->TYPE_NONE:I
+Landroid/net/NetworkRequestProto;->TYPE_REQUEST:I
+Landroid/net/NetworkRequestProto;->TYPE_TRACK_DEFAULT:I
+Landroid/net/NetworkRequestProto;->TYPE_UNKNOWN:I
+Landroid/net/NetworkScoreManager;-><init>(Landroid/content/Context;)V
+Landroid/net/NetworkScoreManager;->CACHE_FILTER_CURRENT_NETWORK:I
+Landroid/net/NetworkScoreManager;->CACHE_FILTER_NONE:I
+Landroid/net/NetworkScoreManager;->CACHE_FILTER_SCAN_RESULTS:I
+Landroid/net/NetworkScoreManager;->getActiveScorer()Landroid/net/NetworkScorerAppData;
+Landroid/net/NetworkScoreManager;->getAllValidScorers()Ljava/util/List;
+Landroid/net/NetworkScoreManager;->isCallerActiveScorer(I)Z
+Landroid/net/NetworkScoreManager;->mContext:Landroid/content/Context;
+Landroid/net/NetworkScoreManager;->mService:Landroid/net/INetworkScoreService;
+Landroid/net/NetworkScoreManager;->NETWORK_AVAILABLE_NOTIFICATION_CHANNEL_ID_META_DATA:Ljava/lang/String;
+Landroid/net/NetworkScoreManager;->RECOMMENDATIONS_ENABLED_FORCED_OFF:I
+Landroid/net/NetworkScoreManager;->RECOMMENDATIONS_ENABLED_OFF:I
+Landroid/net/NetworkScoreManager;->RECOMMENDATIONS_ENABLED_ON:I
+Landroid/net/NetworkScoreManager;->RECOMMENDATION_SERVICE_LABEL_META_DATA:Ljava/lang/String;
+Landroid/net/NetworkScoreManager;->registerNetworkScoreCache(ILandroid/net/INetworkScoreCache;)V
+Landroid/net/NetworkScoreManager;->registerNetworkScoreCache(ILandroid/net/INetworkScoreCache;I)V
+Landroid/net/NetworkScoreManager;->requestScores([Landroid/net/NetworkKey;)Z
+Landroid/net/NetworkScoreManager;->unregisterNetworkScoreCache(ILandroid/net/INetworkScoreCache;)V
+Landroid/net/NetworkScoreManager;->USE_OPEN_WIFI_PACKAGE_META_DATA:Ljava/lang/String;
+Landroid/net/NetworkScorerAppData;-><init>(ILandroid/content/ComponentName;Ljava/lang/String;Landroid/content/ComponentName;Ljava/lang/String;)V
+Landroid/net/NetworkScorerAppData;-><init>(Landroid/os/Parcel;)V
+Landroid/net/NetworkScorerAppData;->CREATOR:Landroid/os/Parcelable$Creator;
+Landroid/net/NetworkScorerAppData;->getEnableUseOpenWifiActivity()Landroid/content/ComponentName;
+Landroid/net/NetworkScorerAppData;->getNetworkAvailableNotificationChannelId()Ljava/lang/String;
+Landroid/net/NetworkScorerAppData;->getRecommendationServiceComponent()Landroid/content/ComponentName;
+Landroid/net/NetworkScorerAppData;->getRecommendationServiceLabel()Ljava/lang/String;
+Landroid/net/NetworkScorerAppData;->getRecommendationServicePackageName()Ljava/lang/String;
+Landroid/net/NetworkScorerAppData;->mEnableUseOpenWifiActivity:Landroid/content/ComponentName;
+Landroid/net/NetworkScorerAppData;->mNetworkAvailableNotificationChannelId:Ljava/lang/String;
+Landroid/net/NetworkScorerAppData;->mRecommendationService:Landroid/content/ComponentName;
+Landroid/net/NetworkScorerAppData;->mRecommendationServiceLabel:Ljava/lang/String;
+Landroid/net/NetworkScorerAppData;->packageUid:I
+Landroid/net/NetworkSpecifier;-><init>()V
+Landroid/net/NetworkSpecifier;->assertValidFromUid(I)V
+Landroid/net/NetworkSpecifier;->satisfiedBy(Landroid/net/NetworkSpecifier;)Z
+Landroid/net/NetworkState;-><init>(Landroid/net/NetworkInfo;Landroid/net/LinkProperties;Landroid/net/NetworkCapabilities;Landroid/net/Network;Ljava/lang/String;Ljava/lang/String;)V
+Landroid/net/NetworkState;->EMPTY:Landroid/net/NetworkState;
+Landroid/net/NetworkState;->linkProperties:Landroid/net/LinkProperties;
+Landroid/net/NetworkState;->networkCapabilities:Landroid/net/NetworkCapabilities;
+Landroid/net/NetworkState;->networkId:Ljava/lang/String;
+Landroid/net/NetworkState;->networkInfo:Landroid/net/NetworkInfo;
+Landroid/net/NetworkState;->SANITY_CHECK_ROAMING:Z
+Landroid/net/NetworkState;->subscriberId:Ljava/lang/String;
+Landroid/net/NetworkStats$Entry;-><init>(JJJJJ)V
+Landroid/net/NetworkStats$Entry;-><init>(Ljava/lang/String;IIIIIIJJJJJ)V
+Landroid/net/NetworkStats$Entry;-><init>(Ljava/lang/String;IIIJJJJJ)V
+Landroid/net/NetworkStats$Entry;->add(Landroid/net/NetworkStats$Entry;)V
+Landroid/net/NetworkStats$Entry;->defaultNetwork:I
+Landroid/net/NetworkStats$Entry;->isEmpty()Z
+Landroid/net/NetworkStats$Entry;->isNegative()Z
+Landroid/net/NetworkStats$Entry;->metered:I
+Landroid/net/NetworkStats$Entry;->operations:J
+Landroid/net/NetworkStats$Entry;->roaming:I
+Landroid/net/NetworkStats$NonMonotonicObserver;->foundNonMonotonic(Landroid/net/NetworkStats;ILandroid/net/NetworkStats;ILjava/lang/Object;)V
+Landroid/net/NetworkStats$NonMonotonicObserver;->foundNonMonotonic(Landroid/net/NetworkStats;ILjava/lang/Object;)V
+Landroid/net/NetworkStats;->addIfaceValues(Ljava/lang/String;JJJJ)Landroid/net/NetworkStats;
+Landroid/net/NetworkStats;->addTrafficToApplications(ILjava/lang/String;Ljava/lang/String;Landroid/net/NetworkStats$Entry;Landroid/net/NetworkStats$Entry;)Landroid/net/NetworkStats$Entry;
+Landroid/net/NetworkStats;->addValues(Landroid/net/NetworkStats$Entry;)Landroid/net/NetworkStats;
+Landroid/net/NetworkStats;->addValues(Ljava/lang/String;IIIIIIJJJJJ)Landroid/net/NetworkStats;
+Landroid/net/NetworkStats;->addValues(Ljava/lang/String;IIIJJJJJ)Landroid/net/NetworkStats;
+Landroid/net/NetworkStats;->apply464xlatAdjustments(Landroid/net/NetworkStats;Landroid/net/NetworkStats;Ljava/util/Map;)V
+Landroid/net/NetworkStats;->apply464xlatAdjustments(Ljava/util/Map;)V
+Landroid/net/NetworkStats;->CLATD_INTERFACE_PREFIX:Ljava/lang/String;
+Landroid/net/NetworkStats;->clear()V
+Landroid/net/NetworkStats;->combineValues(Ljava/lang/String;IIIJJJJJ)Landroid/net/NetworkStats;
+Landroid/net/NetworkStats;->combineValues(Ljava/lang/String;IIJJJJJ)Landroid/net/NetworkStats;
+Landroid/net/NetworkStats;->deductTrafficFromVpnApp(ILjava/lang/String;Landroid/net/NetworkStats$Entry;)V
+Landroid/net/NetworkStats;->defaultNetworkToString(I)Ljava/lang/String;
+Landroid/net/NetworkStats;->DEFAULT_NETWORK_ALL:I
+Landroid/net/NetworkStats;->DEFAULT_NETWORK_NO:I
+Landroid/net/NetworkStats;->DEFAULT_NETWORK_YES:I
+Landroid/net/NetworkStats;->dump(Ljava/lang/String;Ljava/io/PrintWriter;)V
+Landroid/net/NetworkStats;->elapsedRealtime:J
+Landroid/net/NetworkStats;->filter(I[Ljava/lang/String;I)V
+Landroid/net/NetworkStats;->findIndex(Ljava/lang/String;IIIIII)I
+Landroid/net/NetworkStats;->findIndexHinted(Ljava/lang/String;IIIIIII)I
+Landroid/net/NetworkStats;->getElapsedRealtime()J
+Landroid/net/NetworkStats;->getElapsedRealtimeAge()J
+Landroid/net/NetworkStats;->getTotal(Landroid/net/NetworkStats$Entry;Ljava/util/HashSet;)Landroid/net/NetworkStats$Entry;
+Landroid/net/NetworkStats;->getTotal(Landroid/net/NetworkStats$Entry;Ljava/util/HashSet;IZ)Landroid/net/NetworkStats$Entry;
+Landroid/net/NetworkStats;->getTotalPackets()J
+Landroid/net/NetworkStats;->getUniqueIfaces()[Ljava/lang/String;
+Landroid/net/NetworkStats;->groupedByIface()Landroid/net/NetworkStats;
+Landroid/net/NetworkStats;->groupedByUid()Landroid/net/NetworkStats;
+Landroid/net/NetworkStats;->IFACE_ALL:Ljava/lang/String;
+Landroid/net/NetworkStats;->INTERFACES_ALL:[Ljava/lang/String;
+Landroid/net/NetworkStats;->internalSize()I
+Landroid/net/NetworkStats;->IPV4V6_HEADER_DELTA:I
+Landroid/net/NetworkStats;->meteredToString(I)Ljava/lang/String;
+Landroid/net/NetworkStats;->METERED_ALL:I
+Landroid/net/NetworkStats;->METERED_NO:I
+Landroid/net/NetworkStats;->METERED_YES:I
+Landroid/net/NetworkStats;->migrateTun(ILjava/lang/String;Ljava/lang/String;)Z
+Landroid/net/NetworkStats;->roamingToString(I)Ljava/lang/String;
+Landroid/net/NetworkStats;->ROAMING_ALL:I
+Landroid/net/NetworkStats;->ROAMING_NO:I
+Landroid/net/NetworkStats;->ROAMING_YES:I
+Landroid/net/NetworkStats;->setElapsedRealtime(J)V
+Landroid/net/NetworkStats;->setMatches(II)Z
+Landroid/net/NetworkStats;->setToCheckinString(I)Ljava/lang/String;
+Landroid/net/NetworkStats;->setToString(I)Ljava/lang/String;
+Landroid/net/NetworkStats;->setValues(ILandroid/net/NetworkStats$Entry;)V
+Landroid/net/NetworkStats;->SET_ALL:I
+Landroid/net/NetworkStats;->SET_DBG_VPN_IN:I
+Landroid/net/NetworkStats;->SET_DBG_VPN_OUT:I
+Landroid/net/NetworkStats;->SET_DEBUG_START:I
+Landroid/net/NetworkStats;->SET_DEFAULT:I
+Landroid/net/NetworkStats;->SET_FOREGROUND:I
+Landroid/net/NetworkStats;->spliceOperationsFrom(Landroid/net/NetworkStats;)V
+Landroid/net/NetworkStats;->STATS_PER_IFACE:I
+Landroid/net/NetworkStats;->STATS_PER_UID:I
+Landroid/net/NetworkStats;->subtract(Landroid/net/NetworkStats;)Landroid/net/NetworkStats;
+Landroid/net/NetworkStats;->subtract(Landroid/net/NetworkStats;Landroid/net/NetworkStats;Landroid/net/NetworkStats$NonMonotonicObserver;Ljava/lang/Object;)Landroid/net/NetworkStats;
+Landroid/net/NetworkStats;->subtract(Landroid/net/NetworkStats;Landroid/net/NetworkStats;Landroid/net/NetworkStats$NonMonotonicObserver;Ljava/lang/Object;Landroid/net/NetworkStats;)Landroid/net/NetworkStats;
+Landroid/net/NetworkStats;->TAG:Ljava/lang/String;
+Landroid/net/NetworkStats;->tagToString(I)Ljava/lang/String;
+Landroid/net/NetworkStats;->TAG_ALL:I
+Landroid/net/NetworkStats;->TAG_NONE:I
+Landroid/net/NetworkStats;->tunAdjustmentInit(ILjava/lang/String;Ljava/lang/String;Landroid/net/NetworkStats$Entry;Landroid/net/NetworkStats$Entry;)V
+Landroid/net/NetworkStats;->tunGetPool(Landroid/net/NetworkStats$Entry;Landroid/net/NetworkStats$Entry;)Landroid/net/NetworkStats$Entry;
+Landroid/net/NetworkStats;->tunSubtract(ILandroid/net/NetworkStats;Landroid/net/NetworkStats$Entry;)V
+Landroid/net/NetworkStats;->UID_ALL:I
+Landroid/net/NetworkStats;->withoutUids([I)Landroid/net/NetworkStats;
+Landroid/net/NetworkStatsHistory$DataStreamUtils;-><init>()V
+Landroid/net/NetworkStatsHistory$DataStreamUtils;->readFullLongArray(Ljava/io/DataInputStream;)[J
+Landroid/net/NetworkStatsHistory$DataStreamUtils;->readVarLong(Ljava/io/DataInputStream;)J
+Landroid/net/NetworkStatsHistory$DataStreamUtils;->readVarLongArray(Ljava/io/DataInputStream;)[J
+Landroid/net/NetworkStatsHistory$DataStreamUtils;->writeVarLong(Ljava/io/DataOutputStream;J)V
+Landroid/net/NetworkStatsHistory$DataStreamUtils;->writeVarLongArray(Ljava/io/DataOutputStream;[JI)V
+Landroid/net/NetworkStatsHistory$Entry;-><init>()V
+Landroid/net/NetworkStatsHistory$Entry;->activeTime:J
+Landroid/net/NetworkStatsHistory$Entry;->operations:J
+Landroid/net/NetworkStatsHistory$Entry;->UNKNOWN:J
+Landroid/net/NetworkStatsHistory$ParcelUtils;-><init>()V
+Landroid/net/NetworkStatsHistory$ParcelUtils;->readLongArray(Landroid/os/Parcel;)[J
+Landroid/net/NetworkStatsHistory$ParcelUtils;->writeLongArray(Landroid/os/Parcel;[JI)V
+Landroid/net/NetworkStatsHistory;-><init>(JI)V
+Landroid/net/NetworkStatsHistory;-><init>(JII)V
+Landroid/net/NetworkStatsHistory;-><init>(Landroid/net/NetworkStatsHistory;J)V
+Landroid/net/NetworkStatsHistory;-><init>(Ljava/io/DataInputStream;)V
+Landroid/net/NetworkStatsHistory;->activeTime:[J
+Landroid/net/NetworkStatsHistory;->addLong([JIJ)V
+Landroid/net/NetworkStatsHistory;->bucketCount:I
+Landroid/net/NetworkStatsHistory;->bucketDuration:J
+Landroid/net/NetworkStatsHistory;->bucketStart:[J
+Landroid/net/NetworkStatsHistory;->clear()V
+Landroid/net/NetworkStatsHistory;->dump(Lcom/android/internal/util/IndentingPrintWriter;Z)V
+Landroid/net/NetworkStatsHistory;->dumpCheckin(Ljava/io/PrintWriter;)V
+Landroid/net/NetworkStatsHistory;->ensureBuckets(JJ)V
+Landroid/net/NetworkStatsHistory;->estimateResizeBuckets(J)I
+Landroid/net/NetworkStatsHistory;->FIELD_ACTIVE_TIME:I
+Landroid/net/NetworkStatsHistory;->FIELD_ALL:I
+Landroid/net/NetworkStatsHistory;->FIELD_OPERATIONS:I
+Landroid/net/NetworkStatsHistory;->FIELD_RX_BYTES:I
+Landroid/net/NetworkStatsHistory;->FIELD_RX_PACKETS:I
+Landroid/net/NetworkStatsHistory;->FIELD_TX_BYTES:I
+Landroid/net/NetworkStatsHistory;->FIELD_TX_PACKETS:I
+Landroid/net/NetworkStatsHistory;->generateRandom(JJJ)V
+Landroid/net/NetworkStatsHistory;->generateRandom(JJJJJJJLjava/util/Random;)V
+Landroid/net/NetworkStatsHistory;->getBucketDuration()J
+Landroid/net/NetworkStatsHistory;->getIndexAfter(J)I
+Landroid/net/NetworkStatsHistory;->getLong([JIJ)J
+Landroid/net/NetworkStatsHistory;->getTotalBytes()J
+Landroid/net/NetworkStatsHistory;->insertBucket(IJ)V
+Landroid/net/NetworkStatsHistory;->intersects(JJ)Z
+Landroid/net/NetworkStatsHistory;->operations:[J
+Landroid/net/NetworkStatsHistory;->randomLong(Ljava/util/Random;JJ)J
+Landroid/net/NetworkStatsHistory;->recordData(JJJJ)V
+Landroid/net/NetworkStatsHistory;->recordData(JJLandroid/net/NetworkStats$Entry;)V
+Landroid/net/NetworkStatsHistory;->recordHistory(Landroid/net/NetworkStatsHistory;JJ)V
+Landroid/net/NetworkStatsHistory;->removeBucketsBefore(J)V
+Landroid/net/NetworkStatsHistory;->rxBytes:[J
+Landroid/net/NetworkStatsHistory;->rxPackets:[J
+Landroid/net/NetworkStatsHistory;->setLong([JIJ)V
+Landroid/net/NetworkStatsHistory;->setValues(ILandroid/net/NetworkStatsHistory$Entry;)V
+Landroid/net/NetworkStatsHistory;->totalBytes:J
+Landroid/net/NetworkStatsHistory;->txBytes:[J
+Landroid/net/NetworkStatsHistory;->txPackets:[J
+Landroid/net/NetworkStatsHistory;->VERSION_ADD_ACTIVE:I
+Landroid/net/NetworkStatsHistory;->VERSION_ADD_PACKETS:I
+Landroid/net/NetworkStatsHistory;->VERSION_INIT:I
+Landroid/net/NetworkStatsHistory;->writeToProto(Landroid/util/proto/ProtoOutputStream;J)V
+Landroid/net/NetworkStatsHistory;->writeToProto(Landroid/util/proto/ProtoOutputStream;J[JI)V
+Landroid/net/NetworkStatsHistory;->writeToStream(Ljava/io/DataOutputStream;)V
+Landroid/net/NetworkTemplate;-><init>(ILjava/lang/String;[Ljava/lang/String;Ljava/lang/String;)V
+Landroid/net/NetworkTemplate;-><init>(ILjava/lang/String;[Ljava/lang/String;Ljava/lang/String;III)V
+Landroid/net/NetworkTemplate;-><init>(Landroid/os/Parcel;)V
+Landroid/net/NetworkTemplate;->BACKUP_VERSION:I
+Landroid/net/NetworkTemplate;->buildTemplateBluetooth()Landroid/net/NetworkTemplate;
+Landroid/net/NetworkTemplate;->buildTemplateProxy()Landroid/net/NetworkTemplate;
+Landroid/net/NetworkTemplate;->buildTemplateWifi(Ljava/lang/String;)Landroid/net/NetworkTemplate;
+Landroid/net/NetworkTemplate;->forceAllNetworkTypes()V
+Landroid/net/NetworkTemplate;->getBytesForBackup()[B
+Landroid/net/NetworkTemplate;->getMatchRuleName(I)Ljava/lang/String;
+Landroid/net/NetworkTemplate;->getNetworkId()Ljava/lang/String;
+Landroid/net/NetworkTemplate;->getNetworkTemplateFromBackup(Ljava/io/DataInputStream;)Landroid/net/NetworkTemplate;
+Landroid/net/NetworkTemplate;->isKnownMatchRule(I)Z
+Landroid/net/NetworkTemplate;->isMatchRuleMobile()Z
+Landroid/net/NetworkTemplate;->isPersistable()Z
+Landroid/net/NetworkTemplate;->matches(Landroid/net/NetworkIdentity;)Z
+Landroid/net/NetworkTemplate;->matchesBluetooth(Landroid/net/NetworkIdentity;)Z
+Landroid/net/NetworkTemplate;->matchesDefaultNetwork(Landroid/net/NetworkIdentity;)Z
+Landroid/net/NetworkTemplate;->matchesEthernet(Landroid/net/NetworkIdentity;)Z
+Landroid/net/NetworkTemplate;->matchesMetered(Landroid/net/NetworkIdentity;)Z
+Landroid/net/NetworkTemplate;->matchesMobile(Landroid/net/NetworkIdentity;)Z
+Landroid/net/NetworkTemplate;->matchesMobileWildcard(Landroid/net/NetworkIdentity;)Z
+Landroid/net/NetworkTemplate;->matchesProxy(Landroid/net/NetworkIdentity;)Z
+Landroid/net/NetworkTemplate;->matchesRoaming(Landroid/net/NetworkIdentity;)Z
+Landroid/net/NetworkTemplate;->matchesSubscriberId(Ljava/lang/String;)Z
+Landroid/net/NetworkTemplate;->matchesWifi(Landroid/net/NetworkIdentity;)Z
+Landroid/net/NetworkTemplate;->matchesWifiWildcard(Landroid/net/NetworkIdentity;)Z
+Landroid/net/NetworkTemplate;->MATCH_BLUETOOTH:I
+Landroid/net/NetworkTemplate;->MATCH_ETHERNET:I
+Landroid/net/NetworkTemplate;->MATCH_MOBILE:I
+Landroid/net/NetworkTemplate;->MATCH_MOBILE_WILDCARD:I
+Landroid/net/NetworkTemplate;->MATCH_PROXY:I
+Landroid/net/NetworkTemplate;->MATCH_WIFI:I
+Landroid/net/NetworkTemplate;->MATCH_WIFI_WILDCARD:I
+Landroid/net/NetworkTemplate;->mDefaultNetwork:I
+Landroid/net/NetworkTemplate;->mMatchRule:I
+Landroid/net/NetworkTemplate;->mMatchSubscriberIds:[Ljava/lang/String;
+Landroid/net/NetworkTemplate;->mMetered:I
+Landroid/net/NetworkTemplate;->mNetworkId:Ljava/lang/String;
+Landroid/net/NetworkTemplate;->mRoaming:I
+Landroid/net/NetworkTemplate;->mSubscriberId:Ljava/lang/String;
+Landroid/net/NetworkTemplate;->sForceAllNetworkTypes:Z
+Landroid/net/NetworkTemplate;->TAG:Ljava/lang/String;
+Landroid/net/NetworkUtils;-><init>()V
+Landroid/net/NetworkUtils;->addressTypeMatches(Ljava/net/InetAddress;Ljava/net/InetAddress;)Z
+Landroid/net/NetworkUtils;->bindProcessToNetwork(I)Z
+Landroid/net/NetworkUtils;->bindProcessToNetworkForHostResolution(I)Z
+Landroid/net/NetworkUtils;->bindSocketToNetwork(II)I
+Landroid/net/NetworkUtils;->deduplicatePrefixSet(Ljava/util/TreeSet;)Ljava/util/TreeSet;
+Landroid/net/NetworkUtils;->getBoundNetworkForProcess()I
+Landroid/net/NetworkUtils;->getNetworkPart(Ljava/net/InetAddress;I)Ljava/net/InetAddress;
+Landroid/net/NetworkUtils;->hexToInet6Address(Ljava/lang/String;)Ljava/net/InetAddress;
+Landroid/net/NetworkUtils;->inetAddressToInt(Ljava/net/Inet4Address;)I
+Landroid/net/NetworkUtils;->makeStrings(Ljava/util/Collection;)[Ljava/lang/String;
+Landroid/net/NetworkUtils;->maskRawAddress([BI)V
+Landroid/net/NetworkUtils;->netmaskIntToPrefixLength(I)I
+Landroid/net/NetworkUtils;->parcelInetAddress(Landroid/os/Parcel;Ljava/net/InetAddress;I)V
+Landroid/net/NetworkUtils;->parseIpAndMask(Ljava/lang/String;)Landroid/util/Pair;
+Landroid/net/NetworkUtils;->protectFromVpn(I)Z
+Landroid/net/NetworkUtils;->queryUserAccess(II)Z
+Landroid/net/NetworkUtils;->routedIPv4AddressCount(Ljava/util/TreeSet;)J
+Landroid/net/NetworkUtils;->routedIPv6AddressCount(Ljava/util/TreeSet;)Ljava/math/BigInteger;
+Landroid/net/NetworkUtils;->setupRaSocket(Ljava/io/FileDescriptor;I)V
+Landroid/net/NetworkUtils;->TAG:Ljava/lang/String;
+Landroid/net/NetworkUtils;->unparcelInetAddress(Landroid/os/Parcel;)Ljava/net/InetAddress;
+Landroid/net/NetworkWatchlistManager;-><init>(Landroid/content/Context;)V
+Landroid/net/NetworkWatchlistManager;-><init>(Landroid/content/Context;Lcom/android/internal/net/INetworkWatchlistManager;)V
+Landroid/net/NetworkWatchlistManager;->getWatchlistConfigHash()[B
+Landroid/net/NetworkWatchlistManager;->mContext:Landroid/content/Context;
+Landroid/net/NetworkWatchlistManager;->mNetworkWatchlistManager:Lcom/android/internal/net/INetworkWatchlistManager;
+Landroid/net/NetworkWatchlistManager;->reloadWatchlist()V
+Landroid/net/NetworkWatchlistManager;->reportWatchlistIfNecessary()V
+Landroid/net/NetworkWatchlistManager;->SHARED_MEMORY_TAG:Ljava/lang/String;
+Landroid/net/NetworkWatchlistManager;->TAG:Ljava/lang/String;
+Landroid/net/ProxyInfo;-><init>(Landroid/net/ProxyInfo;)V
+Landroid/net/ProxyInfo;-><init>(Landroid/net/Uri;)V
+Landroid/net/ProxyInfo;-><init>(Landroid/net/Uri;I)V
+Landroid/net/ProxyInfo;-><init>(Ljava/lang/String;)V
+Landroid/net/ProxyInfo;-><init>(Ljava/lang/String;ILjava/lang/String;[Ljava/lang/String;)V
+Landroid/net/ProxyInfo;->getExclusionListAsString()Ljava/lang/String;
+Landroid/net/ProxyInfo;->getSocketAddress()Ljava/net/InetSocketAddress;
+Landroid/net/ProxyInfo;->isValid()Z
+Landroid/net/ProxyInfo;->LOCAL_EXCL_LIST:Ljava/lang/String;
+Landroid/net/ProxyInfo;->LOCAL_HOST:Ljava/lang/String;
+Landroid/net/ProxyInfo;->LOCAL_PORT:I
+Landroid/net/ProxyInfo;->makeProxy()Ljava/net/Proxy;
+Landroid/net/ProxyInfo;->mExclusionList:Ljava/lang/String;
+Landroid/net/ProxyInfo;->mHost:Ljava/lang/String;
+Landroid/net/ProxyInfo;->mPacFileUrl:Landroid/net/Uri;
+Landroid/net/ProxyInfo;->mParsedExclusionList:[Ljava/lang/String;
+Landroid/net/ProxyInfo;->mPort:I
+Landroid/net/ProxyInfo;->setExclusionList(Ljava/lang/String;)V
+Landroid/net/RouteInfo;-><init>(Landroid/net/IpPrefix;)V
+Landroid/net/RouteInfo;-><init>(Landroid/net/IpPrefix;I)V
+Landroid/net/RouteInfo;-><init>(Landroid/net/IpPrefix;Ljava/net/InetAddress;)V
+Landroid/net/RouteInfo;-><init>(Landroid/net/IpPrefix;Ljava/net/InetAddress;Ljava/lang/String;I)V
+Landroid/net/RouteInfo;-><init>(Landroid/net/LinkAddress;)V
+Landroid/net/RouteInfo;->getDestinationLinkAddress()Landroid/net/LinkAddress;
+Landroid/net/RouteInfo;->getType()I
+Landroid/net/RouteInfo;->isHostRoute()Z
+Landroid/net/RouteInfo;->isIPv4Default()Z
+Landroid/net/RouteInfo;->isIPv6Default()Z
+Landroid/net/RouteInfo;->makeHostRoute(Ljava/net/InetAddress;Ljava/lang/String;)Landroid/net/RouteInfo;
+Landroid/net/RouteInfo;->makeHostRoute(Ljava/net/InetAddress;Ljava/net/InetAddress;Ljava/lang/String;)Landroid/net/RouteInfo;
+Landroid/net/RouteInfo;->mDestination:Landroid/net/IpPrefix;
+Landroid/net/RouteInfo;->mHasGateway:Z
+Landroid/net/RouteInfo;->mInterface:Ljava/lang/String;
+Landroid/net/RouteInfo;->mType:I
+Landroid/net/RouteInfo;->RTN_THROW:I
+Landroid/net/RouteInfo;->RTN_UNICAST:I
+Landroid/net/RouteInfo;->RTN_UNREACHABLE:I
+Landroid/net/StaticIpConfiguration;-><init>(Landroid/net/StaticIpConfiguration;)V
+Landroid/net/StaticIpConfiguration;->clear()V
+Landroid/net/StaticIpConfiguration;->CREATOR:Landroid/os/Parcelable$Creator;
+Landroid/net/StaticIpConfiguration;->readFromParcel(Landroid/net/StaticIpConfiguration;Landroid/os/Parcel;)V
+Landroid/net/StaticIpConfiguration;->toLinkProperties(Ljava/lang/String;)Landroid/net/LinkProperties;
+Landroid/net/UidRange;-><init>(II)V
+Landroid/net/UidRange;->contains(I)Z
+Landroid/net/UidRange;->containsRange(Landroid/net/UidRange;)Z
+Landroid/net/UidRange;->count()I
+Landroid/net/UidRange;->createForUser(I)Landroid/net/UidRange;
+Landroid/net/UidRange;->CREATOR:Landroid/os/Parcelable$Creator;
+Landroid/net/UidRange;->getStartUser()I
+Landroid/net/UidRange;->start:I
+Landroid/net/UidRange;->stop:I
diff --git a/Tethering/apex/hiddenapi/hiddenapi-unsupported.txt b/Tethering/apex/hiddenapi/hiddenapi-unsupported.txt
new file mode 100644
index 0000000..f89906f
--- /dev/null
+++ b/Tethering/apex/hiddenapi/hiddenapi-unsupported.txt
@@ -0,0 +1,10 @@
+Landroid/net/IConnectivityManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Landroid/net/IConnectivityManager$Stub$Proxy;->getActiveLinkProperties()Landroid/net/LinkProperties;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getActiveNetworkInfo()Landroid/net/NetworkInfo;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getAllNetworkInfo()[Landroid/net/NetworkInfo;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getAllNetworks()[Landroid/net/Network;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getTetherableIfaces()[Ljava/lang/String;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getTetherableUsbRegexs()[Ljava/lang/String;
+Landroid/net/IConnectivityManager$Stub$Proxy;->getTetheredIfaces()[Ljava/lang/String;
+Landroid/net/IConnectivityManager$Stub$Proxy;->mRemote:Landroid/os/IBinder;
+Landroid/net/IConnectivityManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/IConnectivityManager;
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 33f1c29..a33af61 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
@@ -33,6 +33,8 @@
import com.android.networkstack.tethering.Tether4Value;
import com.android.networkstack.tethering.TetherStatsValue;
+import java.util.function.BiConsumer;
+
/**
* Bpf coordinator class for API shims.
*/
@@ -161,6 +163,12 @@
}
@Override
+ public void tetherOffloadRuleForEach(boolean downstream,
+ @NonNull BiConsumer<Tether4Key, Tether4Value> action) {
+ /* no op */
+ }
+
+ @Override
public boolean attachProgram(String iface, boolean downstream) {
/* no op */
return true;
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 74ddcbc..611c828 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
@@ -47,6 +47,7 @@
import java.io.FileDescriptor;
import java.io.IOException;
+import java.util.function.BiConsumer;
/**
* Bpf coordinator class for API shims.
@@ -380,10 +381,7 @@
try {
if (downstream) {
- if (!mBpfDownstream4Map.deleteEntry(key)) {
- mLog.e("Could not delete entry (key: " + key + ")");
- return false;
- }
+ if (!mBpfDownstream4Map.deleteEntry(key)) return false; // Rule did not exist
// Decrease the rule count while a deleting rule is not using a given upstream
// interface anymore.
@@ -401,19 +399,32 @@
mRule4CountOnUpstream.put(upstreamIfindex, count);
}
} else {
- mBpfUpstream4Map.deleteEntry(key);
+ if (!mBpfUpstream4Map.deleteEntry(key)) return false; // Rule did not exist
}
} catch (ErrnoException e) {
- // Silent if the rule did not exist.
- if (e.errno != OsConstants.ENOENT) {
- mLog.e("Could not delete entry: ", e);
- return false;
- }
+ mLog.e("Could not delete entry (key: " + key + ")", e);
+ return false;
}
return true;
}
@Override
+ public void tetherOffloadRuleForEach(boolean downstream,
+ @NonNull BiConsumer<Tether4Key, Tether4Value> action) {
+ if (!isInitialized()) return;
+
+ try {
+ if (downstream) {
+ mBpfDownstream4Map.forEach(action);
+ } else {
+ mBpfUpstream4Map.forEach(action);
+ }
+ } catch (ErrnoException e) {
+ mLog.e("Could not iterate map: ", e);
+ }
+ }
+
+ @Override
public boolean attachProgram(String iface, boolean downstream) {
if (!isInitialized()) return false;
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 8a7a49c..08ab9ca 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
@@ -28,6 +28,8 @@
import com.android.networkstack.tethering.Tether4Value;
import com.android.networkstack.tethering.TetherStatsValue;
+import java.util.function.BiConsumer;
+
/**
* Bpf coordinator class for API shims.
*/
@@ -145,10 +147,25 @@
/**
* Deletes a tethering IPv4 offload rule from the appropriate BPF map.
+ *
+ * @param downstream true if downstream, false if upstream.
+ * @param key the key to delete.
+ * @return true iff the map was modified, false if the key did not exist or there was an error.
*/
public abstract boolean tetherOffloadRuleRemove(boolean downstream, @NonNull Tether4Key key);
/**
+ * Iterate through the map and handle each key -> value retrieved base on the given BiConsumer.
+ *
+ * @param downstream true if downstream, false if upstream.
+ * @param action represents the action for each key -> value. The entry deletion is not
+ * allowed and use #tetherOffloadRuleRemove instead.
+ */
+ @Nullable
+ public abstract void tetherOffloadRuleForEach(boolean downstream,
+ @NonNull BiConsumer<Tether4Key, Tether4Value> action);
+
+ /**
* Whether there is currently any IPv4 rule on the specified upstream.
*/
public abstract boolean isAnyIpv4RuleOnUpstream(int ifIndex);
diff --git a/Tethering/src/android/net/ip/IpServer.java b/Tethering/src/android/net/ip/IpServer.java
index 3428c1d..822bdf6 100644
--- a/Tethering/src/android/net/ip/IpServer.java
+++ b/Tethering/src/android/net/ip/IpServer.java
@@ -596,6 +596,7 @@
// into calls to InterfaceController, shared with startIPv4().
mInterfaceCtrl.clearIPv4Address();
mPrivateAddressCoordinator.releaseDownstream(this);
+ mBpfCoordinator.tetherOffloadClientClear(this);
mIpv4Address = null;
mStaticIpv4ServerAddr = null;
mStaticIpv4ClientAddr = null;
@@ -949,7 +950,6 @@
if (e.isValid()) {
mBpfCoordinator.tetherOffloadClientAdd(this, clientInfo);
} else {
- // TODO: Delete all related offload rules which are using this client.
mBpfCoordinator.tetherOffloadClientRemove(this, clientInfo);
}
}
@@ -1283,6 +1283,16 @@
super.exit();
}
+ // Note that IPv4 offload rules cleanup is implemented in BpfCoordinator while upstream
+ // state is null or changed because IPv4 and IPv6 tethering have different code flow
+ // and behaviour. While upstream is switching from offload supported interface to
+ // offload non-supportted interface, event CMD_TETHER_CONNECTION_CHANGED calls
+ // #cleanupUpstreamInterface but #cleanupUpstream because new UpstreamIfaceSet is not null.
+ // This case won't happen in IPv6 tethering because IPv6 tethering upstream state is
+ // reported by IPv6TetheringCoordinator. #cleanupUpstream is also called by unwirding
+ // adding NAT failure. In that case, the IPv4 offload rules are removed by #stopIPv4
+ // in the state machine. Once there is any case out whish is not covered by previous cases,
+ // probably consider clearing rules in #cleanupUpstream as well.
private void cleanupUpstream() {
if (mUpstreamIfaceSet == null) return;
diff --git a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
index 4a05c9f..56dc69c 100644
--- a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
+++ b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
@@ -34,7 +34,6 @@
import android.app.usage.NetworkStatsManager;
import android.net.INetd;
-import android.net.LinkProperties;
import android.net.MacAddress;
import android.net.NetworkStats;
import android.net.NetworkStats.Entry;
@@ -42,7 +41,9 @@
import android.net.ip.ConntrackMonitor;
import android.net.ip.ConntrackMonitor.ConntrackEventConsumer;
import android.net.ip.IpServer;
+import android.net.netlink.ConntrackMessage;
import android.net.netlink.NetlinkConstants;
+import android.net.netlink.NetlinkSocket;
import android.net.netstats.provider.NetworkStatsProvider;
import android.net.util.InterfaceParams;
import android.net.util.SharedLog;
@@ -50,7 +51,9 @@
import android.os.Handler;
import android.os.SystemClock;
import android.system.ErrnoException;
+import android.system.OsConstants;
import android.text.TextUtils;
+import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
@@ -69,6 +72,7 @@
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
@@ -120,6 +124,13 @@
}
@VisibleForTesting
+ static final int POLLING_CONNTRACK_TIMEOUT_MS = 60_000;
+ @VisibleForTesting
+ static final int NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED = 432000;
+ @VisibleForTesting
+ static final int NF_CONNTRACK_UDP_TIMEOUT_STREAM = 180;
+
+ @VisibleForTesting
enum StatsType {
STATS_PER_IFACE,
STATS_PER_UID,
@@ -228,12 +239,22 @@
// BpfCoordinatorTest needs predictable iteration order.
private final Set<Integer> mDeviceMapSet = new LinkedHashSet<>();
+ // Tracks the last IPv4 upstream index. Support single upstream only.
+ // TODO: Support multi-upstream interfaces.
+ private int mLastIPv4UpstreamIfindex = 0;
+
// Runnable that used by scheduling next polling of stats.
- private final Runnable mScheduledPollingTask = () -> {
+ private final Runnable mScheduledPollingStats = () -> {
updateForwardedStats();
maybeSchedulePollingStats();
};
+ // Runnable that used by scheduling next polling of conntrack timeout.
+ private final Runnable mScheduledPollingConntrackTimeout = () -> {
+ maybeRefreshConntrackTimeout();
+ maybeSchedulePollingConntrackTimeout();
+ };
+
// TODO: add BpfMap<TetherDownstream64Key, TetherDownstream64Value> retrieving function.
@VisibleForTesting
public abstract static class Dependencies {
@@ -263,13 +284,19 @@
}
/**
+ * Represents an estimate of elapsed time since boot in nanoseconds.
+ */
+ public long elapsedRealtimeNanos() {
+ return SystemClock.elapsedRealtimeNanos();
+ }
+
+ /**
* Check OS Build at least S.
*
* TODO: move to BpfCoordinatorShim once the test doesn't need the mocked OS build for
* testing different code flows concurrently.
*/
public boolean isAtLeastS() {
- // TODO: consider using ShimUtils.isAtLeastS.
return SdkLevel.isAtLeastS();
}
@@ -407,6 +434,7 @@
mPollingStarted = true;
maybeSchedulePollingStats();
+ maybeSchedulePollingConntrackTimeout();
mLog.i("Polling started");
}
@@ -422,9 +450,13 @@
public void stopPolling() {
if (!mPollingStarted) return;
- // Stop scheduled polling tasks and poll the latest stats from BPF maps.
- if (mHandler.hasCallbacks(mScheduledPollingTask)) {
- mHandler.removeCallbacks(mScheduledPollingTask);
+ // Stop scheduled polling conntrack timeout.
+ if (mHandler.hasCallbacks(mScheduledPollingConntrackTimeout)) {
+ mHandler.removeCallbacks(mScheduledPollingConntrackTimeout);
+ }
+ // Stop scheduled polling stats and poll the latest stats from BPF maps.
+ if (mHandler.hasCallbacks(mScheduledPollingStats)) {
+ mHandler.removeCallbacks(mScheduledPollingStats);
}
updateForwardedStats();
mPollingStarted = false;
@@ -576,6 +608,7 @@
/**
* Clear all forwarding rules for a given downstream.
* Note that this can be only called on handler thread.
+ * TODO: rename to tetherOffloadRuleClear6 because of IPv6 only.
*/
public void tetherOffloadRuleClear(@NonNull final IpServer ipServer) {
if (!isUsingBpf()) return;
@@ -647,6 +680,7 @@
/**
* Add downstream client.
+ * Note that this can be only called on handler thread.
*/
public void tetherOffloadClientAdd(@NonNull final IpServer ipServer,
@NonNull final ClientInfo client) {
@@ -661,54 +695,180 @@
}
/**
- * Remove downstream client.
+ * Remove a downstream client and its rules if any.
+ * Note that this can be only called on handler thread.
*/
public void tetherOffloadClientRemove(@NonNull final IpServer ipServer,
@NonNull final ClientInfo client) {
if (!isUsingBpf()) return;
+ // No clients on the downstream, return early.
HashMap<Inet4Address, ClientInfo> clients = mTetherClients.get(ipServer);
if (clients == null) return;
- // If no rule is removed, return early. Avoid unnecessary work on a non-existent rule
- // which may have never been added or removed already.
+ // No client is removed, return early.
if (clients.remove(client.clientAddress) == null) return;
- // Remove the downstream entry if it has no more rule.
+ // Remove the client's rules. Removing the client implies that its rules are not used
+ // anymore.
+ tetherOffloadRuleClear(client);
+
+ // Remove the downstream entry if it has no more client.
if (clients.isEmpty()) {
mTetherClients.remove(ipServer);
}
}
/**
- * Call when UpstreamNetworkState may be changed.
- * If upstream has ipv4 for tethering, update this new UpstreamNetworkState to map. The
- * upstream interface index and its address mapping is prepared for building IPv4
- * offload rule.
- *
- * TODO: Delete the unused upstream interface mapping.
- * TODO: Support ether ip upstream interface.
+ * Clear all downstream clients and their rules if any.
+ * Note that this can be only called on handler thread.
*/
- public void addUpstreamIfindexToMap(LinkProperties lp) {
- if (!mPollingStarted) return;
+ public void tetherOffloadClientClear(@NonNull final IpServer ipServer) {
+ if (!isUsingBpf()) return;
+
+ final HashMap<Inet4Address, ClientInfo> clients = mTetherClients.get(ipServer);
+ if (clients == null) return;
+
+ // Need to build a client list because the client map may be changed in the iteration.
+ for (final ClientInfo c : new ArrayList<ClientInfo>(clients.values())) {
+ tetherOffloadClientRemove(ipServer, c);
+ }
+ }
+
+ /**
+ * Clear all forwarding IPv4 rules for a given client.
+ * Note that this can be only called on handler thread.
+ */
+ private void tetherOffloadRuleClear(@NonNull final ClientInfo clientInfo) {
+ // TODO: consider removing the rules in #tetherOffloadRuleForEach once BpfMap#forEach
+ // can guarantee that deleting some pass-in rules in the BPF map iteration can still
+ // walk through every entry.
+ final Inet4Address clientAddr = clientInfo.clientAddress;
+ final Set<Integer> upstreamIndiceSet = new ArraySet<Integer>();
+ final Set<Tether4Key> deleteUpstreamRuleKeys = new ArraySet<Tether4Key>();
+ final Set<Tether4Key> deleteDownstreamRuleKeys = new ArraySet<Tether4Key>();
+
+ // Find the rules which are related with the given client.
+ mBpfCoordinatorShim.tetherOffloadRuleForEach(UPSTREAM, (k, v) -> {
+ if (Arrays.equals(k.src4, clientAddr.getAddress())) {
+ deleteUpstreamRuleKeys.add(k);
+ }
+ });
+ mBpfCoordinatorShim.tetherOffloadRuleForEach(DOWNSTREAM, (k, v) -> {
+ if (Arrays.equals(v.dst46, toIpv4MappedAddressBytes(clientAddr))) {
+ deleteDownstreamRuleKeys.add(k);
+ upstreamIndiceSet.add((int) k.iif);
+ }
+ });
+
+ // The rules should be paired on upstream and downstream map because they are added by
+ // conntrack events which have bidirectional information.
+ // TODO: Consider figuring out a way to fix. Probably delete all rules to fallback.
+ if (deleteUpstreamRuleKeys.size() != deleteDownstreamRuleKeys.size()) {
+ Log.wtf(TAG, "The deleting rule numbers are different on upstream4 and downstream4 ("
+ + "upstream: " + deleteUpstreamRuleKeys.size() + ", "
+ + "downstream: " + deleteDownstreamRuleKeys.size() + ").");
+ return;
+ }
+
+ // Delete the rules which are related with the given client.
+ for (final Tether4Key k : deleteUpstreamRuleKeys) {
+ mBpfCoordinatorShim.tetherOffloadRuleRemove(UPSTREAM, k);
+ }
+ for (final Tether4Key k : deleteDownstreamRuleKeys) {
+ mBpfCoordinatorShim.tetherOffloadRuleRemove(DOWNSTREAM, k);
+ }
+
+ // Cleanup each upstream interface by a set which avoids duplicated work on the same
+ // upstream interface. Cleaning up the same interface twice (or more) here may raise
+ // an exception because all related information were removed in the first deletion.
+ for (final int upstreamIndex : upstreamIndiceSet) {
+ maybeClearLimit(upstreamIndex);
+ }
+ }
+
+ /**
+ * Clear all forwarding IPv4 rules for a given downstream. Needed because the client may still
+ * connect on the downstream but the existing rules are not required anymore. Ex: upstream
+ * changed.
+ */
+ private void tetherOffloadRule4Clear(@NonNull final IpServer ipServer) {
+ if (!isUsingBpf()) return;
+
+ final HashMap<Inet4Address, ClientInfo> clients = mTetherClients.get(ipServer);
+ if (clients == null) return;
+
+ // The value should be unique as its key because currently the key was using from its
+ // client address of ClientInfo. See #tetherOffloadClientAdd.
+ for (final ClientInfo client : clients.values()) {
+ tetherOffloadRuleClear(client);
+ }
+ }
+
+ private boolean isValidUpstreamIpv4Address(@NonNull final InetAddress addr) {
+ if (!(addr instanceof Inet4Address)) return false;
+ Inet4Address v4 = (Inet4Address) addr;
+ if (v4.isAnyLocalAddress() || v4.isLinkLocalAddress()
+ || v4.isLoopbackAddress() || v4.isMulticastAddress()) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Call when UpstreamNetworkState may be changed.
+ * If upstream has ipv4 for tethering, update this new UpstreamNetworkState
+ * to BpfCoordinator for building upstream interface index mapping. Otherwise,
+ * clear the all existing rules if any.
+ *
+ * Note that this can be only called on handler thread.
+ */
+ public void updateUpstreamNetworkState(UpstreamNetworkState ns) {
+ if (!isUsingBpf()) return;
+
+ int upstreamIndex = 0;
// This will not work on a network that is using 464xlat because hasIpv4Address will not be
// true.
// TODO: need to consider 464xlat.
- if (lp == null || !lp.hasIpv4Address()) return;
+ if (ns != null && ns.linkProperties != null && ns.linkProperties.hasIpv4Address()) {
+ // TODO: support ether ip upstream interface.
+ final InterfaceParams params = mDeps.getInterfaceParams(
+ ns.linkProperties.getInterfaceName());
+ if (params != null && !params.hasMacAddress /* raw ip upstream only */) {
+ upstreamIndex = params.index;
+ }
+ }
+ if (mLastIPv4UpstreamIfindex == upstreamIndex) return;
- // Support raw ip upstream interface only.
- final InterfaceParams params = mDeps.getInterfaceParams(lp.getInterfaceName());
- if (params == null || params.hasMacAddress) return;
+ // Clear existing rules if upstream interface is changed. The existing rules should be
+ // cleared before upstream index mapping is cleared. It can avoid that ipServer or
+ // conntrack event may use the non-existing upstream interfeace index to build a removing
+ // key while removeing the rules. Can't notify each IpServer to clear the rules as
+ // IPv6TetheringCoordinator#updateUpstreamNetworkState because the IpServer may not
+ // handle the upstream changing notification before changing upstream index mapping.
+ if (mLastIPv4UpstreamIfindex != 0) {
+ // Clear all forwarding IPv4 rules for all downstreams.
+ for (final IpServer ipserver : mTetherClients.keySet()) {
+ tetherOffloadRule4Clear(ipserver);
+ }
+ }
- Collection<InetAddress> addresses = lp.getAddresses();
- for (InetAddress addr: addresses) {
- if (addr instanceof Inet4Address) {
- Inet4Address i4addr = (Inet4Address) addr;
- if (!i4addr.isAnyLocalAddress() && !i4addr.isLinkLocalAddress()
- && !i4addr.isLoopbackAddress() && !i4addr.isMulticastAddress()) {
- mIpv4UpstreamIndices.put(i4addr, params.index);
- }
+ // Don't update mLastIPv4UpstreamIfindex before clearing existing rules if any. Need that
+ // to tell if it is required to clean the out-of-date rules.
+ mLastIPv4UpstreamIfindex = upstreamIndex;
+
+ // If link properties are valid, build the upstream information mapping. Otherwise, clear
+ // the upstream interface index mapping, to ensure that any conntrack events that arrive
+ // after the upstream is lost do not incorrectly add rules pointing at the upstream.
+ if (upstreamIndex == 0) {
+ mIpv4UpstreamIndices.clear();
+ return;
+ }
+ Collection<InetAddress> addresses = ns.linkProperties.getAddresses();
+ for (final InetAddress addr: addresses) {
+ if (isValidUpstreamIpv4Address(addr)) {
+ mIpv4UpstreamIndices.put((Inet4Address) addr, upstreamIndex);
}
}
}
@@ -793,6 +953,24 @@
dumpDevmap(pw);
pw.decreaseIndent();
+ pw.println("Client Information:");
+ pw.increaseIndent();
+ if (mTetherClients.isEmpty()) {
+ pw.println("<empty>");
+ } else {
+ pw.println(mTetherClients.toString());
+ }
+ pw.decreaseIndent();
+
+ pw.println("IPv4 Upstream Indices:");
+ pw.increaseIndent();
+ if (mIpv4UpstreamIndices.isEmpty()) {
+ pw.println("<empty>");
+ } else {
+ pw.println(mIpv4UpstreamIndices.toString());
+ }
+ pw.decreaseIndent();
+
pw.println();
pw.println("Forwarding counters:");
pw.increaseIndent();
@@ -891,11 +1069,12 @@
throw new AssertionError("IP address array not valid IPv4 address!");
}
- final long ageMs = (now - value.lastUsed) / 1_000_000;
- return String.format("[%s] %d(%s) %s:%d -> %d(%s) %s:%d -> %s:%d [%s] %dms",
+ final String ageStr = (value.lastUsed == 0) ? "-"
+ : String.format("%dms", (now - value.lastUsed) / 1_000_000);
+ return String.format("[%s] %d(%s) %s:%d -> %d(%s) %s:%d -> %s:%d [%s] %s",
key.dstMac, key.iif, getIfName(key.iif), src4, key.srcPort,
value.oif, getIfName(value.oif),
- public4, publicPort, dst4, value.dstPort, value.ethDstMac, ageMs);
+ public4, publicPort, dst4, value.dstPort, value.ethDstMac, ageStr);
}
private void dumpIpv4ForwardingRuleMap(long now, boolean downstream,
@@ -971,14 +1150,14 @@
return;
}
if (map.isEmpty()) {
- pw.println("No interface index");
+ pw.println("<empty>");
return;
}
pw.println("ifindex (iface) -> ifindex (iface)");
pw.increaseIndent();
map.forEach((k, v) -> {
// Only get upstream interface name. Just do the best to make the index readable.
- // TODO: get downstream interface name because the index is either upstrema or
+ // TODO: get downstream interface name because the index is either upstream or
// downstream interface in dev map.
pw.println(String.format("%d (%s) -> %d (%s)", k.ifIndex, getIfName(k.ifIndex),
v.ifIndex, getIfName(v.ifIndex)));
@@ -1248,12 +1427,99 @@
return null;
}
- // Support raw ip only.
- // TODO: add ether ip support.
+ @NonNull
+ private byte[] toIpv4MappedAddressBytes(Inet4Address ia4) {
+ final byte[] addr4 = ia4.getAddress();
+ final byte[] addr6 = new byte[16];
+ addr6[10] = (byte) 0xff;
+ addr6[11] = (byte) 0xff;
+ addr6[12] = addr4[0];
+ addr6[13] = addr4[1];
+ addr6[14] = addr4[2];
+ addr6[15] = addr4[3];
+ return addr6;
+ }
+
+ @Nullable
+ private Inet4Address ipv4MappedAddressBytesToIpv4Address(final byte[] addr46) {
+ if (addr46.length != 16) return null;
+ if (addr46[0] != 0 || addr46[1] != 0 || addr46[2] != 0 || addr46[3] != 0
+ || addr46[4] != 0 || addr46[5] != 0 || addr46[6] != 0 || addr46[7] != 0
+ || addr46[8] != 0 && addr46[9] != 0 || (addr46[10] & 0xff) != 0xff
+ || (addr46[11] & 0xff) != 0xff) {
+ return null;
+ }
+
+ final byte[] addr4 = new byte[4];
+ addr4[0] = addr46[12];
+ addr4[1] = addr46[13];
+ addr4[2] = addr46[14];
+ addr4[3] = addr46[15];
+
+ return parseIPv4Address(addr4);
+ }
+
// TODO: parse CTA_PROTOINFO of conntrack event in ConntrackMonitor. For TCP, only add rules
// while TCP status is established.
@VisibleForTesting
class BpfConntrackEventConsumer implements ConntrackEventConsumer {
+ // The upstream4 and downstream4 rules are built as the following tables. Only raw ip
+ // upstream interface is supported. Note that the field "lastUsed" is only updated by
+ // BPF program which records the last used time for a given rule.
+ // TODO: support ether ip upstream interface.
+ //
+ // NAT network topology:
+ //
+ // public network (rawip) private network
+ // | UE |
+ // +------------+ V +------------+------------+ V +------------+
+ // | Sever +---------+ Upstream | Downstream +---------+ Client |
+ // +------------+ +------------+------------+ +------------+
+ //
+ // upstream4 key and value:
+ //
+ // +------+------------------------------------------------+
+ // | | TetherUpstream4Key |
+ // +------+------+------+------+------+------+------+------+
+ // |field |iif |dstMac|l4prot|src4 |dst4 |srcPor|dstPor|
+ // | | | |o | | |t |t |
+ // +------+------+------+------+------+------+------+------+
+ // |value |downst|downst|tcp/ |client|server|client|server|
+ // | |ream |ream |udp | | | | |
+ // +------+------+------+------+------+------+------+------+
+ //
+ // +------+---------------------------------------------------------------------+
+ // | | TetherUpstream4Value |
+ // +------+------+------+------+------+------+------+------+------+------+------+
+ // |field |oif |ethDst|ethSrc|ethPro|pmtu |src46 |dst46 |srcPor|dstPor|lastUs|
+ // | | |mac |mac |to | | | |t |t |ed |
+ // +------+------+------+------+------+------+------+------+------+------+------+
+ // |value |upstre|-- |-- |ETH_P_|1500 |upstre|server|upstre|server|-- |
+ // | |am | | |IP | |am | |am | | |
+ // +------+------+------+------+------+------+------+------+------+------+------+
+ //
+ // downstream4 key and value:
+ //
+ // +------+------------------------------------------------+
+ // | | TetherDownstream4Key |
+ // +------+------+------+------+------+------+------+------+
+ // |field |iif |dstMac|l4prot|src4 |dst4 |srcPor|dstPor|
+ // | | | |o | | |t |t |
+ // +------+------+------+------+------+------+------+------+
+ // |value |upstre|-- |tcp/ |server|upstre|server|upstre|
+ // | |am | |udp | |am | |am |
+ // +------+------+------+------+------+------+------+------+
+ //
+ // +------+---------------------------------------------------------------------+
+ // | | TetherDownstream4Value |
+ // +------+------+------+------+------+------+------+------+------+------+------+
+ // |field |oif |ethDst|ethSrc|ethPro|pmtu |src46 |dst46 |srcPor|dstPor|lastUs|
+ // | | |mac |mac |to | | | |t |t |ed |
+ // +------+------+------+------+------+------+------+------+------+------+------+
+ // |value |downst|client|downst|ETH_P_|1500 |server|client|server|client|-- |
+ // | |ream | |ream |IP | | | | | | |
+ // +------+------+------+------+------+------+------+------+------+------+------+
+ //
@NonNull
private Tether4Key makeTetherUpstream4Key(
@NonNull ConntrackEvent e, @NonNull ClientInfo c) {
@@ -1292,19 +1558,6 @@
0 /* lastUsed, filled by bpf prog only */);
}
- @NonNull
- private byte[] toIpv4MappedAddressBytes(Inet4Address ia4) {
- final byte[] addr4 = ia4.getAddress();
- final byte[] addr6 = new byte[16];
- addr6[10] = (byte) 0xff;
- addr6[11] = (byte) 0xff;
- addr6[12] = addr4[0];
- addr6[13] = addr4[1];
- addr6[14] = addr4[2];
- addr6[15] = addr4[3];
- return addr6;
- }
-
public void accept(ConntrackEvent e) {
final ClientInfo tetherClient = getClientInfo(e.tupleOrig.srcIp);
if (tetherClient == null) return;
@@ -1318,8 +1571,23 @@
if (e.msgType == (NetlinkConstants.NFNL_SUBSYS_CTNETLINK << 8
| NetlinkConstants.IPCTNL_MSG_CT_DELETE)) {
- mBpfCoordinatorShim.tetherOffloadRuleRemove(UPSTREAM, upstream4Key);
- mBpfCoordinatorShim.tetherOffloadRuleRemove(DOWNSTREAM, downstream4Key);
+ final boolean deletedUpstream = mBpfCoordinatorShim.tetherOffloadRuleRemove(
+ UPSTREAM, upstream4Key);
+ final boolean deletedDownstream = mBpfCoordinatorShim.tetherOffloadRuleRemove(
+ DOWNSTREAM, downstream4Key);
+
+ if (!deletedUpstream && !deletedDownstream) {
+ // The rules may have been already removed by losing client or losing upstream.
+ return;
+ }
+
+ if (deletedUpstream != deletedDownstream) {
+ Log.wtf(TAG, "The bidirectional rules should be removed concurrently ("
+ + "upstream: " + deletedUpstream
+ + ", downstream: " + deletedDownstream + ")");
+ return;
+ }
+
maybeClearLimit(upstreamIndex);
return;
}
@@ -1585,14 +1853,89 @@
return Math.max(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS, configInterval);
}
+ @Nullable
+ private Inet4Address parseIPv4Address(byte[] addrBytes) {
+ try {
+ final InetAddress ia = Inet4Address.getByAddress(addrBytes);
+ if (ia instanceof Inet4Address) return (Inet4Address) ia;
+ } catch (UnknownHostException | IllegalArgumentException e) {
+ mLog.e("Failed to parse IPv4 address: " + e);
+ }
+ return null;
+ }
+
+ // Update CTA_TUPLE_ORIG timeout for a given conntrack entry. Note that there will also be
+ // coming a conntrack event to notify updated timeout.
+ private void updateConntrackTimeout(byte proto, Inet4Address src4, short srcPort,
+ Inet4Address dst4, short dstPort) {
+ if (src4 == null || dst4 == null) return;
+
+ // TODO: consider acquiring the timeout setting from nf_conntrack_* variables.
+ // - proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established
+ // - proc/sys/net/netfilter/nf_conntrack_udp_timeout_stream
+ // See kernel document nf_conntrack-sysctl.txt.
+ final int timeoutSec = (proto == OsConstants.IPPROTO_TCP)
+ ? NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED
+ : NF_CONNTRACK_UDP_TIMEOUT_STREAM;
+ final byte[] msg = ConntrackMessage.newIPv4TimeoutUpdateRequest(
+ proto, src4, (int) srcPort, dst4, (int) dstPort, timeoutSec);
+ try {
+ NetlinkSocket.sendOneShotKernelMessage(OsConstants.NETLINK_NETFILTER, msg);
+ } catch (ErrnoException e) {
+ mLog.e("Error updating conntrack entry ("
+ + "proto: " + proto + ", "
+ + "src4: " + src4 + ", "
+ + "srcPort: " + Short.toUnsignedInt(srcPort) + ", "
+ + "dst4: " + dst4 + ", "
+ + "dstPort: " + Short.toUnsignedInt(dstPort) + "), "
+ + "msg: " + NetlinkConstants.hexify(msg) + ", "
+ + "e: " + e);
+ }
+ }
+
+ private void maybeRefreshConntrackTimeout() {
+ final long now = mDeps.elapsedRealtimeNanos();
+
+ // Reverse the source and destination {address, port} from downstream value because
+ // #updateConntrackTimeout refresh the timeout of netlink attribute CTA_TUPLE_ORIG
+ // which is opposite direction for downstream map value.
+ mBpfCoordinatorShim.tetherOffloadRuleForEach(DOWNSTREAM, (k, v) -> {
+ if ((now - v.lastUsed) / 1_000_000 < POLLING_CONNTRACK_TIMEOUT_MS) {
+ updateConntrackTimeout((byte) k.l4proto,
+ ipv4MappedAddressBytesToIpv4Address(v.dst46), (short) v.dstPort,
+ ipv4MappedAddressBytesToIpv4Address(v.src46), (short) v.srcPort);
+ }
+ });
+
+ // TODO: Consider ignoring TCP traffic on upstream and monitor on downstream only
+ // because TCP is a bidirectional traffic. Probably don't need to extend timeout by
+ // both directions for TCP.
+ mBpfCoordinatorShim.tetherOffloadRuleForEach(UPSTREAM, (k, v) -> {
+ if ((now - v.lastUsed) / 1_000_000 < POLLING_CONNTRACK_TIMEOUT_MS) {
+ updateConntrackTimeout((byte) k.l4proto, parseIPv4Address(k.src4),
+ (short) k.srcPort, parseIPv4Address(k.dst4), (short) k.dstPort);
+ }
+ });
+ }
+
private void maybeSchedulePollingStats() {
if (!mPollingStarted) return;
- if (mHandler.hasCallbacks(mScheduledPollingTask)) {
- mHandler.removeCallbacks(mScheduledPollingTask);
+ if (mHandler.hasCallbacks(mScheduledPollingStats)) {
+ mHandler.removeCallbacks(mScheduledPollingStats);
}
- mHandler.postDelayed(mScheduledPollingTask, getPollingInterval());
+ mHandler.postDelayed(mScheduledPollingStats, getPollingInterval());
+ }
+
+ private void maybeSchedulePollingConntrackTimeout() {
+ if (!mPollingStarted) return;
+
+ if (mHandler.hasCallbacks(mScheduledPollingConntrackTimeout)) {
+ mHandler.removeCallbacks(mScheduledPollingConntrackTimeout);
+ }
+
+ mHandler.postDelayed(mScheduledPollingConntrackTimeout, POLLING_CONNTRACK_TIMEOUT_MS);
}
// Return forwarding rule map. This is used for testing only.
diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java
index b52ec86..e91ae85 100644
--- a/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -1039,7 +1039,7 @@
final boolean rndisEnabled = intent.getBooleanExtra(USB_FUNCTION_RNDIS, false);
final boolean ncmEnabled = intent.getBooleanExtra(USB_FUNCTION_NCM, false);
- mLog.log(String.format("USB bcast connected:%s configured:%s rndis:%s ncm:%s",
+ mLog.i(String.format("USB bcast connected:%s configured:%s rndis:%s ncm:%s",
usbConnected, usbConfigured, rndisEnabled, ncmEnabled));
// There are three types of ACTION_USB_STATE:
@@ -1416,7 +1416,7 @@
// If TETHERING_USB is forced to use ncm function, TETHERING_NCM would no longer be
// available.
- if (mConfig.isUsingNcm()) return TETHER_ERROR_SERVICE_UNAVAIL;
+ if (mConfig.isUsingNcm() && enable) return TETHER_ERROR_SERVICE_UNAVAIL;
UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
usbManager.setCurrentFunctions(enable ? UsbManager.FUNCTION_NCM : UsbManager.FUNCTION_NONE);
@@ -1720,13 +1720,7 @@
protected void handleNewUpstreamNetworkState(UpstreamNetworkState ns) {
mIPv6TetheringCoordinator.updateUpstreamNetworkState(ns);
mOffload.updateUpstreamNetworkState(ns);
-
- // TODO: Delete all related offload rules which are using this upstream.
- if (ns != null) {
- // Add upstream index to the map. The upstream interface index is required while
- // the conntrack event builds the offload rules.
- mBpfCoordinator.addUpstreamIfindexToMap(ns.linkProperties);
- }
+ mBpfCoordinator.updateUpstreamNetworkState(ns);
}
private void handleInterfaceServingStateActive(int mode, IpServer who) {
@@ -2558,7 +2552,7 @@
return;
}
- mLog.log("adding IpServer for: " + iface);
+ mLog.i("adding IpServer for: " + iface);
final TetherState tetherState = new TetherState(
new IpServer(iface, mLooper, interfaceType, mLog, mNetd, mBpfCoordinator,
makeControlCallback(), mConfig.enableLegacyDhcpServer,
@@ -2573,7 +2567,7 @@
if (tetherState == null) return;
tetherState.ipServer.stop();
- mLog.log("removing IpServer for: " + iface);
+ mLog.i("removing IpServer for: " + iface);
mTetherStates.remove(iface);
}
diff --git a/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java b/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
index 31fcea4..d2f44d3 100644
--- a/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
+++ b/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
@@ -176,7 +176,9 @@
// us an interface name. Careful consideration needs to be given to
// implications for Settings and for provisioning checks.
tetherableWifiRegexs = getResourceStringArray(res, R.array.config_tether_wifi_regexs);
- tetherableWigigRegexs = getResourceStringArray(res, R.array.config_tether_wigig_regexs);
+ // TODO: Remove entire wigig code once tethering module no longer support R devices.
+ tetherableWigigRegexs = SdkLevel.isAtLeastS()
+ ? new String[0] : getResourceStringArray(res, R.array.config_tether_wigig_regexs);
tetherableWifiP2pRegexs = getResourceStringArray(
res, R.array.config_tether_wifi_p2p_regexs);
tetherableBluetoothRegexs = getResourceStringArray(
diff --git a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
index ce69cb3..378a21c 100644
--- a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
+++ b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
@@ -584,6 +584,7 @@
inOrder.verify(mNetd).networkRemoveInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
inOrder.verify(mAddressCoordinator).releaseDownstream(any());
+ inOrder.verify(mBpfCoordinator).tetherOffloadClientClear(mIpServer);
inOrder.verify(mBpfCoordinator).stopMonitoring(mIpServer);
inOrder.verify(mCallback).updateInterfaceState(
mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
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 cc912f4..914e0d4 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
@@ -36,9 +36,13 @@
import static android.system.OsConstants.ETH_P_IPV6;
import static android.system.OsConstants.IPPROTO_TCP;
import static android.system.OsConstants.IPPROTO_UDP;
+import static android.system.OsConstants.NETLINK_NETFILTER;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.staticMockMarker;
+import static com.android.networkstack.tethering.BpfCoordinator.NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED;
+import static com.android.networkstack.tethering.BpfCoordinator.NF_CONNTRACK_UDP_TIMEOUT_STREAM;
+import static com.android.networkstack.tethering.BpfCoordinator.POLLING_CONNTRACK_TIMEOUT_MS;
import static com.android.networkstack.tethering.BpfCoordinator.StatsType;
import static com.android.networkstack.tethering.BpfCoordinator.StatsType.STATS_PER_IFACE;
import static com.android.networkstack.tethering.BpfCoordinator.StatsType.STATS_PER_UID;
@@ -70,13 +74,17 @@
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.MacAddress;
+import android.net.Network;
+import android.net.NetworkCapabilities;
import android.net.NetworkStats;
import android.net.TetherOffloadRuleParcel;
import android.net.TetherStatsParcel;
import android.net.ip.ConntrackMonitor;
import android.net.ip.ConntrackMonitor.ConntrackEventConsumer;
import android.net.ip.IpServer;
+import android.net.netlink.ConntrackMessage;
import android.net.netlink.NetlinkConstants;
+import android.net.netlink.NetlinkSocket;
import android.net.util.InterfaceParams;
import android.net.util.SharedLog;
import android.os.Build;
@@ -127,6 +135,8 @@
@Rule
public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
+ private static final int TEST_NET_ID = 24;
+
private static final int UPSTREAM_IFINDEX = 1001;
private static final int DOWNSTREAM_IFINDEX = 1002;
@@ -217,6 +227,7 @@
// it has to access the non-static function of BPF coordinator.
private BpfConntrackEventConsumer mConsumer;
+ private long mElapsedRealtimeNanos = 0;
private final ArgumentCaptor<ArrayList> mStringArrayCaptor =
ArgumentCaptor.forClass(ArrayList.class);
private final TestLooper mTestLooper = new TestLooper();
@@ -256,6 +267,10 @@
return mConntrackMonitor;
}
+ public long elapsedRealtimeNanos() {
+ return mElapsedRealtimeNanos;
+ }
+
@Nullable
public BpfMap<Tether4Key, Tether4Value> getBpfDownstream4Map() {
return mBpfDownstream4Map;
@@ -1340,6 +1355,11 @@
}
@NonNull
+ private Tether4Key makeDownstream4Key() {
+ return makeDownstream4Key(IPPROTO_TCP);
+ }
+
+ @NonNull
private ConntrackEvent makeTestConntrackEvent(short msgType, int proto) {
if (msgType != IPCTNL_MSG_CT_NEW && msgType != IPCTNL_MSG_CT_DELETE) {
fail("Not support message type " + msgType);
@@ -1365,7 +1385,10 @@
final LinkProperties lp = new LinkProperties();
lp.setInterfaceName(UPSTREAM_IFACE);
lp.addLinkAddress(new LinkAddress(PUBLIC_ADDR, 32 /* prefix length */));
- coordinator.addUpstreamIfindexToMap(lp);
+ final NetworkCapabilities capabilities = new NetworkCapabilities()
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ coordinator.updateUpstreamNetworkState(new UpstreamNetworkState(lp, capabilities,
+ new Network(TEST_NET_ID)));
}
private void setDownstreamAndClientInformationTo(final BpfCoordinator coordinator) {
@@ -1379,8 +1402,11 @@
// was started.
coordinator.startPolling();
- // Needed because tetherOffloadRuleRemove of api31.BpfCoordinatorShimImpl only decreases
- // the count while the entry is deleted. In the other words, deleteEntry returns true.
+ // Needed because two reasons: (1) BpfConntrackEventConsumer#accept only performs cleanup
+ // when both upstream and downstream rules are removed. (2) tetherOffloadRuleRemove of
+ // api31.BpfCoordinatorShimImpl only decreases the count while the entry is deleted.
+ // In the other words, deleteEntry returns true.
+ doReturn(true).when(mBpfUpstream4Map).deleteEntry(any());
doReturn(true).when(mBpfDownstream4Map).deleteEntry(any());
// Needed because BpfCoordinator#addUpstreamIfindexToMap queries interface parameter for
@@ -1494,4 +1520,104 @@
mConsumer.accept(makeTestConntrackEvent(IPCTNL_MSG_CT_NEW, IPPROTO_UDP));
verify(mBpfDevMap, never()).updateEntry(any(), any());
}
+
+ private void setElapsedRealtimeNanos(long nanoSec) {
+ mElapsedRealtimeNanos = nanoSec;
+ }
+
+ private void checkRefreshConntrackTimeout(final TestBpfMap<Tether4Key, Tether4Value> bpfMap,
+ final Tether4Key tcpKey, final Tether4Value tcpValue, final Tether4Key udpKey,
+ final Tether4Value udpValue) throws Exception {
+ // Both system elapsed time since boot and the rule last used time are used to measure
+ // the rule expiration. In this test, all test rules are fixed the last used time to 0.
+ // Set the different testing elapsed time to make the rule to be valid or expired.
+ //
+ // Timeline:
+ // 0 60 (seconds)
+ // +---+---+---+---+--...--+---+---+---+---+---+- ..
+ // | POLLING_CONNTRACK_TIMEOUT_MS |
+ // +---+---+---+---+--...--+---+---+---+---+---+- ..
+ // |<- valid diff ->|
+ // |<- expired diff ->|
+ // ^ ^ ^
+ // last used time elapsed time (valid) elapsed time (expired)
+ final long validTime = (POLLING_CONNTRACK_TIMEOUT_MS - 1) * 1_000_000L;
+ final long expiredTime = (POLLING_CONNTRACK_TIMEOUT_MS + 1) * 1_000_000L;
+
+ // Static mocking for NetlinkSocket.
+ MockitoSession mockSession = ExtendedMockito.mockitoSession()
+ .mockStatic(NetlinkSocket.class)
+ .startMocking();
+ try {
+ final BpfCoordinator coordinator = makeBpfCoordinator();
+ coordinator.startPolling();
+ bpfMap.insertEntry(tcpKey, tcpValue);
+ bpfMap.insertEntry(udpKey, udpValue);
+
+ // [1] Don't refresh contrack timeout.
+ setElapsedRealtimeNanos(expiredTime);
+ mTestLooper.moveTimeForward(POLLING_CONNTRACK_TIMEOUT_MS);
+ waitForIdle();
+ ExtendedMockito.verifyNoMoreInteractions(staticMockMarker(NetlinkSocket.class));
+ ExtendedMockito.clearInvocations(staticMockMarker(NetlinkSocket.class));
+
+ // [2] Refresh contrack timeout.
+ setElapsedRealtimeNanos(validTime);
+ mTestLooper.moveTimeForward(POLLING_CONNTRACK_TIMEOUT_MS);
+ waitForIdle();
+ final byte[] expectedNetlinkTcp = ConntrackMessage.newIPv4TimeoutUpdateRequest(
+ IPPROTO_TCP, PRIVATE_ADDR, (int) PRIVATE_PORT, REMOTE_ADDR,
+ (int) REMOTE_PORT, NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED);
+ final byte[] expectedNetlinkUdp = ConntrackMessage.newIPv4TimeoutUpdateRequest(
+ IPPROTO_UDP, PRIVATE_ADDR, (int) PRIVATE_PORT, REMOTE_ADDR,
+ (int) REMOTE_PORT, NF_CONNTRACK_UDP_TIMEOUT_STREAM);
+ ExtendedMockito.verify(() -> NetlinkSocket.sendOneShotKernelMessage(
+ eq(NETLINK_NETFILTER), eq(expectedNetlinkTcp)));
+ ExtendedMockito.verify(() -> NetlinkSocket.sendOneShotKernelMessage(
+ eq(NETLINK_NETFILTER), eq(expectedNetlinkUdp)));
+ ExtendedMockito.verifyNoMoreInteractions(staticMockMarker(NetlinkSocket.class));
+ ExtendedMockito.clearInvocations(staticMockMarker(NetlinkSocket.class));
+
+ // [3] Don't refresh contrack timeout if polling stopped.
+ coordinator.stopPolling();
+ mTestLooper.moveTimeForward(POLLING_CONNTRACK_TIMEOUT_MS);
+ waitForIdle();
+ ExtendedMockito.verifyNoMoreInteractions(staticMockMarker(NetlinkSocket.class));
+ ExtendedMockito.clearInvocations(staticMockMarker(NetlinkSocket.class));
+ } finally {
+ mockSession.finishMocking();
+ }
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ public void testRefreshConntrackTimeout_Upstream4Map() throws Exception {
+ // TODO: Replace the dependencies BPF map with a non-mocked TestBpfMap object.
+ final TestBpfMap<Tether4Key, Tether4Value> bpfUpstream4Map =
+ new TestBpfMap<>(Tether4Key.class, Tether4Value.class);
+ doReturn(bpfUpstream4Map).when(mDeps).getBpfUpstream4Map();
+
+ final Tether4Key tcpKey = makeUpstream4Key(IPPROTO_TCP);
+ final Tether4Key udpKey = makeUpstream4Key(IPPROTO_UDP);
+ final Tether4Value tcpValue = makeUpstream4Value();
+ final Tether4Value udpValue = makeUpstream4Value();
+
+ checkRefreshConntrackTimeout(bpfUpstream4Map, tcpKey, tcpValue, udpKey, udpValue);
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ public void testRefreshConntrackTimeout_Downstream4Map() throws Exception {
+ // TODO: Replace the dependencies BPF map with a non-mocked TestBpfMap object.
+ final TestBpfMap<Tether4Key, Tether4Value> bpfDownstream4Map =
+ new TestBpfMap<>(Tether4Key.class, Tether4Value.class);
+ doReturn(bpfDownstream4Map).when(mDeps).getBpfDownstream4Map();
+
+ final Tether4Key tcpKey = makeDownstream4Key(IPPROTO_TCP);
+ final Tether4Key udpKey = makeDownstream4Key(IPPROTO_UDP);
+ final Tether4Value tcpValue = makeDownstream4Value();
+ final Tether4Value udpValue = makeDownstream4Value();
+
+ checkRefreshConntrackTimeout(bpfDownstream4Map, tcpKey, tcpValue, udpKey, udpValue);
+ }
}
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
index af28dd7..9e0c880 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
@@ -2610,12 +2610,57 @@
reset(mBluetoothAdapter, mBluetoothPan);
}
+ private void runDualStackUsbTethering(final String expectedIface) throws Exception {
+ when(mNetd.interfaceGetList()).thenReturn(new String[] {expectedIface});
+ when(mRouterAdvertisementDaemon.start())
+ .thenReturn(true);
+ final UpstreamNetworkState upstreamState = buildMobileDualStackUpstreamState();
+ runUsbTethering(upstreamState);
+
+ verify(mNetd).interfaceGetList();
+ verify(mNetd).tetherAddForward(expectedIface, TEST_MOBILE_IFNAME);
+ verify(mNetd).ipfwdAddInterfaceForward(expectedIface, TEST_MOBILE_IFNAME);
+
+ verify(mRouterAdvertisementDaemon).start();
+ verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS)).startWithCallbacks(
+ any(), any());
+ sendIPv6TetherUpdates(upstreamState);
+ assertSetIfaceToDadProxy(1 /* numOfCalls */, TEST_MOBILE_IFNAME /* ifaceName */);
+ verify(mRouterAdvertisementDaemon).buildNewRa(any(), notNull());
+ verify(mNetd).tetherApplyDnsInterfaces();
+ }
+
+ private void forceUsbTetheringUse(final int function) {
+ Settings.Global.putInt(mContentResolver, TETHER_FORCE_USB_FUNCTIONS, function);
+ final ContentObserver observer = mTethering.getSettingsObserverForTest();
+ observer.onChange(false /* selfChange */);
+ mLooper.dispatchAll();
+ }
+
+ private void verifyUsbTetheringStopDueToSettingChange(final String iface) {
+ verify(mUsbManager, times(2)).setCurrentFunctions(UsbManager.FUNCTION_NONE);
+ mTethering.interfaceRemoved(iface);
+ sendUsbBroadcast(true, true, -1 /* no functions enabled */);
+ reset(mUsbManager, mNetd, mDhcpServer, mRouterAdvertisementDaemon,
+ mIPv6TetheringCoordinator, mDadProxy);
+ }
+
@Test
- public void testUsbTetheringWithNcmFunction() throws Exception {
- when(mResources.getInteger(R.integer.config_tether_usb_functions)).thenReturn(
- TetheringConfiguration.TETHER_USB_NCM_FUNCTION);
+ public void testUsbFunctionConfigurationChange() throws Exception {
+ // Run TETHERING_NCM.
+ runNcmTethering();
+ verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).startWithCallbacks(
+ any(), any());
+
+ // Change the USB tethering function to NCM. Because the USB tethering function was set to
+ // RNDIS (the default), tethering is stopped.
+ forceUsbTetheringUse(TETHER_USB_NCM_FUNCTION);
+ verifyUsbTetheringStopDueToSettingChange(TEST_NCM_IFNAME);
+
+ // TODO: move this into setup after allowing configure TEST_NCM_REGEX into
+ // config_tether_usb_regexs and config_tether_ncm_regexs at the same time.
when(mResources.getStringArray(R.array.config_tether_usb_regexs))
- .thenReturn(new String[] {TEST_NCM_REGEX});
+ .thenReturn(new String[] {TEST_RNDIS_REGEX, TEST_NCM_REGEX});
sendConfigurationChanged();
// If TETHERING_USB is forced to use ncm function, TETHERING_NCM would no longer be
@@ -2625,30 +2670,16 @@
mLooper.dispatchAll();
ncmResult.assertHasResult();
- final UpstreamNetworkState upstreamState = buildMobileDualStackUpstreamState();
- runUsbTethering(upstreamState);
+ // Run TETHERING_USB with ncm configuration.
+ runDualStackUsbTethering(TEST_NCM_IFNAME);
- verify(mNetd).interfaceGetList();
- verify(mNetd).tetherAddForward(TEST_NCM_IFNAME, TEST_MOBILE_IFNAME);
- verify(mNetd).ipfwdAddInterfaceForward(TEST_NCM_IFNAME, TEST_MOBILE_IFNAME);
+ // Change configuration to rndis.
+ forceUsbTetheringUse(TETHER_USB_RNDIS_FUNCTION);
+ verifyUsbTetheringStopDueToSettingChange(TEST_NCM_IFNAME);
- verify(mRouterAdvertisementDaemon).start();
- verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS)).startWithCallbacks(
- any(), any());
- sendIPv6TetherUpdates(upstreamState);
- assertSetIfaceToDadProxy(1 /* numOfCalls */, TEST_MOBILE_IFNAME /* ifaceName */);
- verify(mRouterAdvertisementDaemon).buildNewRa(any(), notNull());
- verify(mNetd).tetherApplyDnsInterfaces();
-
- Settings.Global.putInt(mContentResolver, TETHER_FORCE_USB_FUNCTIONS,
- TETHER_USB_RNDIS_FUNCTION);
- final ContentObserver observer = mTethering.getSettingsObserverForTest();
- observer.onChange(false /* selfChange */);
- mLooper.dispatchAll();
- // stop TETHERING_USB and TETHERING_NCM
- verify(mUsbManager, times(2)).setCurrentFunctions(UsbManager.FUNCTION_NONE);
- mTethering.interfaceRemoved(TEST_NCM_IFNAME);
- sendUsbBroadcast(true, true, -1 /* function */);
+ // Run TETHERING_USB with rndis configuration.
+ runDualStackUsbTethering(TEST_RNDIS_IFNAME);
+ runStopUSBTethering();
}
// TODO: Test that a request for hotspot mode doesn't interfere with an
// already operating tethering mode interface.
diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java
index e496966..758c612 100644
--- a/framework/src/android/net/ConnectivityManager.java
+++ b/framework/src/android/net/ConnectivityManager.java
@@ -4722,6 +4722,22 @@
}
/**
+ * Temporarily allow bad wifi to override {@code config_networkAvoidBadWifi} configuration.
+ *
+ * @param timeMs The expired current time. The value should be set within a limited time from
+ * now.
+ *
+ * @hide
+ */
+ public void setTestAllowBadWifiUntil(long timeMs) {
+ try {
+ mService.setTestAllowBadWifiUntil(timeMs);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Requests that the system open the captive portal app on the specified network.
*
* <p>This is to be used on networks where a captive portal was detected, as per
diff --git a/framework/src/android/net/ConnectivitySettingsManager.java b/framework/src/android/net/ConnectivitySettingsManager.java
index 4644e4f..085de6b 100644
--- a/framework/src/android/net/ConnectivitySettingsManager.java
+++ b/framework/src/android/net/ConnectivitySettingsManager.java
@@ -562,7 +562,7 @@
public static void setNetworkSwitchNotificationMaximumDailyCount(@NonNull Context context,
@IntRange(from = 0) int count) {
if (count < 0) {
- throw new IllegalArgumentException("Count must be 0~10.");
+ throw new IllegalArgumentException("Count must be more than 0.");
}
Settings.Global.putInt(
context.getContentResolver(), NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT, count);
@@ -585,6 +585,7 @@
/**
* Set minimum duration (to {@link Settings}) between each switching network notifications.
+ * The duration will be rounded down to the next millisecond, and must be positive.
*
* @param context The {@link Context} to set the setting.
* @param duration The minimum duration between notifications when switching networks.
@@ -612,10 +613,11 @@
/**
* Set URL (to {@link Settings}) used for HTTP captive portal detection upon a new connection.
- * This URL should respond with a 204 response to a GET request to indicate no captive portal is
- * present. And this URL must be HTTP as redirect responses are used to find captive portal
- * sign-in pages. If the URL set to null or be incorrect, it will result in captive portal
- * detection failed and lost the connection.
+ * The URL is accessed to check for connectivity and presence of a captive portal on a network.
+ * The URL should respond with HTTP status 204 to a GET request, and the stack will use
+ * redirection status as a signal for captive portal detection.
+ * If the URL is set to null or is otherwise incorrect or inaccessible, the stack will fail to
+ * detect connectivity and portals. This will often result in loss of connectivity.
*
* @param context The {@link Context} to set the setting.
* @param url The URL used for HTTP captive portal detection upon a new connection.
@@ -819,6 +821,7 @@
/**
* Set duration (to {@link Settings}) to keep a PendingIntent-based request.
+ * The duration will be rounded down to the next millisecond, and must be positive.
*
* @param context The {@link Context} to set the setting.
* @param duration The duration to keep a PendingIntent-based request.
diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl
index c434bbc..50ec781 100644
--- a/framework/src/android/net/IConnectivityManager.aidl
+++ b/framework/src/android/net/IConnectivityManager.aidl
@@ -226,4 +226,6 @@
void offerNetwork(int providerId, in NetworkScore score,
in NetworkCapabilities caps, in INetworkOfferCallback callback);
void unofferNetwork(in INetworkOfferCallback callback);
+
+ void setTestAllowBadWifiUntil(long timeMs);
}
diff --git a/framework/src/android/net/util/MultinetworkPolicyTracker.java b/framework/src/android/net/util/MultinetworkPolicyTracker.java
index 0b42a00..9791cbf 100644
--- a/framework/src/android/net/util/MultinetworkPolicyTracker.java
+++ b/framework/src/android/net/util/MultinetworkPolicyTracker.java
@@ -75,6 +75,7 @@
private volatile boolean mAvoidBadWifi = true;
private volatile int mMeteredMultipathPreference;
private int mActiveSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ private volatile long mTestAllowBadWifiUntilMs = 0;
// Mainline module can't use internal HandlerExecutor, so add an identical executor here.
private static class HandlerExecutor implements Executor {
@@ -162,14 +163,31 @@
* Whether the device or carrier configuration disables avoiding bad wifi by default.
*/
public boolean configRestrictsAvoidBadWifi() {
+ final boolean allowBadWifi = mTestAllowBadWifiUntilMs > 0
+ && mTestAllowBadWifiUntilMs > System.currentTimeMillis();
+ // If the config returns true, then avoid bad wifi design can be controlled by the
+ // NETWORK_AVOID_BAD_WIFI setting.
+ if (allowBadWifi) return true;
+
// TODO: use R.integer.config_networkAvoidBadWifi directly
final int id = mResources.get().getIdentifier("config_networkAvoidBadWifi",
"integer", mResources.getResourcesContext().getPackageName());
return (getResourcesForActiveSubId().getInteger(id) == 0);
}
+ /**
+ * Temporarily allow bad wifi to override {@code config_networkAvoidBadWifi} configuration.
+ * The value works when the time set is more than {@link System.currentTimeMillis()}.
+ */
+ public void setTestAllowBadWifiUntil(long timeMs) {
+ Log.d(TAG, "setTestAllowBadWifiUntil: " + mTestAllowBadWifiUntilMs);
+ mTestAllowBadWifiUntilMs = timeMs;
+ reevaluateInternal();
+ }
+
+ @VisibleForTesting
@NonNull
- private Resources getResourcesForActiveSubId() {
+ protected Resources getResourcesForActiveSubId() {
return SubscriptionManager.getResourcesForSubId(
mResources.getResourcesContext(), mActiveSubId);
}
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index 899286b..7b58503 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -652,6 +652,12 @@
private static final int EVENT_MOBILE_DATA_PREFERRED_UIDS_CHANGED = 54;
/**
+ * Event to set temporary allow bad wifi within a limited time to override
+ * {@code config_networkAvoidBadWifi}.
+ */
+ private static final int EVENT_SET_TEST_ALLOW_BAD_WIFI_UNTIL = 55;
+
+ /**
* Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
* should be shown.
*/
@@ -663,6 +669,11 @@
*/
private static final int PROVISIONING_NOTIFICATION_HIDE = 0;
+ /**
+ * The maximum alive time to allow bad wifi configuration for testing.
+ */
+ private static final long MAX_TEST_ALLOW_BAD_WIFI_UNTIL_MS = 5 * 60 * 1000L;
+
private static String eventName(int what) {
return sMagicDecoderRing.get(what, Integer.toString(what));
}
@@ -1276,6 +1287,20 @@
public boolean getCellular464XlatEnabled() {
return NetworkProperties.isCellular464XlatEnabled().orElse(true);
}
+
+ /**
+ * @see PendingIntent#intentFilterEquals
+ */
+ public boolean intentFilterEquals(PendingIntent a, PendingIntent b) {
+ return a.intentFilterEquals(b);
+ }
+
+ /**
+ * @see LocationPermissionChecker
+ */
+ public LocationPermissionChecker makeLocationPermissionChecker(Context context) {
+ return new LocationPermissionChecker(context);
+ }
}
public ConnectivityService(Context context) {
@@ -1343,7 +1368,7 @@
mNetd = netd;
mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
- mLocationPermissionChecker = new LocationPermissionChecker(mContext);
+ mLocationPermissionChecker = mDeps.makeLocationPermissionChecker(mContext);
// To ensure uid state is synchronized with Network Policy, register for
// NetworkPolicyManagerService events must happen prior to NetworkPolicyManagerService
@@ -3934,7 +3959,7 @@
for (Map.Entry<NetworkRequest, NetworkRequestInfo> entry : mNetworkRequests.entrySet()) {
PendingIntent existingPendingIntent = entry.getValue().mPendingIntent;
if (existingPendingIntent != null &&
- existingPendingIntent.intentFilterEquals(pendingIntent)) {
+ mDeps.intentFilterEquals(existingPendingIntent, pendingIntent)) {
return entry.getValue();
}
}
@@ -4328,6 +4353,22 @@
mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_AVOID_UNVALIDATED, network));
}
+ @Override
+ public void setTestAllowBadWifiUntil(long timeMs) {
+ enforceSettingsPermission();
+ if (!Build.isDebuggable()) {
+ throw new IllegalStateException("Does not support in non-debuggable build");
+ }
+
+ if (timeMs > System.currentTimeMillis() + MAX_TEST_ALLOW_BAD_WIFI_UNTIL_MS) {
+ throw new IllegalArgumentException("It should not exceed "
+ + MAX_TEST_ALLOW_BAD_WIFI_UNTIL_MS + "ms from now");
+ }
+
+ mHandler.sendMessage(
+ mHandler.obtainMessage(EVENT_SET_TEST_ALLOW_BAD_WIFI_UNTIL, timeMs));
+ }
+
private void handleSetAcceptUnvalidated(Network network, boolean accept, boolean always) {
if (DBG) log("handleSetAcceptUnvalidated network=" + network +
" accept=" + accept + " always=" + always);
@@ -4870,6 +4911,10 @@
case EVENT_MOBILE_DATA_PREFERRED_UIDS_CHANGED:
handleMobileDataPreferredUidsChanged();
break;
+ case EVENT_SET_TEST_ALLOW_BAD_WIFI_UNTIL:
+ final long timeMs = ((Long) msg.obj).longValue();
+ mMultinetworkPolicyTracker.setTestAllowBadWifiUntil(timeMs);
+ break;
}
}
}
@@ -6243,7 +6288,8 @@
callingAttributionTag);
if (VDBG) log("pendingListenForNetwork for " + nri);
- mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
+ mHandler.sendMessage(mHandler.obtainMessage(
+ EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT, nri));
}
/** Returns the next Network provider ID. */
@@ -7551,9 +7597,16 @@
// If apps could file multi-layer requests with PendingIntents, they'd need to know
// which of the layer is satisfied alongside with some ID for the request. Hence, if
// such an API is ever implemented, there is no doubt the right request to send in
- // EXTRA_NETWORK_REQUEST is mActiveRequest, and whatever ID would be added would need to
- // be sent as a separate extra.
- intent.putExtra(ConnectivityManager.EXTRA_NETWORK_REQUEST, nri.getActiveRequest());
+ // EXTRA_NETWORK_REQUEST is the active request, and whatever ID would be added would
+ // need to be sent as a separate extra.
+ final NetworkRequest req = nri.isMultilayerRequest()
+ ? nri.getActiveRequest()
+ // Non-multilayer listen requests do not have an active request
+ : nri.mRequests.get(0);
+ if (req == null) {
+ Log.wtf(TAG, "No request in NRI " + nri);
+ }
+ intent.putExtra(ConnectivityManager.EXTRA_NETWORK_REQUEST, req);
nri.mPendingIntentSent = true;
sendIntent(nri.mPendingIntent, intent);
}
diff --git a/service/src/com/android/server/connectivity/KeepaliveTracker.java b/service/src/com/android/server/connectivity/KeepaliveTracker.java
index 7d922a4..3b58823 100644
--- a/service/src/com/android/server/connectivity/KeepaliveTracker.java
+++ b/service/src/com/android/server/connectivity/KeepaliveTracker.java
@@ -366,12 +366,10 @@
Log.e(TAG, "Cannot stop unowned keepalive " + mSlot + " on " + mNai.network);
}
}
- // Ignore the case when the network disconnects immediately after stop() has been
- // called and the keepalive code is waiting for the response from the modem. This
- // might happen when the caller listens for a lower-layer network disconnect
- // callback and stop the keepalive at that time. But the stop() races with the
- // stop() generated in ConnectivityService network disconnection code path.
- if (mStartedState == STOPPING && reason == ERROR_INVALID_NETWORK) return;
+ // To prevent races from re-entrance of stop(), return if the state is already stopping.
+ // This might happen if multiple event sources stop keepalive in a short time. Such as
+ // network disconnect after user calls stop(), or tear down socket after binder died.
+ if (mStartedState == STOPPING) return;
// Store the reason of stopping, and report it after the keepalive is fully stopped.
if (mStopReason != ERROR_STOP_REASON_UNINITIALIZED) {
diff --git a/service/src/com/android/server/connectivity/PermissionMonitor.java b/service/src/com/android/server/connectivity/PermissionMonitor.java
old mode 100644
new mode 100755
index 3328846..e98a638
--- a/service/src/com/android/server/connectivity/PermissionMonitor.java
+++ b/service/src/com/android/server/connectivity/PermissionMonitor.java
@@ -230,11 +230,11 @@
boolean hasRestrictedPermission = hasRestrictedNetworkPermission(app);
if (isNetwork || hasRestrictedPermission) {
- Boolean permission = mApps.get(uid);
+ Boolean permission = mApps.get(UserHandle.getAppId(uid));
// If multiple packages share a UID (cf: android:sharedUserId) and ask for different
// permissions, don't downgrade (i.e., if it's already SYSTEM, leave it as is).
if (permission == null || permission == NETWORK) {
- mApps.put(uid, hasRestrictedPermission);
+ mApps.put(UserHandle.getAppId(uid), hasRestrictedPermission);
}
}
@@ -325,14 +325,14 @@
// networks. mApps contains the result of checks for both hasNetworkPermission and
// hasRestrictedNetworkPermission. If uid is in the mApps list that means uid has one of
// permissions at least.
- return mApps.containsKey(uid);
+ return mApps.containsKey(UserHandle.getAppId(uid));
}
/**
* Returns whether the given uid has permission to use restricted networks.
*/
public synchronized boolean hasRestrictedNetworksPermission(int uid) {
- return Boolean.TRUE.equals(mApps.get(uid));
+ return Boolean.TRUE.equals(mApps.get(UserHandle.getAppId(uid)));
}
private void update(Set<UserHandle> users, Map<Integer, Boolean> apps, boolean add) {
@@ -452,12 +452,13 @@
// If multiple packages share a UID (cf: android:sharedUserId) and ask for different
// permissions, don't downgrade (i.e., if it's already SYSTEM, leave it as is).
- final Boolean permission = highestPermissionForUid(mApps.get(uid), packageName);
- if (permission != mApps.get(uid)) {
- mApps.put(uid, permission);
+ final int appId = UserHandle.getAppId(uid);
+ final Boolean permission = highestPermissionForUid(mApps.get(appId), packageName);
+ if (permission != mApps.get(appId)) {
+ mApps.put(appId, permission);
Map<Integer, Boolean> apps = new HashMap<>();
- apps.put(uid, permission);
+ apps.put(appId, permission);
update(mUsers, apps, true);
}
@@ -472,7 +473,7 @@
updateVpnUids(vpn.getKey(), changedUids, true);
}
}
- mAllApps.add(UserHandle.getAppId(uid));
+ mAllApps.add(appId);
}
private Boolean highestUidNetworkPermission(int uid) {
@@ -529,16 +530,17 @@
return;
}
- if (permission == mApps.get(uid)) {
+ final int appId = UserHandle.getAppId(uid);
+ if (permission == mApps.get(appId)) {
// The permissions of this UID have not changed. Nothing to do.
return;
} else if (permission != null) {
- mApps.put(uid, permission);
- apps.put(uid, permission);
+ mApps.put(appId, permission);
+ apps.put(appId, permission);
update(mUsers, apps, true);
} else {
- mApps.remove(uid);
- apps.put(uid, NETWORK); // doesn't matter which permission we pick here
+ mApps.remove(appId);
+ apps.put(appId, NETWORK); // doesn't matter which permission we pick here
update(mUsers, apps, false);
}
}
@@ -653,7 +655,7 @@
*/
private void removeBypassingUids(Set<Integer> uids, int vpnAppUid) {
uids.remove(vpnAppUid);
- uids.removeIf(uid -> mApps.getOrDefault(uid, NETWORK) == SYSTEM);
+ uids.removeIf(uid -> mApps.getOrDefault(UserHandle.getAppId(uid), NETWORK) == SYSTEM);
}
/**
@@ -795,12 +797,13 @@
for (Integer uid : uidsToUpdate) {
final Boolean permission = highestUidNetworkPermission(uid);
+ final int appId = UserHandle.getAppId(uid);
if (null == permission) {
- removedUids.put(uid, NETWORK); // Doesn't matter which permission is set here.
- mApps.remove(uid);
+ removedUids.put(appId, NETWORK); // Doesn't matter which permission is set here.
+ mApps.remove(appId);
} else {
- updatedUids.put(uid, permission);
- mApps.put(uid, permission);
+ updatedUids.put(appId, permission);
+ mApps.put(appId, permission);
}
}
diff --git a/tests/unit/java/android/net/ConnectivityDiagnosticsManagerTest.java b/tests/common/java/android/net/ConnectivityDiagnosticsManagerTest.java
similarity index 98%
rename from tests/unit/java/android/net/ConnectivityDiagnosticsManagerTest.java
rename to tests/common/java/android/net/ConnectivityDiagnosticsManagerTest.java
index 06e9405..294ed10 100644
--- a/tests/unit/java/android/net/ConnectivityDiagnosticsManagerTest.java
+++ b/tests/common/java/android/net/ConnectivityDiagnosticsManagerTest.java
@@ -36,9 +36,11 @@
import static org.mockito.Mockito.verifyNoMoreInteractions;
import android.content.Context;
+import android.os.Build;
import android.os.PersistableBundle;
import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SdkSuppress;
import org.junit.After;
import org.junit.Before;
@@ -50,6 +52,7 @@
import java.util.concurrent.Executor;
@RunWith(JUnit4.class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
public class ConnectivityDiagnosticsManagerTest {
private static final int NET_ID = 1;
private static final int DETECTION_METHOD = 2;
diff --git a/tests/common/java/android/net/ConnectivitySettingsManagerTest.kt b/tests/common/java/android/net/ConnectivitySettingsManagerTest.kt
new file mode 100644
index 0000000..ebaa787
--- /dev/null
+++ b/tests/common/java/android/net/ConnectivitySettingsManagerTest.kt
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net
+
+import android.net.ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE
+import android.net.ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_AVOID
+import android.net.ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_IGNORE
+import android.net.ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_PROMPT
+import android.net.ConnectivitySettingsManager.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS
+import android.net.ConnectivitySettingsManager.DATA_ACTIVITY_TIMEOUT_MOBILE
+import android.net.ConnectivitySettingsManager.DATA_ACTIVITY_TIMEOUT_WIFI
+import android.net.ConnectivitySettingsManager.DNS_RESOLVER_MAX_SAMPLES
+import android.net.ConnectivitySettingsManager.DNS_RESOLVER_MIN_SAMPLES
+import android.net.ConnectivitySettingsManager.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS
+import android.net.ConnectivitySettingsManager.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT
+import android.net.ConnectivitySettingsManager.MOBILE_DATA_ALWAYS_ON
+import android.net.ConnectivitySettingsManager.NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT
+import android.net.ConnectivitySettingsManager.NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS
+import android.net.ConnectivitySettingsManager.PRIVATE_DNS_DEFAULT_MODE
+import android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OFF
+import android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OPPORTUNISTIC
+import android.net.ConnectivitySettingsManager.WIFI_ALWAYS_REQUESTED
+import android.net.ConnectivitySettingsManager.getCaptivePortalMode
+import android.net.ConnectivitySettingsManager.getConnectivityKeepPendingIntentDuration
+import android.net.ConnectivitySettingsManager.getDnsResolverSampleRanges
+import android.net.ConnectivitySettingsManager.getDnsResolverSampleValidityDuration
+import android.net.ConnectivitySettingsManager.getDnsResolverSuccessThresholdPercent
+import android.net.ConnectivitySettingsManager.getMobileDataActivityTimeout
+import android.net.ConnectivitySettingsManager.getMobileDataAlwaysOn
+import android.net.ConnectivitySettingsManager.getNetworkSwitchNotificationMaximumDailyCount
+import android.net.ConnectivitySettingsManager.getNetworkSwitchNotificationRateDuration
+import android.net.ConnectivitySettingsManager.getPrivateDnsDefaultMode
+import android.net.ConnectivitySettingsManager.getWifiAlwaysRequested
+import android.net.ConnectivitySettingsManager.getWifiDataActivityTimeout
+import android.net.ConnectivitySettingsManager.setCaptivePortalMode
+import android.net.ConnectivitySettingsManager.setConnectivityKeepPendingIntentDuration
+import android.net.ConnectivitySettingsManager.setDnsResolverSampleRanges
+import android.net.ConnectivitySettingsManager.setDnsResolverSampleValidityDuration
+import android.net.ConnectivitySettingsManager.setDnsResolverSuccessThresholdPercent
+import android.net.ConnectivitySettingsManager.setMobileDataActivityTimeout
+import android.net.ConnectivitySettingsManager.setMobileDataAlwaysOn
+import android.net.ConnectivitySettingsManager.setNetworkSwitchNotificationMaximumDailyCount
+import android.net.ConnectivitySettingsManager.setNetworkSwitchNotificationRateDuration
+import android.net.ConnectivitySettingsManager.setPrivateDnsDefaultMode
+import android.net.ConnectivitySettingsManager.setWifiAlwaysRequested
+import android.net.ConnectivitySettingsManager.setWifiDataActivityTimeout
+import android.os.Build
+import android.platform.test.annotations.AppModeFull
+import android.provider.Settings
+import android.util.Range
+import androidx.test.InstrumentationRegistry
+import androidx.test.filters.SmallTest
+import com.android.net.module.util.ConnectivitySettingsUtils.getPrivateDnsModeAsString
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
+import com.android.testutils.DevSdkIgnoreRunner
+import junit.framework.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.time.Duration
+import java.util.Objects
+import kotlin.test.assertFailsWith
+
+/**
+ * Tests for [ConnectivitySettingsManager].
+ *
+ * Build, install and run with:
+ * atest android.net.ConnectivitySettingsManagerTest
+ */
+@RunWith(DevSdkIgnoreRunner::class)
+@IgnoreUpTo(Build.VERSION_CODES.R)
+@SmallTest
+@AppModeFull(reason = "WRITE_SECURE_SETTINGS permission can't be granted to instant apps")
+class ConnectivitySettingsManagerTest {
+ private val instrumentation = InstrumentationRegistry.getInstrumentation()
+ private val context = instrumentation.context
+ private val resolver = context.contentResolver
+
+ private val defaultDuration = Duration.ofSeconds(0L)
+ private val testTime1 = 5L
+ private val testTime2 = 10L
+ private val settingsTypeGlobal = "global"
+ private val settingsTypeSecure = "secure"
+
+ /*** Reset setting value or delete setting if the setting was not existed before testing. */
+ private fun resetSettings(names: Array<String>, type: String, values: Array<String?>) {
+ for (i in names.indices) {
+ if (Objects.equals(values[i], null)) {
+ instrumentation.uiAutomation.executeShellCommand(
+ "settings delete $type ${names[i]}")
+ } else {
+ if (settingsTypeSecure.equals(type)) {
+ Settings.Secure.putString(resolver, names[i], values[i])
+ } else {
+ Settings.Global.putString(resolver, names[i], values[i])
+ }
+ }
+ }
+ }
+
+ fun <T> testIntSetting(
+ names: Array<String>,
+ type: String,
+ value1: T,
+ value2: T,
+ getter: () -> T,
+ setter: (value: T) -> Unit,
+ testIntValues: IntArray
+ ) {
+ val originals: Array<String?> = Array(names.size) { i ->
+ if (settingsTypeSecure.equals(type)) {
+ Settings.Secure.getString(resolver, names[i])
+ } else {
+ Settings.Global.getString(resolver, names[i])
+ }
+ }
+
+ try {
+ for (i in names.indices) {
+ if (settingsTypeSecure.equals(type)) {
+ Settings.Secure.putString(resolver, names[i], testIntValues[i].toString())
+ } else {
+ Settings.Global.putString(resolver, names[i], testIntValues[i].toString())
+ }
+ }
+ assertEquals(value1, getter())
+
+ setter(value2)
+ assertEquals(value2, getter())
+ } finally {
+ resetSettings(names, type, originals)
+ }
+ }
+
+ @Test
+ fun testMobileDataActivityTimeout() {
+ testIntSetting(names = arrayOf(DATA_ACTIVITY_TIMEOUT_MOBILE), type = settingsTypeGlobal,
+ value1 = Duration.ofSeconds(testTime1), value2 = Duration.ofSeconds(testTime2),
+ getter = { getMobileDataActivityTimeout(context, defaultDuration) },
+ setter = { setMobileDataActivityTimeout(context, it) },
+ testIntValues = intArrayOf(testTime1.toInt()))
+ }
+
+ @Test
+ fun testWifiDataActivityTimeout() {
+ testIntSetting(names = arrayOf(DATA_ACTIVITY_TIMEOUT_WIFI), type = settingsTypeGlobal,
+ value1 = Duration.ofSeconds(testTime1), value2 = Duration.ofSeconds(testTime2),
+ getter = { getWifiDataActivityTimeout(context, defaultDuration) },
+ setter = { setWifiDataActivityTimeout(context, it) },
+ testIntValues = intArrayOf(testTime1.toInt()))
+ }
+
+ @Test
+ fun testDnsResolverSampleValidityDuration() {
+ testIntSetting(names = arrayOf(DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS),
+ type = settingsTypeGlobal, value1 = Duration.ofSeconds(testTime1),
+ value2 = Duration.ofSeconds(testTime2),
+ getter = { getDnsResolverSampleValidityDuration(context, defaultDuration) },
+ setter = { setDnsResolverSampleValidityDuration(context, it) },
+ testIntValues = intArrayOf(testTime1.toInt()))
+
+ assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") {
+ setDnsResolverSampleValidityDuration(context, Duration.ofSeconds(-1L)) }
+ }
+
+ @Test
+ fun testDnsResolverSuccessThresholdPercent() {
+ testIntSetting(names = arrayOf(DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT),
+ type = settingsTypeGlobal, value1 = 5, value2 = 10,
+ getter = { getDnsResolverSuccessThresholdPercent(context, 0 /* def */) },
+ setter = { setDnsResolverSuccessThresholdPercent(context, it) },
+ testIntValues = intArrayOf(5))
+
+ assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") {
+ setDnsResolverSuccessThresholdPercent(context, -1) }
+ assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") {
+ setDnsResolverSuccessThresholdPercent(context, 120) }
+ }
+
+ @Test
+ fun testDnsResolverSampleRanges() {
+ testIntSetting(names = arrayOf(DNS_RESOLVER_MIN_SAMPLES, DNS_RESOLVER_MAX_SAMPLES),
+ type = settingsTypeGlobal, value1 = Range(1, 63), value2 = Range(2, 62),
+ getter = { getDnsResolverSampleRanges(context) },
+ setter = { setDnsResolverSampleRanges(context, it) },
+ testIntValues = intArrayOf(1, 63))
+
+ assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") {
+ setDnsResolverSampleRanges(context, Range(-1, 62)) }
+ assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") {
+ setDnsResolverSampleRanges(context, Range(2, 65)) }
+ }
+
+ @Test
+ fun testNetworkSwitchNotificationMaximumDailyCount() {
+ testIntSetting(names = arrayOf(NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT),
+ type = settingsTypeGlobal, value1 = 5, value2 = 15,
+ getter = { getNetworkSwitchNotificationMaximumDailyCount(context, 0 /* def */) },
+ setter = { setNetworkSwitchNotificationMaximumDailyCount(context, it) },
+ testIntValues = intArrayOf(5))
+
+ assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") {
+ setNetworkSwitchNotificationMaximumDailyCount(context, -1) }
+ }
+
+ @Test
+ fun testNetworkSwitchNotificationRateDuration() {
+ testIntSetting(names = arrayOf(NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS),
+ type = settingsTypeGlobal, value1 = Duration.ofMillis(testTime1),
+ value2 = Duration.ofMillis(testTime2),
+ getter = { getNetworkSwitchNotificationRateDuration(context, defaultDuration) },
+ setter = { setNetworkSwitchNotificationRateDuration(context, it) },
+ testIntValues = intArrayOf(testTime1.toInt()))
+
+ assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") {
+ setNetworkSwitchNotificationRateDuration(context, Duration.ofMillis(-1L)) }
+ }
+
+ @Test
+ fun testCaptivePortalMode() {
+ testIntSetting(names = arrayOf(CAPTIVE_PORTAL_MODE), type = settingsTypeGlobal,
+ value1 = CAPTIVE_PORTAL_MODE_AVOID, value2 = CAPTIVE_PORTAL_MODE_PROMPT,
+ getter = { getCaptivePortalMode(context, CAPTIVE_PORTAL_MODE_IGNORE) },
+ setter = { setCaptivePortalMode(context, it) },
+ testIntValues = intArrayOf(CAPTIVE_PORTAL_MODE_AVOID))
+
+ assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") {
+ setCaptivePortalMode(context, 5 /* mode */) }
+ }
+
+ @Test
+ fun testPrivateDnsDefaultMode() {
+ val original = Settings.Global.getString(resolver, PRIVATE_DNS_DEFAULT_MODE)
+
+ try {
+ val mode = getPrivateDnsModeAsString(PRIVATE_DNS_MODE_OPPORTUNISTIC)
+ Settings.Global.putString(resolver, PRIVATE_DNS_DEFAULT_MODE, mode)
+ assertEquals(mode, getPrivateDnsDefaultMode(context))
+
+ setPrivateDnsDefaultMode(context, PRIVATE_DNS_MODE_OFF)
+ assertEquals(getPrivateDnsModeAsString(PRIVATE_DNS_MODE_OFF),
+ getPrivateDnsDefaultMode(context))
+ } finally {
+ resetSettings(names = arrayOf(PRIVATE_DNS_DEFAULT_MODE), type = settingsTypeGlobal,
+ values = arrayOf(original))
+ }
+
+ assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") {
+ setPrivateDnsDefaultMode(context, -1) }
+ }
+
+ @Test
+ fun testConnectivityKeepPendingIntentDuration() {
+ testIntSetting(names = arrayOf(CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS),
+ type = settingsTypeSecure, value1 = Duration.ofMillis(testTime1),
+ value2 = Duration.ofMillis(testTime2),
+ getter = { getConnectivityKeepPendingIntentDuration(context, defaultDuration) },
+ setter = { setConnectivityKeepPendingIntentDuration(context, it) },
+ testIntValues = intArrayOf(testTime1.toInt()))
+
+ assertFailsWith<IllegalArgumentException>("Expect fail but argument accepted.") {
+ setConnectivityKeepPendingIntentDuration(context, Duration.ofMillis(-1L)) }
+ }
+
+ @Test
+ fun testMobileDataAlwaysOn() {
+ testIntSetting(names = arrayOf(MOBILE_DATA_ALWAYS_ON), type = settingsTypeGlobal,
+ value1 = false, value2 = true,
+ getter = { getMobileDataAlwaysOn(context, true /* def */) },
+ setter = { setMobileDataAlwaysOn(context, it) },
+ testIntValues = intArrayOf(0))
+ }
+
+ @Test
+ fun testWifiAlwaysRequested() {
+ testIntSetting(names = arrayOf(WIFI_ALWAYS_REQUESTED), type = settingsTypeGlobal,
+ value1 = false, value2 = true,
+ getter = { getWifiAlwaysRequested(context, true /* def */) },
+ setter = { setWifiAlwaysRequested(context, it) },
+ testIntValues = intArrayOf(0))
+ }
+}
\ No newline at end of file
diff --git a/tests/common/java/android/net/InvalidPacketExceptionTest.kt b/tests/common/java/android/net/InvalidPacketExceptionTest.kt
new file mode 100644
index 0000000..320ac27
--- /dev/null
+++ b/tests/common/java/android/net/InvalidPacketExceptionTest.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net
+
+import android.os.Build
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SdkSuppress
+import org.junit.runner.RunWith
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+@RunWith(AndroidJUnit4::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+class InvalidPacketExceptionTest {
+ @Test
+ fun testConstructor() {
+ assertEquals(123, InvalidPacketException(123).error)
+ assertEquals(0, InvalidPacketException(0).error)
+ assertEquals(-123, InvalidPacketException(-123).error)
+ }
+}
\ No newline at end of file
diff --git a/tests/cts/net/src/android/net/cts/BatteryStatsManagerTest.java b/tests/cts/net/src/android/net/cts/BatteryStatsManagerTest.java
new file mode 100644
index 0000000..a54fd64
--- /dev/null
+++ b/tests/cts/net/src/android/net/cts/BatteryStatsManagerTest.java
@@ -0,0 +1,195 @@
+/*
+ * 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.cts;
+
+import static android.Manifest.permission.UPDATE_DEVICE_STATS;
+
+import static androidx.test.InstrumentationRegistry.getContext;
+
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+import static com.android.testutils.MiscAsserts.assertThrows;
+import static com.android.testutils.TestPermissionUtil.runAsShell;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.cts.util.CtsNetUtils;
+import android.os.BatteryStatsManager;
+import android.os.Build;
+import android.os.connectivity.CellularBatteryStats;
+import android.os.connectivity.WifiBatteryStats;
+import android.util.Log;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.SkipPresubmit;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+
+/**
+ * Test for BatteryStatsManager.
+ */
+@RunWith(AndroidJUnit4.class)
+public class BatteryStatsManagerTest{
+ @Rule
+ public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
+ private static final String TAG = BatteryStatsManagerTest.class.getSimpleName();
+ private static final String TEST_URL = "https://connectivitycheck.gstatic.com/generate_204";
+ // This value should be the same as BatteryStatsManager.BATTERY_STATUS_DISCHARGING.
+ // TODO: Use the constant once it's available in all branches
+ private static final int BATTERY_STATUS_DISCHARGING = 3;
+
+ private Context mContext;
+ private BatteryStatsManager mBsm;
+ private ConnectivityManager mCm;
+ private CtsNetUtils mCtsNetUtils;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = getContext();
+ mBsm = mContext.getSystemService(BatteryStatsManager.class);
+ mCm = mContext.getSystemService(ConnectivityManager.class);
+ mCtsNetUtils = new CtsNetUtils(mContext);
+ }
+
+ @Test
+ @SkipPresubmit(reason = "Virtual hardware does not support wifi battery stats")
+ public void testReportNetworkInterfaceForTransports() throws Exception {
+ try {
+ final Network cellNetwork = mCtsNetUtils.connectToCell();
+ final URL url = new URL(TEST_URL);
+
+ // Make sure wifi is disabled.
+ mCtsNetUtils.ensureWifiDisconnected(null /* wifiNetworkToCheck */);
+ // Simulate the device being unplugged from charging.
+ executeShellCommand("dumpsys battery unplug");
+ executeShellCommand("dumpsys battery set status " + BATTERY_STATUS_DISCHARGING);
+ executeShellCommand("dumpsys batterystats enable pretend-screen-off");
+
+ // Get cellular battery stats
+ CellularBatteryStats cellularStatsBefore = runAsShell(UPDATE_DEVICE_STATS,
+ mBsm::getCellularBatteryStats);
+
+ // Generate traffic on cellular network.
+ generateNetworkTraffic(cellNetwork, url);
+
+ // The mobile battery stats are updated when a network stops being the default network.
+ // ConnectivityService will call BatteryStatsManager.reportMobileRadioPowerState when
+ // removing data activity tracking.
+ final Network wifiNetwork = mCtsNetUtils.ensureWifiConnected();
+
+ // Check cellular battery stats are updated.
+ runAsShell(UPDATE_DEVICE_STATS,
+ () -> assertStatsEventually(mBsm::getCellularBatteryStats,
+ cellularStatsAfter -> cellularBatteryStatsIncreased(
+ cellularStatsBefore, cellularStatsAfter)));
+
+ WifiBatteryStats wifiStatsBefore = runAsShell(UPDATE_DEVICE_STATS,
+ mBsm::getWifiBatteryStats);
+
+ // Generate traffic on wifi network.
+ generateNetworkTraffic(wifiNetwork, url);
+ // Wifi battery stats are updated when wifi on.
+ mCtsNetUtils.toggleWifi();
+
+ // Check wifi battery stats are updated.
+ runAsShell(UPDATE_DEVICE_STATS,
+ () -> assertStatsEventually(mBsm::getWifiBatteryStats,
+ wifiStatsAfter -> wifiBatteryStatsIncreased(wifiStatsBefore,
+ wifiStatsAfter)));
+ } finally {
+ // Reset battery settings.
+ executeShellCommand("dumpsys battery reset");
+ executeShellCommand("dumpsys batterystats disable pretend-screen-off");
+ }
+ }
+
+ @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+ @Test
+ public void testReportNetworkInterfaceForTransports_throwsSecurityException()
+ throws Exception {
+ Network wifiNetwork = mCtsNetUtils.ensureWifiConnected();
+ final String iface = mCm.getLinkProperties(wifiNetwork).getInterfaceName();
+ final int[] transportType = mCm.getNetworkCapabilities(wifiNetwork).getTransportTypes();
+ assertThrows(SecurityException.class,
+ () -> mBsm.reportNetworkInterfaceForTransports(iface, transportType));
+ }
+
+ private void generateNetworkTraffic(Network network, URL url) throws IOException {
+ HttpURLConnection connection = null;
+ try {
+ connection = (HttpURLConnection) network.openConnection(url);
+ assertEquals(204, connection.getResponseCode());
+ } catch (IOException e) {
+ Log.e(TAG, "Generate traffic failed with exception " + e);
+ } finally {
+ if (connection != null) {
+ connection.disconnect();
+ }
+ }
+ }
+
+ private static <T> void assertStatsEventually(Supplier<T> statsGetter,
+ Predicate<T> statsChecker) throws Exception {
+ // Wait for updating mobile/wifi stats, and check stats every 10ms.
+ final int maxTries = 1000;
+ T result = null;
+ for (int i = 1; i <= maxTries; i++) {
+ result = statsGetter.get();
+ if (statsChecker.test(result)) return;
+ Thread.sleep(10);
+ }
+ final String stats = result instanceof CellularBatteryStats
+ ? "Cellular" : "Wifi";
+ fail(stats + " battery stats did not increase.");
+ }
+
+ private static boolean cellularBatteryStatsIncreased(CellularBatteryStats before,
+ CellularBatteryStats after) {
+ return (after.getNumBytesTx() > before.getNumBytesTx())
+ && (after.getNumBytesRx() > before.getNumBytesRx())
+ && (after.getNumPacketsTx() > before.getNumPacketsTx())
+ && (after.getNumPacketsRx() > before.getNumPacketsRx());
+ }
+
+ private static boolean wifiBatteryStatsIncreased(WifiBatteryStats before,
+ WifiBatteryStats after) {
+ return (after.getNumBytesTx() > before.getNumBytesTx())
+ && (after.getNumBytesRx() > before.getNumBytesRx())
+ && (after.getNumPacketsTx() > before.getNumPacketsTx())
+ && (after.getNumPacketsRx() > before.getNumPacketsRx());
+ }
+
+ private static String executeShellCommand(String command) {
+ final String result = runShellCommand(command).trim();
+ Log.d(TAG, "Output of '" + command + "': '" + result + "'");
+ return result;
+ }
+}
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index c2613c8..4403a0e 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -29,6 +29,8 @@
import static android.content.pm.PackageManager.FEATURE_WIFI_DIRECT;
import static android.content.pm.PackageManager.GET_PERMISSIONS;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.net.ConnectivityManager.EXTRA_NETWORK;
+import static android.net.ConnectivityManager.EXTRA_NETWORK_REQUEST;
import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE;
import static android.net.ConnectivityManager.TYPE_BLUETOOTH;
import static android.net.ConnectivityManager.TYPE_ETHERNET;
@@ -74,12 +76,14 @@
import static com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity;
import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+import static com.android.modules.utils.build.SdkLevel.isAtLeastS;
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.MiscAsserts.assertThrows;
import static com.android.testutils.TestNetworkTrackerKt.initTestNetwork;
import static com.android.testutils.TestPermissionUtil.runAsShell;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
@@ -111,11 +115,15 @@
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
+import android.net.NetworkAgent;
+import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkInfo.State;
+import android.net.NetworkProvider;
import android.net.NetworkRequest;
+import android.net.NetworkScore;
import android.net.NetworkSpecifier;
import android.net.NetworkStateSnapshot;
import android.net.NetworkUtils;
@@ -203,9 +211,12 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -240,6 +251,9 @@
// Airplane Mode BroadcastReceiver Timeout
private static final long AIRPLANE_MODE_CHANGE_TIMEOUT_MS = 10_000L;
+ // Timeout for applying uids allowed on restricted networks
+ private static final long APPLYING_UIDS_ALLOWED_ON_RESTRICTED_NETWORKS_TIMEOUT_MS = 3_000L;
+
// Minimum supported keepalive counts for wifi and cellular.
public static final int MIN_SUPPORTED_CELLULAR_KEEPALIVE_COUNT = 1;
public static final int MIN_SUPPORTED_WIFI_KEEPALIVE_COUNT = 3;
@@ -523,8 +537,10 @@
Objects.requireNonNull(mCm.getNetworkCapabilities(network));
// Redact specifier of the capabilities of the snapshot before comparing since
// the result returned from getNetworkCapabilities always get redacted.
+ final NetworkSpecifier snapshotCapSpecifier =
+ snapshot.getNetworkCapabilities().getNetworkSpecifier();
final NetworkSpecifier redactedSnapshotCapSpecifier =
- snapshot.getNetworkCapabilities().getNetworkSpecifier().redact();
+ snapshotCapSpecifier == null ? null : snapshotCapSpecifier.redact();
assertEquals("", caps.describeImmutableDifferences(
snapshot.getNetworkCapabilities()
.setNetworkSpecifier(redactedSnapshotCapSpecifier)));
@@ -721,6 +737,8 @@
.isPrivateDnsBroken()) && networkForPrivateDns.equals(entry.getNetwork()));
} finally {
mCtsNetUtils.restorePrivateDnsSetting();
+ // Toggle wifi to make sure it is re-validated
+ reconnectWifi();
}
}
@@ -849,6 +867,117 @@
}
}
+ private void runIdenticalPendingIntentsRequestTest(boolean useListen) throws Exception {
+ assumeTrue(mPackageManager.hasSystemFeature(FEATURE_WIFI));
+
+ // Disconnect before registering callbacks, reconnect later to fire them
+ mCtsNetUtils.ensureWifiDisconnected(null);
+
+ final NetworkRequest firstRequest = makeWifiNetworkRequest();
+ final NetworkRequest secondRequest = new NetworkRequest(firstRequest);
+ // Will match wifi or test, since transports are ORed; but there should only be wifi
+ secondRequest.networkCapabilities.addTransportType(TRANSPORT_TEST);
+
+ PendingIntent firstIntent = null;
+ PendingIntent secondIntent = null;
+ BroadcastReceiver receiver = null;
+
+ // Avoid receiving broadcasts from other runs by appending a timestamp
+ final String broadcastAction = NETWORK_CALLBACK_ACTION + System.currentTimeMillis();
+ try {
+ // TODO: replace with PendingIntent.FLAG_MUTABLE when this code compiles against S+
+ // Intent is mutable to receive EXTRA_NETWORK_REQUEST from ConnectivityService
+ final int pendingIntentFlagMutable = 1 << 25;
+ final String extraBoolKey = "extra_bool";
+ firstIntent = PendingIntent.getBroadcast(mContext,
+ 0 /* requestCode */,
+ new Intent(broadcastAction).putExtra(extraBoolKey, false),
+ PendingIntent.FLAG_UPDATE_CURRENT | pendingIntentFlagMutable);
+
+ if (useListen) {
+ mCm.registerNetworkCallback(firstRequest, firstIntent);
+ } else {
+ mCm.requestNetwork(firstRequest, firstIntent);
+ }
+
+ // Second intent equals the first as per filterEquals (extras don't count), so first
+ // intent will be updated with the new extras
+ secondIntent = PendingIntent.getBroadcast(mContext,
+ 0 /* requestCode */,
+ new Intent(broadcastAction).putExtra(extraBoolKey, true),
+ PendingIntent.FLAG_UPDATE_CURRENT | pendingIntentFlagMutable);
+
+ // Because secondIntent.intentFilterEquals the first, the request should be replaced
+ if (useListen) {
+ mCm.registerNetworkCallback(secondRequest, secondIntent);
+ } else {
+ mCm.requestNetwork(secondRequest, secondIntent);
+ }
+
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(broadcastAction);
+
+ final CompletableFuture<Network> networkFuture = new CompletableFuture<>();
+ final AtomicInteger receivedCount = new AtomicInteger(0);
+ receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final NetworkRequest request = intent.getParcelableExtra(EXTRA_NETWORK_REQUEST);
+ assertPendingIntentRequestMatches(request, secondRequest, useListen);
+ receivedCount.incrementAndGet();
+ networkFuture.complete(intent.getParcelableExtra(EXTRA_NETWORK));
+ }
+ };
+ mContext.registerReceiver(receiver, filter);
+
+ final Network wifiNetwork = mCtsNetUtils.ensureWifiConnected();
+ try {
+ assertEquals(wifiNetwork, networkFuture.get(
+ NETWORK_CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ } catch (TimeoutException e) {
+ throw new AssertionError("PendingIntent not received for " + secondRequest, e);
+ }
+
+ // Sleep for a small amount of time to try to check that only one callback is ever
+ // received (so the first callback was really unregistered). This does not guarantee
+ // that the test will fail if it runs very slowly, but it should at least be very
+ // noticeably flaky.
+ Thread.sleep(NO_CALLBACK_TIMEOUT_MS);
+
+ // For R- frameworks, listens will receive duplicated callbacks. See b/189868426.
+ if (isAtLeastS() || !useListen) {
+ assertEquals("PendingIntent should only be received once", 1, receivedCount.get());
+ }
+ } finally {
+ if (firstIntent != null) mCm.unregisterNetworkCallback(firstIntent);
+ if (secondIntent != null) mCm.unregisterNetworkCallback(secondIntent);
+ if (receiver != null) mContext.unregisterReceiver(receiver);
+ mCtsNetUtils.ensureWifiConnected();
+ }
+ }
+
+ private void assertPendingIntentRequestMatches(NetworkRequest broadcasted, NetworkRequest filed,
+ boolean useListen) {
+ assertArrayEquals(filed.networkCapabilities.getCapabilities(),
+ broadcasted.networkCapabilities.getCapabilities());
+ // For R- frameworks, listens will receive duplicated callbacks. See b/189868426.
+ if (!isAtLeastS() && useListen) return;
+ assertArrayEquals(filed.networkCapabilities.getTransportTypes(),
+ broadcasted.networkCapabilities.getTransportTypes());
+ }
+
+ @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
+ @Test
+ public void testRegisterNetworkRequest_identicalPendingIntents() throws Exception {
+ runIdenticalPendingIntentsRequestTest(false /* useListen */);
+ }
+
+ @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
+ @Test
+ public void testRegisterNetworkCallback_identicalPendingIntents() throws Exception {
+ runIdenticalPendingIntentsRequestTest(true /* useListen */);
+ }
+
/**
* Exercises the requestNetwork with NetworkCallback API. This checks to
* see if we get a callback for an INTERNET request.
@@ -2399,8 +2528,7 @@
} finally {
resetValidationConfig();
// Reconnect wifi to reset the wifi status
- mCtsNetUtils.ensureWifiDisconnected(null /* wifiNetworkToCheck */);
- mCtsNetUtils.ensureWifiConnected();
+ reconnectWifi();
}
}
@@ -2475,6 +2603,88 @@
}
}
+ @AppModeFull(reason = "WRITE_DEVICE_CONFIG permission can't be granted to instant apps")
+ @Test
+ public void testSetAvoidUnvalidated() throws Exception {
+ assumeTrue(TestUtils.shouldTestSApis());
+ // TODO: Allow in debuggable ROM only. To be replaced by FabricatedOverlay
+ assumeTrue(Build.isDebuggable());
+ final boolean canRunTest = mPackageManager.hasSystemFeature(FEATURE_WIFI)
+ && mPackageManager.hasSystemFeature(FEATURE_TELEPHONY);
+ assumeTrue("testSetAvoidUnvalidated cannot execute"
+ + " unless device supports WiFi and telephony", canRunTest);
+
+ final TestableNetworkCallback wifiCb = new TestableNetworkCallback();
+ final TestableNetworkCallback defaultCb = new TestableNetworkCallback();
+ final int previousAvoidBadWifi =
+ ConnectivitySettingsManager.getNetworkAvoidBadWifi(mContext);
+
+ allowBadWifi();
+
+ final Network cellNetwork = mCtsNetUtils.connectToCell();
+ final Network wifiNetwork = prepareValidatedNetwork();
+
+ mCm.registerDefaultNetworkCallback(defaultCb);
+ mCm.registerNetworkCallback(makeWifiNetworkRequest(), wifiCb);
+
+ try {
+ // Verify wifi is the default network.
+ defaultCb.eventuallyExpect(CallbackEntry.AVAILABLE, NETWORK_CALLBACK_TIMEOUT_MS,
+ entry -> wifiNetwork.equals(entry.getNetwork()));
+ wifiCb.eventuallyExpect(CallbackEntry.AVAILABLE, NETWORK_CALLBACK_TIMEOUT_MS,
+ entry -> wifiNetwork.equals(entry.getNetwork()));
+ assertTrue(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
+ NET_CAPABILITY_VALIDATED));
+
+ // Configure response code for unvalidated network
+ configTestServer(Status.INTERNAL_ERROR, Status.INTERNAL_ERROR);
+ mCm.reportNetworkConnectivity(wifiNetwork, false);
+ // Default network should stay on unvalidated wifi because avoid bad wifi is disabled.
+ defaultCb.eventuallyExpect(CallbackEntry.NETWORK_CAPS_UPDATED,
+ NETWORK_CALLBACK_TIMEOUT_MS,
+ entry -> !((CallbackEntry.CapabilitiesChanged) entry).getCaps()
+ .hasCapability(NET_CAPABILITY_VALIDATED));
+ wifiCb.eventuallyExpect(CallbackEntry.NETWORK_CAPS_UPDATED,
+ NETWORK_CALLBACK_TIMEOUT_MS,
+ entry -> !((CallbackEntry.CapabilitiesChanged) entry).getCaps()
+ .hasCapability(NET_CAPABILITY_VALIDATED));
+
+ runAsShell(NETWORK_SETTINGS, () -> {
+ mCm.setAvoidUnvalidated(wifiNetwork);
+ });
+ // Default network should be updated to validated cellular network.
+ defaultCb.eventuallyExpect(CallbackEntry.AVAILABLE, NETWORK_CALLBACK_TIMEOUT_MS,
+ entry -> cellNetwork.equals(entry.getNetwork()));
+ // No update on wifi callback.
+ wifiCb.assertNoCallback();
+ } finally {
+ mCm.unregisterNetworkCallback(wifiCb);
+ mCm.unregisterNetworkCallback(defaultCb);
+ resetAvoidBadWifi(previousAvoidBadWifi);
+ resetValidationConfig();
+ // Reconnect wifi to reset the wifi status
+ reconnectWifi();
+ }
+ }
+
+ private void resetAvoidBadWifi(int settingValue) {
+ setTestAllowBadWifiResource(0 /* timeMs */);
+ ConnectivitySettingsManager.setNetworkAvoidBadWifi(mContext, settingValue);
+ }
+
+ private void allowBadWifi() {
+ setTestAllowBadWifiResource(
+ System.currentTimeMillis() + WIFI_CONNECT_TIMEOUT_MS /* timeMs */);
+ ConnectivitySettingsManager.setNetworkAvoidBadWifi(mContext,
+ ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI_IGNORE);
+ }
+
+ private void setTestAllowBadWifiResource(long timeMs) {
+ runAsShell(NETWORK_SETTINGS, () -> {
+ mCm.setTestAllowBadWifiUntil(timeMs);
+ });
+ }
+
private Network expectNetworkHasCapability(Network network, int expectedNetCap, long timeout)
throws Exception {
final CompletableFuture<Network> future = new CompletableFuture();
@@ -2514,6 +2724,21 @@
mHttpServer.start();
}
+ private Network reconnectWifi() {
+ mCtsNetUtils.ensureWifiDisconnected(null /* wifiNetworkToCheck */);
+ return mCtsNetUtils.ensureWifiConnected();
+ }
+
+ private Network prepareValidatedNetwork() throws Exception {
+ prepareHttpServer();
+ configTestServer(Status.NO_CONTENT, Status.NO_CONTENT);
+ // Disconnect wifi first then start wifi network with configuration.
+ final Network wifiNetwork = reconnectWifi();
+
+ return expectNetworkHasCapability(wifiNetwork, NET_CAPABILITY_VALIDATED,
+ WIFI_CONNECT_TIMEOUT_MS);
+ }
+
private Network preparePartialConnectivity() throws Exception {
prepareHttpServer();
// Configure response code for partial connectivity
@@ -2633,4 +2858,110 @@
mContext, mobileDataPreferredUids);
}
}
+
+ /** Wait for assigned time. */
+ private void waitForMs(long ms) {
+ try {
+ Thread.sleep(ms);
+ } catch (InterruptedException e) {
+ fail("Thread was interrupted");
+ }
+ }
+
+ private void assertBindSocketToNetworkSuccess(final Network network) throws Exception {
+ final CompletableFuture<Boolean> future = new CompletableFuture<>();
+ final ExecutorService executor = Executors.newSingleThreadExecutor();
+ try {
+ executor.execute(() -> {
+ for (int i = 0; i < 30; i++) {
+ waitForMs(100);
+
+ try (Socket socket = new Socket()) {
+ network.bindSocket(socket);
+ future.complete(true);
+ return;
+ } catch (IOException e) { }
+ }
+ });
+ assertTrue(future.get(APPLYING_UIDS_ALLOWED_ON_RESTRICTED_NETWORKS_TIMEOUT_MS,
+ TimeUnit.MILLISECONDS));
+ } finally {
+ executor.shutdown();
+ }
+ }
+
+ @AppModeFull(reason = "WRITE_SECURE_SETTINGS permission can't be granted to instant apps")
+ @Test
+ public void testUidsAllowedOnRestrictedNetworks() throws Exception {
+ assumeTrue(TestUtils.shouldTestSApis());
+
+ final int uid = mPackageManager.getPackageUid(mContext.getPackageName(), 0 /* flag */);
+ final Set<Integer> originalUidsAllowedOnRestrictedNetworks =
+ ConnectivitySettingsManager.getUidsAllowedOnRestrictedNetworks(mContext);
+ // CtsNetTestCases uid should not list in UIDS_ALLOWED_ON_RESTRICTED_NETWORKS setting
+ // because it has been just installed to device. In case the uid is existed in setting
+ // mistakenly, try to remove the uid and set correct uids to setting.
+ originalUidsAllowedOnRestrictedNetworks.remove(uid);
+ ConnectivitySettingsManager.setUidsAllowedOnRestrictedNetworks(mContext,
+ originalUidsAllowedOnRestrictedNetworks);
+
+ final Handler h = new Handler(Looper.getMainLooper());
+ final TestableNetworkCallback testNetworkCb = new TestableNetworkCallback();
+ mCm.registerBestMatchingNetworkCallback(new NetworkRequest.Builder().clearCapabilities()
+ .addTransportType(NetworkCapabilities.TRANSPORT_TEST).build(), testNetworkCb, h);
+
+ // Create test network agent with restricted network.
+ final NetworkCapabilities nc = new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_TEST)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
+ .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
+ .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+ .build();
+ final NetworkScore score = new NetworkScore.Builder()
+ .setExiting(false)
+ .setTransportPrimary(false)
+ .setKeepConnectedReason(NetworkScore.KEEP_CONNECTED_FOR_HANDOVER)
+ .build();
+ final NetworkAgent agent = new NetworkAgent(mContext, Looper.getMainLooper(),
+ TAG, nc, new LinkProperties(), score, new NetworkAgentConfig.Builder().build(),
+ new NetworkProvider(mContext, Looper.getMainLooper(), TAG)) {};
+ runWithShellPermissionIdentity(() -> agent.register(),
+ android.Manifest.permission.MANAGE_TEST_NETWORKS);
+ agent.markConnected();
+
+ final Network network = agent.getNetwork();
+
+ try (Socket socket = new Socket()) {
+ testNetworkCb.eventuallyExpect(CallbackEntry.AVAILABLE, NETWORK_CALLBACK_TIMEOUT_MS,
+ entry -> network.equals(entry.getNetwork()));
+ // Verify that the network is restricted.
+ final NetworkCapabilities testNetworkNc = mCm.getNetworkCapabilities(network);
+ assertNotNull(testNetworkNc);
+ assertFalse(testNetworkNc.hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED));
+ // CtsNetTestCases package doesn't hold CONNECTIVITY_USE_RESTRICTED_NETWORKS, so it
+ // does not allow to bind socket to restricted network.
+ assertThrows(IOException.class, () -> network.bindSocket(socket));
+
+ // Add CtsNetTestCases uid to UIDS_ALLOWED_ON_RESTRICTED_NETWORKS setting, then it can
+ // bind socket to restricted network normally.
+ final Set<Integer> newUidsAllowedOnRestrictedNetworks =
+ new ArraySet<>(originalUidsAllowedOnRestrictedNetworks);
+ newUidsAllowedOnRestrictedNetworks.add(uid);
+ ConnectivitySettingsManager.setUidsAllowedOnRestrictedNetworks(mContext,
+ newUidsAllowedOnRestrictedNetworks);
+ // Wait a while for sending allowed uids on the restricted network to netd.
+ // TODD: Have a significant signal to know the uids has been send to netd.
+ assertBindSocketToNetworkSuccess(network);
+ } finally {
+ mCm.unregisterNetworkCallback(testNetworkCb);
+ agent.unregister();
+
+ // Restore setting.
+ ConnectivitySettingsManager.setUidsAllowedOnRestrictedNetworks(mContext,
+ originalUidsAllowedOnRestrictedNetworks);
+ }
+ }
}
diff --git a/tests/cts/net/src/android/net/cts/IpSecBaseTest.java b/tests/cts/net/src/android/net/cts/IpSecBaseTest.java
index c54ee91..7f710d7 100644
--- a/tests/cts/net/src/android/net/cts/IpSecBaseTest.java
+++ b/tests/cts/net/src/android/net/cts/IpSecBaseTest.java
@@ -23,6 +23,7 @@
import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA384;
import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA512;
import static android.net.IpSecAlgorithm.CRYPT_AES_CBC;
+import static android.system.OsConstants.FIONREAD;
import static org.junit.Assert.assertArrayEquals;
@@ -32,8 +33,10 @@
import android.net.IpSecManager;
import android.net.IpSecTransform;
import android.platform.test.annotations.AppModeFull;
+import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
+import android.system.StructTimeval;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
@@ -46,15 +49,21 @@
import org.junit.runner.RunWith;
import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
-import java.net.ServerSocket;
import java.net.Socket;
+import java.net.SocketAddress;
import java.net.SocketException;
+import java.net.SocketImpl;
+import java.net.SocketOptions;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
@@ -232,6 +241,12 @@
public NativeTcpSocket(FileDescriptor fd) {
super(fd);
}
+
+ public JavaTcpSocket acceptToJavaSocket() throws Exception {
+ InetSocketAddress peer = new InetSocketAddress(0);
+ FileDescriptor newFd = Os.accept(mFd, peer);
+ return new JavaTcpSocket(new AcceptedTcpFileDescriptorSocket(newFd, peer, getPort()));
+ }
}
public static class NativeUdpSocket extends NativeSocket implements GenericUdpSocket {
@@ -357,6 +372,137 @@
}
}
+ private static class AcceptedTcpFileDescriptorSocket extends Socket {
+
+ AcceptedTcpFileDescriptorSocket(FileDescriptor fd, InetSocketAddress remote,
+ int localPort) throws IOException {
+ super(new FileDescriptorSocketImpl(fd, remote, localPort));
+ connect(remote);
+ }
+
+ private static class FileDescriptorSocketImpl extends SocketImpl {
+
+ private FileDescriptorSocketImpl(FileDescriptor fd, InetSocketAddress remote,
+ int localPort) {
+ this.fd = fd;
+ this.address = remote.getAddress();
+ this.port = remote.getPort();
+ this.localport = localPort;
+ }
+
+ @Override
+ protected void create(boolean stream) throws IOException {
+ // The socket has been created.
+ }
+
+ @Override
+ protected void connect(String host, int port) throws IOException {
+ // The socket has connected.
+ }
+
+ @Override
+ protected void connect(InetAddress address, int port) throws IOException {
+ // The socket has connected.
+ }
+
+ @Override
+ protected void connect(SocketAddress address, int timeout) throws IOException {
+ // The socket has connected.
+ }
+
+ @Override
+ protected void bind(InetAddress host, int port) throws IOException {
+ // The socket is bounded.
+ }
+
+ @Override
+ protected void listen(int backlog) throws IOException {
+ throw new UnsupportedOperationException("listen");
+ }
+
+ @Override
+ protected void accept(SocketImpl s) throws IOException {
+ throw new UnsupportedOperationException("accept");
+ }
+
+ @Override
+ protected InputStream getInputStream() throws IOException {
+ return new FileInputStream(fd);
+ }
+
+ @Override
+ protected OutputStream getOutputStream() throws IOException {
+ return new FileOutputStream(fd);
+ }
+
+ @Override
+ protected int available() throws IOException {
+ try {
+ return Os.ioctlInt(fd, FIONREAD);
+ } catch (ErrnoException e) {
+ throw new IOException(e);
+ }
+ }
+
+ @Override
+ protected void close() throws IOException {
+ try {
+ Os.close(fd);
+ } catch (ErrnoException e) {
+ throw new IOException(e);
+ }
+ }
+
+ @Override
+ protected void sendUrgentData(int data) throws IOException {
+ throw new UnsupportedOperationException("sendUrgentData");
+ }
+
+ @Override
+ public void setOption(int optID, Object value) throws SocketException {
+ try {
+ setOptionInternal(optID, value);
+ } catch (ErrnoException e) {
+ throw new SocketException(e.getMessage());
+ }
+ }
+
+ private void setOptionInternal(int optID, Object value) throws ErrnoException,
+ SocketException {
+ switch(optID) {
+ case SocketOptions.SO_TIMEOUT:
+ int millis = (Integer) value;
+ StructTimeval tv = StructTimeval.fromMillis(millis);
+ Os.setsockoptTimeval(fd, OsConstants.SOL_SOCKET, OsConstants.SO_RCVTIMEO,
+ tv);
+ return;
+ default:
+ throw new SocketException("Unknown socket option: " + optID);
+ }
+ }
+
+ @Override
+ public Object getOption(int optID) throws SocketException {
+ try {
+ return getOptionInternal(optID);
+ } catch (ErrnoException e) {
+ throw new SocketException(e.getMessage());
+ }
+ }
+
+ private Object getOptionInternal(int optID) throws ErrnoException, SocketException {
+ switch (optID) {
+ case SocketOptions.SO_LINGER:
+ // Returns an arbitrary value because IpSecManager doesn't actually
+ // use this value.
+ return 10;
+ default:
+ throw new SocketException("Unknown socket option: " + optID);
+ }
+ }
+ }
+ }
+
public static class SocketPair<T> {
public final T mLeftSock;
public final T mRightSock;
@@ -441,8 +587,6 @@
public static SocketPair<JavaTcpSocket> getJavaTcpSocketPair(
InetAddress localAddr, IpSecManager ism, IpSecTransform transform) throws Exception {
JavaTcpSocket clientSock = new JavaTcpSocket(new Socket());
- ServerSocket serverSocket = new ServerSocket();
- serverSocket.bind(new InetSocketAddress(localAddr, 0));
// While technically the client socket does not need to be bound, the OpenJDK implementation
// of Socket only allocates an FD when bind() or connect() or other similar methods are
@@ -451,16 +595,19 @@
clientSock.mSocket.bind(new InetSocketAddress(localAddr, 0));
// IpSecService doesn't support serverSockets at the moment; workaround using FD
- FileDescriptor serverFd = serverSocket.getImpl().getFD$();
+ NativeTcpSocket server = new NativeTcpSocket(
+ Os.socket(getDomain(localAddr), OsConstants.SOCK_STREAM, OsConstants.IPPROTO_TCP));
+ Os.bind(server.mFd, localAddr, 0);
- applyTransformBidirectionally(ism, transform, new NativeTcpSocket(serverFd));
+ applyTransformBidirectionally(ism, transform, server);
applyTransformBidirectionally(ism, transform, clientSock);
- clientSock.mSocket.connect(new InetSocketAddress(localAddr, serverSocket.getLocalPort()));
- JavaTcpSocket acceptedSock = new JavaTcpSocket(serverSocket.accept());
+ Os.listen(server.mFd, 10 /* backlog */);
+ clientSock.mSocket.connect(new InetSocketAddress(localAddr, server.getPort()));
+ JavaTcpSocket acceptedSock = server.acceptToJavaSocket();
applyTransformBidirectionally(ism, transform, acceptedSock);
- serverSocket.close();
+ server.close();
return new SocketPair<>(clientSock, acceptedSock);
}
diff --git a/tests/cts/net/src/android/net/cts/IpSecManagerTunnelTest.java b/tests/cts/net/src/android/net/cts/IpSecManagerTunnelTest.java
index ae38faa..a9a3380 100644
--- a/tests/cts/net/src/android/net/cts/IpSecManagerTunnelTest.java
+++ b/tests/cts/net/src/android/net/cts/IpSecManagerTunnelTest.java
@@ -43,6 +43,7 @@
import android.net.ConnectivityManager;
import android.net.IpSecAlgorithm;
import android.net.IpSecManager;
+import android.net.IpSecManager.IpSecTunnelInterface;
import android.net.IpSecTransform;
import android.net.LinkAddress;
import android.net.Network;
@@ -50,25 +51,33 @@
import android.net.TestNetworkManager;
import android.net.cts.PacketUtils.Payload;
import android.net.cts.util.CtsNetUtils;
+import android.os.Build;
import android.os.ParcelFileDescriptor;
import android.platform.test.annotations.AppModeFull;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.NetworkInterface;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+
@RunWith(AndroidJUnit4.class)
@AppModeFull(reason = "MANAGE_TEST_NETWORKS permission can't be granted to instant apps")
public class IpSecManagerTunnelTest extends IpSecBaseTest {
+ @Rule public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
+
private static final String TAG = IpSecManagerTunnelTest.class.getSimpleName();
private static final InetAddress LOCAL_OUTER_4 = InetAddress.parseNumericAddress("192.0.2.1");
@@ -78,6 +87,15 @@
private static final InetAddress REMOTE_OUTER_6 =
InetAddress.parseNumericAddress("2001:db8:1::2");
+ private static final InetAddress LOCAL_OUTER_4_NEW =
+ InetAddress.parseNumericAddress("192.0.2.101");
+ private static final InetAddress REMOTE_OUTER_4_NEW =
+ InetAddress.parseNumericAddress("192.0.2.102");
+ private static final InetAddress LOCAL_OUTER_6_NEW =
+ InetAddress.parseNumericAddress("2001:db8:1::101");
+ private static final InetAddress REMOTE_OUTER_6_NEW =
+ InetAddress.parseNumericAddress("2001:db8:1::102");
+
private static final InetAddress LOCAL_INNER_4 =
InetAddress.parseNumericAddress("198.51.100.1");
private static final InetAddress REMOTE_INNER_4 =
@@ -95,10 +113,9 @@
// Static state to reduce setup/teardown
private static ConnectivityManager sCM;
private static TestNetworkManager sTNM;
- private static ParcelFileDescriptor sTunFd;
- private static TestNetworkCallback sTunNetworkCallback;
- private static Network sTunNetwork;
- private static TunUtils sTunUtils;
+
+ private static TunNetworkWrapper sTunWrapper;
+ private static TunNetworkWrapper sTunWrapperNew;
private static Context sContext = InstrumentationRegistry.getContext();
private static final CtsNetUtils mCtsNetUtils = new CtsNetUtils(sContext);
@@ -116,19 +133,8 @@
// right appop permissions.
mCtsNetUtils.setAppopPrivileged(OP_MANAGE_IPSEC_TUNNELS, true);
- TestNetworkInterface testIface =
- sTNM.createTunInterface(
- new LinkAddress[] {
- new LinkAddress(LOCAL_OUTER_4, IP4_PREFIX_LEN),
- new LinkAddress(LOCAL_OUTER_6, IP6_PREFIX_LEN)
- });
-
- sTunFd = testIface.getFileDescriptor();
- sTunNetworkCallback = mCtsNetUtils.setupAndGetTestNetwork(testIface.getInterfaceName());
- sTunNetworkCallback.waitForAvailable();
- sTunNetwork = sTunNetworkCallback.currentNetwork;
-
- sTunUtils = new TunUtils(sTunFd);
+ sTunWrapper = new TunNetworkWrapper(LOCAL_OUTER_4, LOCAL_OUTER_6);
+ sTunWrapperNew = new TunNetworkWrapper(LOCAL_OUTER_4_NEW, LOCAL_OUTER_6_NEW);
}
@Before
@@ -139,24 +145,76 @@
// Set to true before every run; some tests flip this.
mCtsNetUtils.setAppopPrivileged(OP_MANAGE_IPSEC_TUNNELS, true);
- // Clear sTunUtils state
- sTunUtils.reset();
+ // Clear TunUtils state
+ sTunWrapper.utils.reset();
+ sTunWrapperNew.utils.reset();
+ }
+
+ private static void tearDownTunWrapperIfNotNull(TunNetworkWrapper tunWrapper) throws Exception {
+ if (tunWrapper != null) {
+ tunWrapper.tearDown();
+ }
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
mCtsNetUtils.setAppopPrivileged(OP_MANAGE_IPSEC_TUNNELS, false);
- sCM.unregisterNetworkCallback(sTunNetworkCallback);
-
- sTNM.teardownTestNetwork(sTunNetwork);
- sTunFd.close();
+ tearDownTunWrapperIfNotNull(sTunWrapper);
+ tearDownTunWrapperIfNotNull(sTunWrapperNew);
InstrumentationRegistry.getInstrumentation()
.getUiAutomation()
.dropShellPermissionIdentity();
}
+ private static class TunNetworkWrapper {
+ public final ParcelFileDescriptor fd;
+ public final TestNetworkCallback networkCallback;
+ public final Network network;
+ public final TunUtils utils;
+
+ TunNetworkWrapper(InetAddress... addresses) throws Exception {
+ final LinkAddress[] linkAddresses = new LinkAddress[addresses.length];
+ for (int i = 0; i < linkAddresses.length; i++) {
+ InetAddress addr = addresses[i];
+ if (addr instanceof Inet4Address) {
+ linkAddresses[i] = new LinkAddress(addr, IP4_PREFIX_LEN);
+ } else {
+ linkAddresses[i] = new LinkAddress(addr, IP6_PREFIX_LEN);
+ }
+ }
+
+ try {
+ final TestNetworkInterface testIface = sTNM.createTunInterface(linkAddresses);
+
+ fd = testIface.getFileDescriptor();
+ networkCallback = mCtsNetUtils.setupAndGetTestNetwork(testIface.getInterfaceName());
+ networkCallback.waitForAvailable();
+ network = networkCallback.currentNetwork;
+ } catch (Exception e) {
+ tearDown();
+ throw e;
+ }
+
+ utils = new TunUtils(fd);
+ }
+
+ public void tearDown() throws Exception {
+ if (networkCallback != null) {
+ sCM.unregisterNetworkCallback(networkCallback);
+ }
+
+ if (network != null) {
+ sTNM.teardownTestNetwork(network);
+ }
+
+ if (fd != null) {
+ fd.close();
+ }
+ }
+ }
+
@Test
public void testSecurityExceptionCreateTunnelInterfaceWithoutAppop() throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -166,7 +224,7 @@
// Security exceptions are thrown regardless of IPv4/IPv6. Just test one
try {
- mISM.createIpSecTunnelInterface(LOCAL_INNER_6, REMOTE_INNER_6, sTunNetwork);
+ mISM.createIpSecTunnelInterface(LOCAL_INNER_6, REMOTE_INNER_6, sTunWrapper.network);
fail("Did not throw SecurityException for Tunnel creation without appop");
} catch (SecurityException expected) {
}
@@ -196,11 +254,16 @@
* Runs the test code, and returns the inner socket port, if any.
*
* @param ipsecNetwork The IPsec Interface based Network for binding sockets on
+ * @param tunnelIface The IPsec tunnel interface that will be tested
+ * @param underlyingTunUtils The utility of the IPsec tunnel interface's underlying TUN
+ * network
* @return the integer port of the inner socket if outbound, or 0 if inbound
* IpSecTunnelTestRunnable
* @throws Exception if any part of the test failed.
*/
- public abstract int run(Network ipsecNetwork) throws Exception;
+ public abstract int run(
+ Network ipsecNetwork, IpSecTunnelInterface tunnelIface, TunUtils underlyingTunUtils)
+ throws Exception;
}
private int getPacketSize(
@@ -265,7 +328,9 @@
int expectedPacketSize) {
return new IpSecTunnelTestRunnable() {
@Override
- public int run(Network ipsecNetwork) throws Exception {
+ public int run(
+ Network ipsecNetwork, IpSecTunnelInterface tunnelIface, TunUtils tunUtils)
+ throws Exception {
// Build a socket and send traffic
JavaUdpSocket socket = new JavaUdpSocket(localInner);
ipsecNetwork.bindSocket(socket.mSocket);
@@ -284,7 +349,7 @@
// Verify that an encrypted packet is sent. As of right now, checking encrypted
// body is not possible, due to the test not knowing some of the fields of the
// inner IP header (flow label, flags, etc)
- sTunUtils.awaitEspPacketNoPlaintext(
+ tunUtils.awaitEspPacketNoPlaintext(
spi, TEST_DATA, encapPort != 0, expectedPacketSize);
socket.close();
@@ -312,7 +377,9 @@
throws Exception {
return new IpSecTunnelTestRunnable() {
@Override
- public int run(Network ipsecNetwork) throws Exception {
+ public int run(
+ Network ipsecNetwork, IpSecTunnelInterface tunnelIface, TunUtils tunUtils)
+ throws Exception {
// Build a socket and receive traffic
JavaUdpSocket socket = new JavaUdpSocket(localInner, innerSocketPort);
ipsecNetwork.bindSocket(socket.mSocket);
@@ -325,7 +392,7 @@
socket.mSocket, IpSecManager.DIRECTION_OUT, inTransportTransform);
}
- sTunUtils.reflectPackets();
+ tunUtils.reflectPackets();
// Receive packet from socket, and validate that the payload is correct
receiveAndValidatePacket(socket);
@@ -355,7 +422,9 @@
throws Exception {
return new IpSecTunnelTestRunnable() {
@Override
- public int run(Network ipsecNetwork) throws Exception {
+ public int run(
+ Network ipsecNetwork, IpSecTunnelInterface tunnelIface, TunUtils tunUtils)
+ throws Exception {
// Build a socket and receive traffic
JavaUdpSocket socket = new JavaUdpSocket(localInner);
ipsecNetwork.bindSocket(socket.mSocket);
@@ -391,7 +460,7 @@
socket.getPort(),
encapPort);
}
- sTunUtils.injectPacket(pkt);
+ tunUtils.injectPacket(pkt);
// Receive packet from socket, and validate
receiveAndValidatePacket(socket);
@@ -404,6 +473,161 @@
}
}
+ private class MigrateIpSecTunnelTestRunnableFactory implements IpSecTunnelTestRunnableFactory {
+ private final IpSecTunnelTestRunnableFactory mTestRunnableFactory;
+
+ MigrateIpSecTunnelTestRunnableFactory(boolean isOutputTest) {
+ if (isOutputTest) {
+ mTestRunnableFactory = new OutputIpSecTunnelTestRunnableFactory();
+ } else {
+ mTestRunnableFactory = new InputPacketGeneratorIpSecTunnelTestRunnableFactory();
+ }
+ }
+
+ @Override
+ public IpSecTunnelTestRunnable getIpSecTunnelTestRunnable(
+ boolean transportInTunnelMode,
+ int spi,
+ InetAddress localInner,
+ InetAddress remoteInner,
+ InetAddress localOuter,
+ InetAddress remoteOuter,
+ IpSecTransform inTransportTransform,
+ IpSecTransform outTransportTransform,
+ int encapPort,
+ int unusedInnerSocketPort,
+ int expectedPacketSize) {
+ return new IpSecTunnelTestRunnable() {
+ @Override
+ public int run(
+ Network ipsecNetwork, IpSecTunnelInterface tunnelIface, TunUtils tunUtils)
+ throws Exception {
+ mTestRunnableFactory
+ .getIpSecTunnelTestRunnable(
+ transportInTunnelMode,
+ spi,
+ localInner,
+ remoteInner,
+ localOuter,
+ remoteOuter,
+ inTransportTransform,
+ outTransportTransform,
+ encapPort,
+ unusedInnerSocketPort,
+ expectedPacketSize)
+ .run(ipsecNetwork, tunnelIface, sTunWrapper.utils);
+
+ tunnelIface.setUnderlyingNetwork(sTunWrapperNew.network);
+
+ // Verify migrating to IPv4 and IPv6 addresses. It ensures that not only
+ // can IPsec tunnel migrate across interfaces, IPsec tunnel can also migrate to
+ // a different address on the same interface.
+ checkMigratedTunnel(
+ localInner,
+ remoteInner,
+ LOCAL_OUTER_4_NEW,
+ REMOTE_OUTER_4_NEW,
+ encapPort != 0,
+ transportInTunnelMode,
+ sTunWrapperNew.utils,
+ tunnelIface,
+ ipsecNetwork);
+ checkMigratedTunnel(
+ localInner,
+ remoteInner,
+ LOCAL_OUTER_6_NEW,
+ REMOTE_OUTER_6_NEW,
+ false, // IPv6 does not support UDP encapsulation
+ transportInTunnelMode,
+ sTunWrapperNew.utils,
+ tunnelIface,
+ ipsecNetwork);
+
+ return 0;
+ }
+ };
+ }
+
+ private void checkMigratedTunnel(
+ InetAddress localInner,
+ InetAddress remoteInner,
+ InetAddress localOuter,
+ InetAddress remoteOuter,
+ boolean useEncap,
+ boolean transportInTunnelMode,
+ TunUtils tunUtils,
+ IpSecTunnelInterface tunnelIface,
+ Network ipsecNetwork)
+ throws Exception {
+
+ // Preselect both SPI and encap port, to be used for both inbound and outbound tunnels.
+ // Re-uses the same SPI to ensure that even in cases of symmetric SPIs shared across
+ // tunnel and transport mode, packets are encrypted/decrypted properly based on the
+ // src/dst.
+ int spi = getRandomSpi(localOuter, remoteOuter);
+
+ int innerFamily = localInner instanceof Inet4Address ? AF_INET : AF_INET6;
+ int outerFamily = localOuter instanceof Inet4Address ? AF_INET : AF_INET6;
+ int expectedPacketSize =
+ getPacketSize(innerFamily, outerFamily, useEncap, transportInTunnelMode);
+
+ // Build transport mode transforms and encapsulation socket for verifying
+ // transport-in-tunnel case and encapsulation case.
+ try (IpSecManager.SecurityParameterIndex inTransportSpi =
+ mISM.allocateSecurityParameterIndex(localInner, spi);
+ IpSecManager.SecurityParameterIndex outTransportSpi =
+ mISM.allocateSecurityParameterIndex(remoteInner, spi);
+ IpSecTransform inTransportTransform =
+ buildIpSecTransform(sContext, inTransportSpi, null, remoteInner);
+ IpSecTransform outTransportTransform =
+ buildIpSecTransform(sContext, outTransportSpi, null, localInner);
+ UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) {
+
+ // Configure tunnel mode Transform parameters
+ IpSecTransform.Builder transformBuilder = new IpSecTransform.Builder(sContext);
+ transformBuilder.setEncryption(
+ new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY));
+ transformBuilder.setAuthentication(
+ new IpSecAlgorithm(
+ IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 4));
+
+ if (useEncap) {
+ transformBuilder.setIpv4Encapsulation(encapSocket, encapSocket.getPort());
+ }
+
+ // Apply transform and check that traffic is properly encrypted
+ try (IpSecManager.SecurityParameterIndex inSpi =
+ mISM.allocateSecurityParameterIndex(localOuter, spi);
+ IpSecManager.SecurityParameterIndex outSpi =
+ mISM.allocateSecurityParameterIndex(remoteOuter, spi);
+ IpSecTransform inTransform =
+ transformBuilder.buildTunnelModeTransform(remoteOuter, inSpi);
+ IpSecTransform outTransform =
+ transformBuilder.buildTunnelModeTransform(localOuter, outSpi)) {
+ mISM.applyTunnelModeTransform(
+ tunnelIface, IpSecManager.DIRECTION_IN, inTransform);
+ mISM.applyTunnelModeTransform(
+ tunnelIface, IpSecManager.DIRECTION_OUT, outTransform);
+
+ mTestRunnableFactory
+ .getIpSecTunnelTestRunnable(
+ transportInTunnelMode,
+ spi,
+ localInner,
+ remoteInner,
+ localOuter,
+ remoteOuter,
+ inTransportTransform,
+ outTransportTransform,
+ useEncap ? encapSocket.getPort() : 0,
+ 0,
+ expectedPacketSize)
+ .run(ipsecNetwork, tunnelIface, tunUtils);
+ }
+ }
+ }
+ }
+
private void checkTunnelOutput(
int innerFamily, int outerFamily, boolean useEncap, boolean transportInTunnelMode)
throws Exception {
@@ -426,6 +650,28 @@
new InputPacketGeneratorIpSecTunnelTestRunnableFactory());
}
+ private void checkMigrateTunnelOutput(
+ int innerFamily, int outerFamily, boolean useEncap, boolean transportInTunnelMode)
+ throws Exception {
+ checkTunnel(
+ innerFamily,
+ outerFamily,
+ useEncap,
+ transportInTunnelMode,
+ new MigrateIpSecTunnelTestRunnableFactory(true));
+ }
+
+ private void checkMigrateTunnelInput(
+ int innerFamily, int outerFamily, boolean useEncap, boolean transportInTunnelMode)
+ throws Exception {
+ checkTunnel(
+ innerFamily,
+ outerFamily,
+ useEncap,
+ transportInTunnelMode,
+ new MigrateIpSecTunnelTestRunnableFactory(false));
+ }
+
/**
* Validates that the kernel can talk to itself.
*
@@ -579,7 +825,8 @@
IpSecManager.SecurityParameterIndex outSpi =
mISM.allocateSecurityParameterIndex(remoteOuter, spi);
IpSecManager.IpSecTunnelInterface tunnelIface =
- mISM.createIpSecTunnelInterface(localOuter, remoteOuter, sTunNetwork)) {
+ mISM.createIpSecTunnelInterface(
+ localOuter, remoteOuter, sTunWrapper.network)) {
// Build the test network
tunnelIface.addAddress(localInner, innerPrefixLen);
testNetworkCb = mCtsNetUtils.setupAndGetTestNetwork(tunnelIface.getInterfaceName());
@@ -615,7 +862,7 @@
mISM.applyTunnelModeTransform(
tunnelIface, IpSecManager.DIRECTION_OUT, outTransform);
- innerSocketPort = test.run(testNetwork);
+ innerSocketPort = test.run(testNetwork, tunnelIface, sTunWrapper.utils);
}
// Teardown the test network
@@ -739,6 +986,14 @@
return maybeEncapPacket(srcOuter, dstOuter, encapPort, espPayload).getPacketBytes();
}
+ private void doTestMigrateTunnel(
+ int innerFamily, int outerFamily, boolean useEncap, boolean transportInTunnelMode)
+ throws Exception {
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
+ checkTunnelOutput(innerFamily, outerFamily, useEncap, transportInTunnelMode);
+ checkTunnelInput(innerFamily, outerFamily, useEncap, transportInTunnelMode);
+ }
+
// Transport-in-Tunnel mode tests
@Test
public void testTransportInTunnelModeV4InV4() throws Exception {
@@ -747,6 +1002,12 @@
checkTunnelInput(AF_INET, AF_INET, false, true);
}
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ @Test
+ public void testMigrateTransportInTunnelModeV4InV4() throws Exception {
+ doTestMigrateTunnel(AF_INET, AF_INET, false, true);
+ }
+
@Test
public void testTransportInTunnelModeV4InV4Reflected() throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -760,6 +1021,12 @@
checkTunnelInput(AF_INET, AF_INET, true, true);
}
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ @Test
+ public void testMigrateTransportInTunnelModeV4InV4UdpEncap() throws Exception {
+ doTestMigrateTunnel(AF_INET, AF_INET, true, true);
+ }
+
@Test
public void testTransportInTunnelModeV4InV4UdpEncapReflected() throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -773,6 +1040,12 @@
checkTunnelInput(AF_INET, AF_INET6, false, true);
}
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ @Test
+ public void testMigrateTransportInTunnelModeV4InV6() throws Exception {
+ doTestMigrateTunnel(AF_INET, AF_INET6, false, true);
+ }
+
@Test
public void testTransportInTunnelModeV4InV6Reflected() throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -786,6 +1059,12 @@
checkTunnelInput(AF_INET6, AF_INET, false, true);
}
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ @Test
+ public void testMigrateTransportInTunnelModeV6InV4() throws Exception {
+ doTestMigrateTunnel(AF_INET6, AF_INET, false, true);
+ }
+
@Test
public void testTransportInTunnelModeV6InV4Reflected() throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -799,6 +1078,12 @@
checkTunnelInput(AF_INET6, AF_INET, true, true);
}
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ @Test
+ public void testMigrateTransportInTunnelModeV6InV4UdpEncap() throws Exception {
+ doTestMigrateTunnel(AF_INET6, AF_INET, true, true);
+ }
+
@Test
public void testTransportInTunnelModeV6InV4UdpEncapReflected() throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -812,6 +1097,12 @@
checkTunnelInput(AF_INET, AF_INET6, false, true);
}
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ @Test
+ public void testMigrateTransportInTunnelModeV6InV6() throws Exception {
+ doTestMigrateTunnel(AF_INET, AF_INET6, false, true);
+ }
+
@Test
public void testTransportInTunnelModeV6InV6Reflected() throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -826,6 +1117,12 @@
checkTunnelInput(AF_INET, AF_INET, false, false);
}
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ @Test
+ public void testMigrateTunnelV4InV4() throws Exception {
+ doTestMigrateTunnel(AF_INET, AF_INET, false, false);
+ }
+
@Test
public void testTunnelV4InV4Reflected() throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -839,6 +1136,12 @@
checkTunnelInput(AF_INET, AF_INET, true, false);
}
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ @Test
+ public void testMigrateTunnelV4InV4UdpEncap() throws Exception {
+ doTestMigrateTunnel(AF_INET, AF_INET, true, false);
+ }
+
@Test
public void testTunnelV4InV4UdpEncapReflected() throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -852,6 +1155,12 @@
checkTunnelInput(AF_INET, AF_INET6, false, false);
}
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ @Test
+ public void testMigrateTunnelV4InV6() throws Exception {
+ doTestMigrateTunnel(AF_INET, AF_INET6, false, false);
+ }
+
@Test
public void testTunnelV4InV6Reflected() throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -865,6 +1174,12 @@
checkTunnelInput(AF_INET6, AF_INET, false, false);
}
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ @Test
+ public void testMigrateTunnelV6InV4() throws Exception {
+ doTestMigrateTunnel(AF_INET6, AF_INET, false, false);
+ }
+
@Test
public void testTunnelV6InV4Reflected() throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -878,6 +1193,12 @@
checkTunnelInput(AF_INET6, AF_INET, true, false);
}
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ @Test
+ public void testMigrateTunnelV6InV4UdpEncap() throws Exception {
+ doTestMigrateTunnel(AF_INET6, AF_INET, true, false);
+ }
+
@Test
public void testTunnelV6InV4UdpEncapReflected() throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -891,6 +1212,12 @@
checkTunnelInput(AF_INET6, AF_INET6, false, false);
}
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ @Test
+ public void testMigrateTunnelV6InV6() throws Exception {
+ doTestMigrateTunnel(AF_INET6, AF_INET6, false, false);
+ }
+
@Test
public void testTunnelV6InV6Reflected() throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
diff --git a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
index c505cef..ccc9416 100644
--- a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
+++ b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
@@ -29,9 +29,9 @@
import android.net.NattKeepalivePacketData
import android.net.Network
import android.net.NetworkAgent
+import android.net.NetworkAgentConfig
import android.net.NetworkAgent.INVALID_NETWORK
import android.net.NetworkAgent.VALID_NETWORK
-import android.net.NetworkAgentConfig
import android.net.NetworkCapabilities
import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED
@@ -46,9 +46,17 @@
import android.net.NetworkCapabilities.TRANSPORT_VPN
import android.net.NetworkInfo
import android.net.NetworkProvider
+import android.net.NetworkReleasedException
import android.net.NetworkRequest
import android.net.NetworkScore
import android.net.RouteInfo
+import android.net.QosCallback
+import android.net.QosCallbackException
+import android.net.QosCallback.QosCallbackRegistrationException
+import android.net.QosFilter
+import android.net.QosSession
+import android.net.QosSessionAttributes
+import android.net.QosSocketInfo
import android.net.SocketKeepalive
import android.net.Uri
import android.net.VpnManager
@@ -59,12 +67,17 @@
import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnNetworkCreated
import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnNetworkDestroyed
import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnNetworkUnwanted
+import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnRegisterQosCallback
import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnRemoveKeepalivePacketFilter
import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnSaveAcceptUnvalidated
import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnSignalStrengthThresholdsUpdated
import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnStartSocketKeepalive
import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnStopSocketKeepalive
+import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnUnregisterQosCallback
import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnValidationStatus
+import android.net.cts.NetworkAgentTest.TestableQosCallback.CallbackEntry.OnError
+import android.net.cts.NetworkAgentTest.TestableQosCallback.CallbackEntry.OnQosSessionAvailable
+import android.net.cts.NetworkAgentTest.TestableQosCallback.CallbackEntry.OnQosSessionLost
import android.os.Build
import android.os.Handler
import android.os.HandlerThread
@@ -72,6 +85,7 @@
import android.os.Message
import android.os.SystemClock
import android.telephony.TelephonyManager
+import android.telephony.data.EpsBearerQosSessionAttributes
import android.util.DebugUtils.valueToString
import androidx.test.InstrumentationRegistry
import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
@@ -97,9 +111,13 @@
import org.mockito.Mockito.mock
import org.mockito.Mockito.timeout
import org.mockito.Mockito.verify
+import java.net.InetAddress
+import java.net.InetSocketAddress
+import java.net.Socket
import java.time.Duration
import java.util.Arrays
import java.util.UUID
+import java.util.concurrent.Executors
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import kotlin.test.assertFalse
@@ -143,7 +161,7 @@
private val LOCAL_IPV4_ADDRESS = InetAddresses.parseNumericAddress("192.0.2.1")
private val REMOTE_IPV4_ADDRESS = InetAddresses.parseNumericAddress("192.0.2.2")
- private val mCM = realContext.getSystemService(ConnectivityManager::class.java)
+ private val mCM = realContext.getSystemService(ConnectivityManager::class.java)!!
private val mHandlerThread = HandlerThread("${javaClass.simpleName} handler thread")
private val mFakeConnectivityService = FakeConnectivityService()
@@ -152,6 +170,7 @@
private val agentsToCleanUp = mutableListOf<NetworkAgent>()
private val callbacksToCleanUp = mutableListOf<TestableNetworkCallback>()
+ private var qosTestSocket: Socket? = null
@Before
fun setUp() {
@@ -163,6 +182,7 @@
fun tearDown() {
agentsToCleanUp.forEach { it.unregister() }
callbacksToCleanUp.forEach { mCM.unregisterNetworkCallback(it) }
+ qosTestSocket?.close()
mHandlerThread.quitSafely()
instrumentation.getUiAutomation().dropShellPermissionIdentity()
}
@@ -228,6 +248,11 @@
data class OnSignalStrengthThresholdsUpdated(val thresholds: IntArray) : CallbackEntry()
object OnNetworkCreated : CallbackEntry()
object OnNetworkDestroyed : CallbackEntry()
+ data class OnRegisterQosCallback(
+ val callbackId: Int,
+ val filter: QosFilter
+ ) : CallbackEntry()
+ data class OnUnregisterQosCallback(val callbackId: Int) : CallbackEntry()
}
override fun onBandwidthUpdateRequested() {
@@ -276,6 +301,14 @@
}
}
+ override fun onQosCallbackRegistered(qosCallbackId: Int, filter: QosFilter) {
+ history.add(OnRegisterQosCallback(qosCallbackId, filter))
+ }
+
+ override fun onQosCallbackUnregistered(qosCallbackId: Int) {
+ history.add(OnUnregisterQosCallback(qosCallbackId))
+ }
+
override fun onValidationStatus(status: Int, uri: Uri?) {
history.add(OnValidationStatus(status, uri))
}
@@ -307,6 +340,12 @@
return foundCallback
}
+ inline fun <reified T : CallbackEntry> expectCallback(valid: (T) -> Boolean) {
+ val foundCallback = history.poll(DEFAULT_TIMEOUT_MS)
+ assertTrue(foundCallback is T, "Expected ${T::class} but found $foundCallback")
+ assertTrue(valid(foundCallback), "Unexpected callback : $foundCallback")
+ }
+
inline fun <reified T : CallbackEntry> eventuallyExpect() =
history.poll(DEFAULT_TIMEOUT_MS) { it is T }.also {
assertNotNull(it, "Callback ${T::class} not received")
@@ -390,7 +429,7 @@
initialConfig: NetworkAgentConfig? = null,
expectedInitSignalStrengthThresholds: IntArray? = intArrayOf()
): Pair<TestableNetworkAgent, TestableNetworkCallback> {
- val callback = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS)
+ val callback = TestableNetworkCallback()
// Ensure this NetworkAgent is never unneeded by filing a request with its specifier.
requestNetwork(makeTestNetworkRequest(specifier = specifier), callback)
val agent = createNetworkAgent(context, specifier, initialConfig = initialConfig)
@@ -651,7 +690,7 @@
assertFalse(vpnNc.hasCapability(NET_CAPABILITY_NOT_VPN))
assertTrue(hasAllTransports(vpnNc, defaultNetworkTransports),
"VPN transports ${Arrays.toString(vpnNc.transportTypes)}" +
- " lacking transports from ${Arrays.toString(defaultNetworkTransports)}")
+ " lacking transports from ${Arrays.toString(defaultNetworkTransports)}")
// Check that when no underlying networks are announced the underlying transport disappears.
agent.setUnderlyingNetworks(listOf<Network>())
@@ -934,4 +973,251 @@
// tearDown() will unregister the requests and agents
}
+
+ private class TestableQosCallback : QosCallback() {
+ val history = ArrayTrackRecord<CallbackEntry>().newReadHead()
+
+ sealed class CallbackEntry {
+ data class OnQosSessionAvailable(val sess: QosSession, val attr: QosSessionAttributes)
+ : CallbackEntry()
+ data class OnQosSessionLost(val sess: QosSession)
+ : CallbackEntry()
+ data class OnError(val ex: QosCallbackException)
+ : CallbackEntry()
+ }
+
+ override fun onQosSessionAvailable(sess: QosSession, attr: QosSessionAttributes) {
+ history.add(OnQosSessionAvailable(sess, attr))
+ }
+
+ override fun onQosSessionLost(sess: QosSession) {
+ history.add(OnQosSessionLost(sess))
+ }
+
+ override fun onError(ex: QosCallbackException) {
+ history.add(OnError(ex))
+ }
+
+ inline fun <reified T : CallbackEntry> expectCallback(): T {
+ val foundCallback = history.poll(DEFAULT_TIMEOUT_MS)
+ assertTrue(foundCallback is T, "Expected ${T::class} but found $foundCallback")
+ return foundCallback
+ }
+
+ inline fun <reified T : CallbackEntry> expectCallback(valid: (T) -> Boolean) {
+ val foundCallback = history.poll(DEFAULT_TIMEOUT_MS)
+ assertTrue(foundCallback is T, "Expected ${T::class} but found $foundCallback")
+ assertTrue(valid(foundCallback), "Unexpected callback : $foundCallback")
+ }
+
+ fun assertNoCallback() {
+ assertNull(history.poll(NO_CALLBACK_TIMEOUT),
+ "Callback received")
+ }
+ }
+
+ private fun setupForQosCallbackTesting(): Pair<TestableNetworkAgent, Socket> {
+ val request = NetworkRequest.Builder()
+ .clearCapabilities()
+ .addTransportType(TRANSPORT_TEST)
+ .build()
+
+ val callback = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS)
+ requestNetwork(request, callback)
+ val (agent, _) = createConnectedNetworkAgent()
+
+ qosTestSocket = assertNotNull(agent.network?.socketFactory?.createSocket()).also {
+ it.bind(InetSocketAddress(InetAddress.getLoopbackAddress(), 0))
+ }
+ return Pair(agent, qosTestSocket!!)
+ }
+
+ @Test
+ fun testQosCallbackRegisterWithUnregister() {
+ val (agent, socket) = setupForQosCallbackTesting()
+
+ val qosCallback = TestableQosCallback()
+ var callbackId = -1
+ Executors.newSingleThreadExecutor().let { executor ->
+ try {
+ val info = QosSocketInfo(agent.network!!, socket)
+ mCM.registerQosCallback(info, executor, qosCallback)
+ callbackId = agent.expectCallback<OnRegisterQosCallback>().callbackId
+
+ assertFailsWith<QosCallbackRegistrationException>(
+ "The same callback cannot be " +
+ "registered more than once without first being unregistered") {
+ mCM.registerQosCallback(info, executor, qosCallback)
+ }
+ } finally {
+ socket.close()
+ mCM.unregisterQosCallback(qosCallback)
+ agent.expectCallback<OnUnregisterQosCallback> { it.callbackId == callbackId }
+ executor.shutdown()
+ }
+ }
+ }
+
+ @Test
+ fun testQosCallbackOnQosSession() {
+ val (agent, socket) = setupForQosCallbackTesting()
+ val qosCallback = TestableQosCallback()
+ Executors.newSingleThreadExecutor().let { executor ->
+ try {
+ val info = QosSocketInfo(agent.network!!, socket)
+ mCM.registerQosCallback(info, executor, qosCallback)
+ val callbackId = agent.expectCallback<OnRegisterQosCallback>().callbackId
+
+ val uniqueSessionId = 4294967397
+ val sessId = 101
+
+ val attributes = createEpsAttributes(5)
+ assertEquals(attributes.qosIdentifier, 5)
+ agent.sendQosSessionAvailable(callbackId, sessId, attributes)
+ qosCallback.expectCallback<OnQosSessionAvailable> {
+ it.sess.sessionId == sessId && it.sess.uniqueId == uniqueSessionId &&
+ it.sess.sessionType == QosSession.TYPE_EPS_BEARER
+ }
+
+ agent.sendQosSessionLost(callbackId, sessId, QosSession.TYPE_EPS_BEARER)
+ qosCallback.expectCallback<OnQosSessionLost> {
+ it.sess.sessionId == sessId && it.sess.uniqueId == uniqueSessionId &&
+ it.sess.sessionType == QosSession.TYPE_EPS_BEARER
+ }
+
+ // Make sure that we don't get more qos callbacks
+ mCM.unregisterQosCallback(qosCallback)
+ agent.expectCallback<OnUnregisterQosCallback>()
+
+ agent.sendQosSessionLost(callbackId, sessId, QosSession.TYPE_EPS_BEARER)
+ qosCallback.assertNoCallback()
+ } finally {
+ socket.close()
+
+ // safety precaution
+ mCM.unregisterQosCallback(qosCallback)
+
+ executor.shutdown()
+ }
+ }
+ }
+
+ @Test
+ fun testQosCallbackOnError() {
+ val (agent, socket) = setupForQosCallbackTesting()
+ val qosCallback = TestableQosCallback()
+ Executors.newSingleThreadExecutor().let { executor ->
+ try {
+ val info = QosSocketInfo(agent.network!!, socket)
+ mCM.registerQosCallback(info, executor, qosCallback)
+ val callbackId = agent.expectCallback<OnRegisterQosCallback>().callbackId
+
+ val sessId = 101
+ val attributes = createEpsAttributes()
+
+ // Double check that this is wired up and ready to go
+ agent.sendQosSessionAvailable(callbackId, sessId, attributes)
+ qosCallback.expectCallback<OnQosSessionAvailable>()
+
+ // Check that onError is coming through correctly
+ agent.sendQosCallbackError(callbackId,
+ QosCallbackException.EX_TYPE_FILTER_NOT_SUPPORTED)
+ qosCallback.expectCallback<OnError> {
+ it.ex.cause is UnsupportedOperationException
+ }
+
+ // Ensure that when an error occurs the callback was also unregistered
+ agent.sendQosSessionLost(callbackId, sessId, QosSession.TYPE_EPS_BEARER)
+ qosCallback.assertNoCallback()
+ } finally {
+ socket.close()
+
+ // Make sure that the callback is fully unregistered
+ mCM.unregisterQosCallback(qosCallback)
+
+ executor.shutdown()
+ }
+ }
+ }
+
+ @Test
+ fun testQosCallbackIdsAreMappedCorrectly() {
+ val (agent, socket) = setupForQosCallbackTesting()
+ val qosCallback1 = TestableQosCallback()
+ val qosCallback2 = TestableQosCallback()
+ Executors.newSingleThreadExecutor().let { executor ->
+ try {
+ val info = QosSocketInfo(agent.network!!, socket)
+ mCM.registerQosCallback(info, executor, qosCallback1)
+ val callbackId1 = agent.expectCallback<OnRegisterQosCallback>().callbackId
+
+ mCM.registerQosCallback(info, executor, qosCallback2)
+ val callbackId2 = agent.expectCallback<OnRegisterQosCallback>().callbackId
+
+ val sessId1 = 101
+ val attributes1 = createEpsAttributes(1)
+
+ // Check #1
+ agent.sendQosSessionAvailable(callbackId1, sessId1, attributes1)
+ qosCallback1.expectCallback<OnQosSessionAvailable>()
+ qosCallback2.assertNoCallback()
+
+ // Check #2
+ val sessId2 = 102
+ val attributes2 = createEpsAttributes(2)
+ agent.sendQosSessionAvailable(callbackId2, sessId2, attributes2)
+ qosCallback1.assertNoCallback()
+ qosCallback2.expectCallback<OnQosSessionAvailable> { sessId2 == it.sess.sessionId }
+ } finally {
+ socket.close()
+
+ // Make sure that the callback is fully unregistered
+ mCM.unregisterQosCallback(qosCallback1)
+ mCM.unregisterQosCallback(qosCallback2)
+
+ executor.shutdown()
+ }
+ }
+ }
+
+ @Test
+ fun testQosCallbackWhenNetworkReleased() {
+ val (agent, socket) = setupForQosCallbackTesting()
+ Executors.newSingleThreadExecutor().let { executor ->
+ try {
+ val qosCallback1 = TestableQosCallback()
+ val qosCallback2 = TestableQosCallback()
+ try {
+ val info = QosSocketInfo(agent.network!!, socket)
+ mCM.registerQosCallback(info, executor, qosCallback1)
+ mCM.registerQosCallback(info, executor, qosCallback2)
+ agent.unregister()
+
+ qosCallback1.expectCallback<OnError> {
+ it.ex.cause is NetworkReleasedException
+ }
+
+ qosCallback2.expectCallback<OnError> {
+ it.ex.cause is NetworkReleasedException
+ }
+ } finally {
+ socket.close()
+ mCM.unregisterQosCallback(qosCallback1)
+ mCM.unregisterQosCallback(qosCallback2)
+ }
+ } finally {
+ socket.close()
+ executor.shutdown()
+ }
+ }
+ }
+
+ private fun createEpsAttributes(qci: Int = 1): EpsBearerQosSessionAttributes {
+ val remoteAddresses = ArrayList<InetSocketAddress>()
+ remoteAddresses.add(InetSocketAddress("2001:db8::123", 80))
+ return EpsBearerQosSessionAttributes(
+ qci, 2, 3, 4, 5,
+ remoteAddresses
+ )
+ }
}
diff --git a/tests/cts/net/src/android/net/ipv6/cts/PingTest.java b/tests/cts/net/src/android/net/ipv6/cts/PingTest.java
index 146fd83..8665fc8 100644
--- a/tests/cts/net/src/android/net/ipv6/cts/PingTest.java
+++ b/tests/cts/net/src/android/net/ipv6/cts/PingTest.java
@@ -115,7 +115,7 @@
// Receive the response.
if (useRecvfrom) {
- InetSocketAddress from = new InetSocketAddress();
+ InetSocketAddress from = new InetSocketAddress(0);
bytesRead = Os.recvfrom(s, responseBuffer, 0, from);
// Check the source address and scope ID.
diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp
index beae0cf..98c15db 100644
--- a/tests/unit/Android.bp
+++ b/tests/unit/Android.bp
@@ -60,11 +60,11 @@
"java/**/*.kt",
],
test_suites: ["device-tests"],
- certificate: "platform",
jarjar_rules: "jarjar-rules.txt",
static_libs: [
"androidx.test.rules",
"bouncycastle-repackaged-unbundled",
+ "core-tests-support",
"FrameworksNetCommonTests",
"frameworks-base-testutils",
"frameworks-net-integration-testutils",
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index be7239d..2aa95ee 100644
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -18,10 +18,15 @@
import static android.Manifest.permission.CHANGE_NETWORK_STATE;
import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
+import static android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE;
+import static android.Manifest.permission.CREATE_USERS;
import static android.Manifest.permission.DUMP;
+import static android.Manifest.permission.GET_INTENT_SENDER_INTENT;
import static android.Manifest.permission.LOCAL_MAC_ADDRESS;
import static android.Manifest.permission.NETWORK_FACTORY;
import static android.Manifest.permission.NETWORK_SETTINGS;
+import static android.Manifest.permission.NETWORK_STACK;
+import static android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD;
import static android.app.PendingIntent.FLAG_IMMUTABLE;
import static android.content.Intent.ACTION_PACKAGE_ADDED;
import static android.content.Intent.ACTION_PACKAGE_REMOVED;
@@ -134,6 +139,7 @@
import static com.android.testutils.MiscAsserts.assertRunsInAtMost;
import static com.android.testutils.MiscAsserts.assertSameElements;
import static com.android.testutils.MiscAsserts.assertThrows;
+import static com.android.testutils.TestPermissionUtil.runAsShell;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -259,6 +265,7 @@
import android.net.shared.PrivateDnsConfig;
import android.net.util.MultinetworkPolicyTracker;
import android.os.BadParcelableException;
+import android.os.BatteryStatsManager;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -297,6 +304,7 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.connectivity.resources.R;
+import com.android.internal.app.IBatteryStats;
import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnProfile;
import com.android.internal.util.ArrayUtils;
@@ -305,6 +313,7 @@
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.net.module.util.ArrayTrackRecord;
import com.android.net.module.util.CollectionUtils;
+import com.android.net.module.util.LocationPermissionChecker;
import com.android.server.ConnectivityService.ConnectivityDiagnosticsCallbackInfo;
import com.android.server.ConnectivityService.NetworkRequestInfo;
import com.android.server.connectivity.MockableSystemProperties;
@@ -488,6 +497,11 @@
@Mock Resources mResources;
@Mock ProxyTracker mProxyTracker;
+ // BatteryStatsManager is final and cannot be mocked with regular mockito, so just mock the
+ // underlying binder calls.
+ final BatteryStatsManager mBatteryStatsManager =
+ new BatteryStatsManager(mock(IBatteryStats.class));
+
private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
ArgumentCaptor.forClass(ResolverParamsParcel.class);
@@ -579,6 +593,7 @@
if (Context.NETWORK_POLICY_SERVICE.equals(name)) return mNetworkPolicyManager;
if (Context.SYSTEM_CONFIG_SERVICE.equals(name)) return mSystemConfigManager;
if (Context.NETWORK_STATS_SERVICE.equals(name)) return mStatsManager;
+ if (Context.BATTERY_STATS_SERVICE.equals(name)) return mBatteryStatsManager;
return super.getSystemService(name);
}
@@ -659,6 +674,15 @@
public void setPermission(String permission, Integer granted) {
mMockedPermissions.put(permission, granted);
}
+
+ @Override
+ public Intent registerReceiverForAllUsers(@Nullable BroadcastReceiver receiver,
+ @NonNull IntentFilter filter, @Nullable String broadcastPermission,
+ @Nullable Handler scheduler) {
+ // TODO: ensure MultinetworkPolicyTracker's BroadcastReceiver is tested; just returning
+ // null should not pass the test
+ return null;
+ }
}
private void waitForIdle() {
@@ -1208,7 +1232,24 @@
return mDeviceIdleInternal;
}
},
- mNetworkManagementService, mMockNetd, userId, mVpnProfileStore);
+ mNetworkManagementService, mMockNetd, userId, mVpnProfileStore,
+ new SystemServices(mServiceContext) {
+ @Override
+ public String settingsSecureGetStringForUser(String key, int userId) {
+ switch (key) {
+ // Settings keys not marked as @Readable are not readable from
+ // non-privileged apps, unless marked as testOnly=true
+ // (atest refuses to install testOnly=true apps), even if mocked
+ // in the content provider, because
+ // Settings.Secure.NameValueCache#getStringForUser checks the key
+ // before querying the mock settings provider.
+ case Settings.Secure.ALWAYS_ON_VPN_APP:
+ return null;
+ default:
+ return super.settingsSecureGetStringForUser(key, userId);
+ }
+ }
+ }, new Ikev2SessionCreator());
}
public void setUids(Set<UidRange> uids) {
@@ -1455,8 +1496,7 @@
return mService.getNetworkAgentInfoForNetwork(mna.getNetwork()).clatd;
}
- private static class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
- volatile boolean mConfigRestrictsAvoidBadWifi;
+ private class WrappedMultinetworkPolicyTracker extends MultinetworkPolicyTracker {
volatile int mConfigMeteredMultipathPreference;
WrappedMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
@@ -1464,8 +1504,8 @@
}
@Override
- public boolean configRestrictsAvoidBadWifi() {
- return mConfigRestrictsAvoidBadWifi;
+ protected Resources getResourcesForActiveSubId() {
+ return mResources;
}
@Override
@@ -1592,6 +1632,11 @@
mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
new FakeSettingsProvider());
mServiceContext.setUseRegisteredHandlers(true);
+ mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
+ mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
+ mServiceContext.setPermission(CONTROL_OEM_PAID_NETWORK_PREFERENCE, PERMISSION_GRANTED);
+ mServiceContext.setPermission(PACKET_KEEPALIVE_OFFLOAD, PERMISSION_GRANTED);
+ mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_GRANTED);
mAlarmManagerThread = new HandlerThread("TestAlarmManager");
mAlarmManagerThread.start();
@@ -1651,6 +1696,13 @@
return mPolicyTracker;
}).when(deps).makeMultinetworkPolicyTracker(any(), any(), any());
doReturn(true).when(deps).getCellular464XlatEnabled();
+ doAnswer(inv ->
+ new LocationPermissionChecker(inv.getArgument(0)) {
+ @Override
+ protected int getCurrentUser() {
+ return runAsShell(CREATE_USERS, () -> super.getCurrentUser());
+ }
+ }).when(deps).makeLocationPermissionChecker(any());
doReturn(60000).when(mResources).getInteger(R.integer.config_networkTransitionTimeout);
doReturn("").when(mResources).getString(R.string.config_networkCaptivePortalServerUrl);
@@ -1670,7 +1722,9 @@
.getIdentifier(eq("config_networkSupportedKeepaliveCount"), eq("array"), any());
doReturn(R.array.network_switch_type_name).when(mResources)
.getIdentifier(eq("network_switch_type_name"), eq("array"), any());
-
+ doReturn(R.integer.config_networkAvoidBadWifi).when(mResources)
+ .getIdentifier(eq("config_networkAvoidBadWifi"), eq("integer"), any());
+ doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
final ConnectivityResources connRes = mock(ConnectivityResources.class);
doReturn(mResources).when(connRes).get();
@@ -1680,6 +1734,12 @@
doReturn(mResources).when(mockResContext).getResources();
ConnectivityResources.setResourcesContextForTest(mockResContext);
+ doAnswer(inv -> {
+ final PendingIntent a = inv.getArgument(0);
+ final PendingIntent b = inv.getArgument(1);
+ return runAsShell(GET_INTENT_SENDER_INTENT, () -> a.intentFilterEquals(b));
+ }).when(deps).intentFilterEquals(any(), any());
+
return deps;
}
@@ -4704,30 +4764,29 @@
}
@Test
- public void testAvoidBadWifiSetting() throws Exception {
+ public void testSetAllowBadWifiUntil() throws Exception {
+ runAsShell(NETWORK_SETTINGS,
+ () -> mService.setTestAllowBadWifiUntil(System.currentTimeMillis() + 5_000L));
+ waitForIdle();
+ testAvoidBadWifiConfig_controlledBySettings();
+
+ runAsShell(NETWORK_SETTINGS,
+ () -> mService.setTestAllowBadWifiUntil(System.currentTimeMillis() - 5_000L));
+ waitForIdle();
+ testAvoidBadWifiConfig_ignoreSettings();
+ }
+
+ private void testAvoidBadWifiConfig_controlledBySettings() {
final ContentResolver cr = mServiceContext.getContentResolver();
final String settingName = ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI;
- mPolicyTracker.mConfigRestrictsAvoidBadWifi = false;
- String[] values = new String[] {null, "0", "1"};
- for (int i = 0; i < values.length; i++) {
- Settings.Global.putInt(cr, settingName, 1);
- mPolicyTracker.reevaluate();
- waitForIdle();
- String msg = String.format("config=false, setting=%s", values[i]);
- assertTrue(mService.avoidBadWifi());
- assertFalse(msg, mPolicyTracker.shouldNotifyWifiUnvalidated());
- }
-
- mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
-
- Settings.Global.putInt(cr, settingName, 0);
+ Settings.Global.putString(cr, settingName, "0");
mPolicyTracker.reevaluate();
waitForIdle();
assertFalse(mService.avoidBadWifi());
assertFalse(mPolicyTracker.shouldNotifyWifiUnvalidated());
- Settings.Global.putInt(cr, settingName, 1);
+ Settings.Global.putString(cr, settingName, "1");
mPolicyTracker.reevaluate();
waitForIdle();
assertTrue(mService.avoidBadWifi());
@@ -4740,13 +4799,40 @@
assertTrue(mPolicyTracker.shouldNotifyWifiUnvalidated());
}
+ private void testAvoidBadWifiConfig_ignoreSettings() {
+ final ContentResolver cr = mServiceContext.getContentResolver();
+ final String settingName = ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI;
+
+ String[] values = new String[] {null, "0", "1"};
+ for (int i = 0; i < values.length; i++) {
+ Settings.Global.putString(cr, settingName, values[i]);
+ mPolicyTracker.reevaluate();
+ waitForIdle();
+ String msg = String.format("config=false, setting=%s", values[i]);
+ assertTrue(mService.avoidBadWifi());
+ assertFalse(msg, mPolicyTracker.shouldNotifyWifiUnvalidated());
+ }
+ }
+
+ @Test
+ public void testAvoidBadWifiSetting() throws Exception {
+ final ContentResolver cr = mServiceContext.getContentResolver();
+ final String settingName = ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI;
+
+ doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
+ testAvoidBadWifiConfig_ignoreSettings();
+
+ doReturn(0).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
+ testAvoidBadWifiConfig_controlledBySettings();
+ }
+
@Ignore("Refactoring in progress b/178071397")
@Test
public void testAvoidBadWifi() throws Exception {
final ContentResolver cr = mServiceContext.getContentResolver();
// Pretend we're on a carrier that restricts switching away from bad wifi.
- mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
+ doReturn(0).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
// File a request for cell to ensure it doesn't go down.
final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
@@ -4797,13 +4883,13 @@
// Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
// that we switch back to cell.
- mPolicyTracker.mConfigRestrictsAvoidBadWifi = false;
+ doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
mPolicyTracker.reevaluate();
defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
assertEquals(mCm.getActiveNetwork(), cellNetwork);
// Switch back to a restrictive carrier.
- mPolicyTracker.mConfigRestrictsAvoidBadWifi = true;
+ doReturn(0).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
mPolicyTracker.reevaluate();
defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
assertEquals(mCm.getActiveNetwork(), wifiNetwork);
@@ -5480,6 +5566,8 @@
// the follow-up network disconnection will be processed first.
mWiFiNetworkAgent.setKeepaliveResponseDelay(3 * TIMEOUT_MS);
ka.stop();
+ // Call stop() twice shouldn't result in crash, b/182586681.
+ ka.stop();
// Make sure the stop has been processed. Wait for executor idle is needed to prevent
// flaky since the actual stop call to the service is delegated to executor thread.
@@ -5777,37 +5865,59 @@
@Test
public void testNetworkCallbackMaximum() throws Exception {
final int MAX_REQUESTS = 100;
- final int CALLBACKS = 89;
- final int INTENTS = 11;
+ final int CALLBACKS = 87;
+ final int DIFF_INTENTS = 10;
+ final int SAME_INTENTS = 10;
final int SYSTEM_ONLY_MAX_REQUESTS = 250;
- assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
+ // Assert 1 (Default request filed before testing) + CALLBACKS + DIFF_INTENTS +
+ // 1 (same intent) = MAX_REQUESTS - 1, since the capacity is MAX_REQUEST - 1.
+ assertEquals(MAX_REQUESTS - 1, 1 + CALLBACKS + DIFF_INTENTS + 1);
NetworkRequest networkRequest = new NetworkRequest.Builder().build();
ArrayList<Object> registered = new ArrayList<>();
- int j = 0;
- while (j++ < CALLBACKS / 2) {
- NetworkCallback cb = new NetworkCallback();
- mCm.requestNetwork(networkRequest, cb);
+ for (int j = 0; j < CALLBACKS; j++) {
+ final NetworkCallback cb = new NetworkCallback();
+ if (j < CALLBACKS / 2) {
+ mCm.requestNetwork(networkRequest, cb);
+ } else {
+ mCm.registerNetworkCallback(networkRequest, cb);
+ }
registered.add(cb);
}
- while (j++ < CALLBACKS) {
- NetworkCallback cb = new NetworkCallback();
- mCm.registerNetworkCallback(networkRequest, cb);
- registered.add(cb);
+
+ // Since ConnectivityService will de-duplicate the request with the same intent,
+ // register multiple times does not really increase multiple requests.
+ final PendingIntent same_pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
+ new Intent("same"), FLAG_IMMUTABLE);
+ for (int j = 0; j < SAME_INTENTS; j++) {
+ mCm.registerNetworkCallback(networkRequest, same_pi);
+ // Wait for the requests with the same intent to be de-duplicated. Because
+ // ConnectivityService side incrementCountOrThrow in binder, decrementCount in handler
+ // thread, waitForIdle is needed to ensure decrementCount being invoked for same intent
+ // requests before doing further tests.
+ waitForIdle();
}
- j = 0;
- while (j++ < INTENTS / 2) {
- final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
- new Intent("a" + j), FLAG_IMMUTABLE);
- mCm.requestNetwork(networkRequest, pi);
- registered.add(pi);
+ for (int j = 0; j < SAME_INTENTS; j++) {
+ mCm.requestNetwork(networkRequest, same_pi);
+ // Wait for the requests with the same intent to be de-duplicated.
+ // Refer to the reason above.
+ waitForIdle();
}
- while (j++ < INTENTS) {
- final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
- new Intent("b" + j), FLAG_IMMUTABLE);
- mCm.registerNetworkCallback(networkRequest, pi);
- registered.add(pi);
+ registered.add(same_pi);
+
+ for (int j = 0; j < DIFF_INTENTS; j++) {
+ if (j < DIFF_INTENTS / 2) {
+ final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
+ new Intent("a" + j), FLAG_IMMUTABLE);
+ mCm.requestNetwork(networkRequest, pi);
+ registered.add(pi);
+ } else {
+ final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
+ new Intent("b" + j), FLAG_IMMUTABLE);
+ mCm.registerNetworkCallback(networkRequest, pi);
+ registered.add(pi);
+ }
}
// Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
@@ -5857,10 +5967,10 @@
for (Object o : registered) {
if (o instanceof NetworkCallback) {
- mCm.unregisterNetworkCallback((NetworkCallback)o);
+ mCm.unregisterNetworkCallback((NetworkCallback) o);
}
if (o instanceof PendingIntent) {
- mCm.unregisterNetworkCallback((PendingIntent)o);
+ mCm.unregisterNetworkCallback((PendingIntent) o);
}
}
waitForIdle();
@@ -9357,8 +9467,7 @@
mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
PERMISSION_DENIED);
mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
- mServiceContext.setPermission(Manifest.permission.NETWORK_STACK,
- PERMISSION_DENIED);
+ mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
mServiceContext.setPermission(Manifest.permission.NETWORK_SETUP_WIZARD,
PERMISSION_DENIED);
}
@@ -9799,7 +9908,7 @@
setupConnectionOwnerUid(vpnOwnerUid, vpnType);
// Test as VPN app
- mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
+ mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
mServiceContext.setPermission(
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_DENIED);
}
@@ -9839,8 +9948,7 @@
public void testGetConnectionOwnerUidVpnServiceNetworkStackDoesNotThrow() throws Exception {
final int myUid = Process.myUid();
setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE);
- mServiceContext.setPermission(
- android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
+ mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
assertEquals(42, mService.getConnectionOwnerUid(getTestConnectionInfo()));
}
@@ -10008,8 +10116,7 @@
public void testCheckConnectivityDiagnosticsPermissionsNetworkStack() throws Exception {
final NetworkAgentInfo naiWithoutUid = fakeMobileNai(new NetworkCapabilities());
- mServiceContext.setPermission(
- android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
+ mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
assertTrue(
"NetworkStack permission not applied",
mService.checkConnectivityDiagnosticsPermissions(
@@ -10025,7 +10132,7 @@
nc.setAdministratorUids(new int[] {wrongUid});
final NetworkAgentInfo naiWithUid = fakeWifiNai(nc);
- mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
+ mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
assertFalse(
"Mismatched uid/package name should not pass the location permission check",
@@ -10035,7 +10142,7 @@
private void verifyConnectivityDiagnosticsPermissionsWithNetworkAgentInfo(
NetworkAgentInfo info, boolean expectPermission) {
- mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
+ mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
assertEquals(
"Unexpected ConnDiags permission",
@@ -10103,7 +10210,7 @@
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION);
- mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
+ mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
assertTrue(
"NetworkCapabilities administrator uid permission not applied",
@@ -10120,7 +10227,7 @@
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION);
- mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
+ mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
// Use wrong pid and uid
assertFalse(
@@ -10146,8 +10253,7 @@
final NetworkRequest request = new NetworkRequest.Builder().build();
when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
- mServiceContext.setPermission(
- android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
+ mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
mService.registerConnectivityDiagnosticsCallback(
mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
@@ -10166,8 +10272,7 @@
final NetworkRequest request = new NetworkRequest.Builder().build();
when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
- mServiceContext.setPermission(
- android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
+ mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
mService.registerConnectivityDiagnosticsCallback(
mConnectivityDiagnosticsCallback, request, mContext.getPackageName());
diff --git a/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
index e98f5db..db63495 100644
--- a/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -521,13 +521,13 @@
// MOCK_UID1: MOCK_PACKAGE1 only has network permission.
// SYSTEM_UID: SYSTEM_PACKAGE1 has system permission.
// SYSTEM_UID: SYSTEM_PACKAGE2 only has network permission.
- doReturn(SYSTEM).when(mPermissionMonitor).highestPermissionForUid(eq(SYSTEM), anyString());
doReturn(SYSTEM).when(mPermissionMonitor).highestPermissionForUid(any(),
eq(SYSTEM_PACKAGE1));
doReturn(NETWORK).when(mPermissionMonitor).highestPermissionForUid(any(),
eq(SYSTEM_PACKAGE2));
doReturn(NETWORK).when(mPermissionMonitor).highestPermissionForUid(any(),
eq(MOCK_PACKAGE1));
+ doReturn(SYSTEM).when(mPermissionMonitor).highestPermissionForUid(eq(SYSTEM), anyString());
// Add SYSTEM_PACKAGE2, expect only have network permission.
mPermissionMonitor.onUserAdded(MOCK_USER1);
@@ -542,6 +542,21 @@
netdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2},
new int[]{SYSTEM_UID});
+ // Remove SYSTEM_PACKAGE2, expect keep system permission.
+ when(mPackageManager.getPackagesForUid(MOCK_USER1.getUid(SYSTEM_UID)))
+ .thenReturn(new String[]{SYSTEM_PACKAGE1});
+ when(mPackageManager.getPackagesForUid(MOCK_USER2.getUid(SYSTEM_UID)))
+ .thenReturn(new String[]{SYSTEM_PACKAGE1});
+ removePackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2},
+ SYSTEM_PACKAGE2, SYSTEM_UID);
+ netdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2},
+ new int[]{SYSTEM_UID});
+
+ // Add SYSTEM_PACKAGE2, expect keep system permission.
+ addPackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2}, SYSTEM_PACKAGE2, SYSTEM_UID);
+ netdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2},
+ new int[]{SYSTEM_UID});
+
addPackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_PACKAGE1, MOCK_UID1);
netdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2},
new int[]{SYSTEM_UID});
@@ -549,6 +564,10 @@
new int[]{MOCK_UID1});
// Remove MOCK_UID1, expect no permission left for all user.
+ when(mPackageManager.getPackagesForUid(MOCK_USER1.getUid(MOCK_UID1)))
+ .thenReturn(new String[]{});
+ when(mPackageManager.getPackagesForUid(MOCK_USER2.getUid(MOCK_UID1)))
+ .thenReturn(new String[]{});
mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1);
removePackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_PACKAGE1, MOCK_UID1);
netdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1, MOCK_USER2},
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java b/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java
index f3ae9b0..40d4446 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java
@@ -46,6 +46,7 @@
import libcore.io.IoUtils;
import libcore.io.Streams;
+import libcore.testing.io.TestIoUtils;
import org.junit.After;
import org.junit.Before;
@@ -69,10 +70,7 @@
@Before
public void setUp() throws Exception {
- mTestProc = new File(InstrumentationRegistry.getContext().getFilesDir(), "proc");
- if (mTestProc.exists()) {
- IoUtils.deleteContents(mTestProc);
- }
+ mTestProc = TestIoUtils.createTemporaryDirectory("proc");
// The libandroid_servers which have the native method is not available to
// applications. So in order to have a test support native library, the native code
@@ -85,10 +83,6 @@
@After
public void tearDown() throws Exception {
mFactory = null;
-
- if (mTestProc.exists()) {
- IoUtils.deleteContents(mTestProc);
- }
}
@Test
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
index c32c1d2..ee94ae9 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -16,12 +16,17 @@
package com.android.server.net;
+import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
+import static android.Manifest.permission.UPDATE_DEVICE_STATS;
import static android.content.Intent.ACTION_UID_REMOVED;
import static android.content.Intent.EXTRA_UID;
+import static android.content.pm.PackageManager.PERMISSION_DENIED;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.NetworkIdentity.OEM_PAID;
import static android.net.NetworkIdentity.OEM_PRIVATE;
+import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
@@ -106,6 +111,7 @@
import android.provider.Settings;
import android.telephony.TelephonyManager;
+import androidx.annotation.Nullable;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -117,7 +123,7 @@
import com.android.testutils.HandlerUtils;
import com.android.testutils.TestableNetworkStatsProviderBinder;
-import libcore.io.IoUtils;
+import libcore.testing.io.TestIoUtils;
import org.junit.After;
import org.junit.Before;
@@ -200,6 +206,26 @@
if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager;
return mBaseContext.getSystemService(name);
}
+
+ @Override
+ public void enforceCallingOrSelfPermission(String permission, @Nullable String message) {
+ if (checkCallingOrSelfPermission(permission) != PERMISSION_GRANTED) {
+ throw new SecurityException("Test does not have mocked permission " + permission);
+ }
+ }
+
+ @Override
+ public int checkCallingOrSelfPermission(String permission) {
+ switch (permission) {
+ case PERMISSION_MAINLINE_NETWORK_STACK:
+ case READ_NETWORK_USAGE_HISTORY:
+ case UPDATE_DEVICE_STATS:
+ return PERMISSION_GRANTED;
+ default:
+ return PERMISSION_DENIED;
+ }
+
+ }
}
private final Clock mClock = new SimpleClock(ZoneOffset.UTC) {
@@ -213,10 +239,7 @@
MockitoAnnotations.initMocks(this);
final Context context = InstrumentationRegistry.getContext();
mServiceContext = new MockContext(context);
- mStatsDir = context.getFilesDir();
- if (mStatsDir.exists()) {
- IoUtils.deleteContents(mStatsDir);
- }
+ mStatsDir = TestIoUtils.createTemporaryDirectory(getClass().getSimpleName());
PowerManager powerManager = (PowerManager) mServiceContext.getSystemService(
Context.POWER_SERVICE);
@@ -285,8 +308,6 @@
@After
public void tearDown() throws Exception {
- IoUtils.deleteContents(mStatsDir);
-
mServiceContext = null;
mStatsDir = null;