Android 16.0.0 release 4

-----BEGIN PGP SIGNATURE-----
 
 iF0EABECAB0WIQRDQNE1cO+UXoOBCWTorT+BmrEOeAUCaS5huQAKCRDorT+BmrEO
 eIsnAJ9kJ9OjiHpwigt9XwjTrGcbD1hQ0QCfSw2VHyS9TLyzt7DZsQ3AYU+WVVA=
 =/SH/
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN SSH SIGNATURE-----
 U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgPpdpjxPACTIhnlvYz0GM4BR7FJ
 +rYv3jMbfxNKD3JvcAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5
 AAAAQHUBff/oLA1TO7KbbZDsBJZmFVcXgFmG+2K3aaKq9F0tiaT1kiNeHdjXpaLI07p344
 TExz9CBvFVft81pJyRBwY=
 -----END SSH SIGNATURE-----

Merge tag 'android-16.0.0_r4' into staging/lineage-23.2_merge-android-16.0.0_r4

Android 16.0.0 release 4

# -----BEGIN PGP SIGNATURE-----
#
# iF0EABECAB0WIQRDQNE1cO+UXoOBCWTorT+BmrEOeAUCaS5huQAKCRDorT+BmrEO
# eIsnAJ9kJ9OjiHpwigt9XwjTrGcbD1hQ0QCfSw2VHyS9TLyzt7DZsQ3AYU+WVVA=
# =/SH/
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue Dec  2 05:49:13 2025 EET
# gpg:                using DSA key 4340D13570EF945E83810964E8AD3F819AB10E78
# gpg: Good signature from "The Android Open Source Project <initial-contribution@android.com>" [ultimate]

# By Yan Yan (203) and others
# Via Automerger Merge Worker (1173) and others
* tag 'android-16.0.0_r4': (1057 commits)
  Use string for CREATE_APP_SPECIFIC_NETWORK permission
  bpf: move MSS calculation under CE check to avoid overhead
  BpfNetworkStats: use `atomic` for ifindex cache when possible
  NetBpfLoad: remove pointless 0 write.
  bpf: remove obsolete isAtLeastR/Sv2/25Q3
  NetBpfLoad: use global `api_level_full` directly in NetBpfLoad
  Log validated underlying network count that's available for VCN underlying network selection
  BpfUtils: fix sdk level detection logic for 25Q3+
  Add RTMGRP_IPV6_IFINFO
  bpf: remove BPFLOADER_MAINLINE_U_QPR3_VERSION
  bpf: move BPFLOADER_MAINLINE_S_VERSION into bpf_map_def.h
  Reduce log level for BluetoothSocket errors
  Bump the min sdk of Tethering
  BpfNetworkStats: apparently RiscV isn't actually a 64-bit architecture.
  KernelUtils.h: isAtLeastKernelVersion(x,y,z) - default 'z' to 0
  bpf_existence_test - update for tcp acc ecn
  bpf: tcpAccECN: eliminate header file and move more fully into netd
  BpfMap: shorten error strings to enable SSO (on 64-bit)
  BpfNetworkStats: enforce that IfaceValue access is lock-free
  NetBpfLoad: use libbpf based on mainline beta flag, part 2
  ...

 Conflicts:
	bpf/headers/include/bpf/KernelUtils.h
	bpf/progs/netd.h

Change-Id: I76a7aadc1405c6621e17f3d1b6b87640d84f5794
This commit is contained in:
Michael Bestas 2025-12-09 06:40:14 +02:00
commit 42374b293f
554 changed files with 53416 additions and 6658 deletions

View file

@ -11,4 +11,4 @@ xiaom@google.com
yuyanghuang@google.com yuyanghuang@google.com
martinwu@google.com #{LAST_RESORT_SUGGESTION} martinwu@google.com #{LAST_RESORT_SUGGESTION}
satk@google.com #{LAST_RESORT_SUGGESTION} larsberg@google.com #{LAST_RESORT_SUGGESTION}

View file

@ -1,5 +1,5 @@
lorenzo@google.com lorenzo@google.com
satk@google.com #{LAST_RESORT_SUGGESTION} larsberg@google.com #{LAST_RESORT_SUGGESTION}
# For cherry-picks of CLs that are already merged in aosp/master, flaky test # For cherry-picks of CLs that are already merged in aosp/master, flaky test
# fixes, or no-op refactors. # fixes, or no-op refactors.

View file

@ -15,6 +15,3 @@ ktlint_hook = ${REPO_ROOT}/prebuilts/ktlint/ktlint.py --disabled-rules comment-w
hidden_api_txt_checksorted_hook = ${REPO_ROOT}/tools/platform-compat/hiddenapi/checksorted_sha.sh ${PREUPLOAD_COMMIT} ${REPO_ROOT} hidden_api_txt_checksorted_hook = ${REPO_ROOT}/tools/platform-compat/hiddenapi/checksorted_sha.sh ${PREUPLOAD_COMMIT} ${REPO_ROOT}
python_hook = ${REPO_ROOT}/packages/modules/Connectivity/preupload_hook_script.py ${PREUPLOAD_FILES} python_hook = ${REPO_ROOT}/packages/modules/Connectivity/preupload_hook_script.py ${PREUPLOAD_FILES}
# go/alint for details
alint_hook = ${REPO_ROOT}/vendor/google/tools/alint

View file

@ -83,6 +83,14 @@
"exclude-annotation": "com.android.testutils.NetworkStackModuleTest" "exclude-annotation": "com.android.testutils.NetworkStackModuleTest"
} }
] ]
},
{
"name": "CtsHostsideNetworkTests",
"options": [
{
"exclude-annotation": "androidx.test.filters.RequiresDevice"
}
]
} }
], ],
"captiveportal-networkstack-mainline-presubmit": [ "captiveportal-networkstack-mainline-presubmit": [
@ -319,14 +327,6 @@
} }
] ]
}, },
{
"name": "CtsHostsideNetworkTests[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex+com.google.android.tethering.apex]",
"options": [
{
"exclude-annotation": "androidx.test.filters.RequiresDevice"
}
]
},
// Test with APK modules only, in cases where APEX is not supported, or the other modules // Test with APK modules only, in cases where APEX is not supported, or the other modules
// were simply not updated // were simply not updated
{ {
@ -435,12 +435,23 @@
"name": "CtsNetTestCasesUpdateStatsPermission" "name": "CtsNetTestCasesUpdateStatsPermission"
} }
], ],
"tv-presubmit": [ "hsum-presubmit": [
{ {
"name": "CtsNetTestCases" "name": "CtsNetTestCases"
}, },
{ {
"name": "CtsNativeNetTestCases" "name": "CtsNativeNetDnsTestCases"
},
{
"name": "CtsNetTestCasesInternetPermission"
},
{
"name": "CtsNetTestCasesUpdateStatsPermission"
}
],
"tv-presubmit": [
{
"name": "CtsNetTestCases"
}, },
{ {
"name": "CtsNativeNetDnsTestCases" "name": "CtsNativeNetDnsTestCases"
@ -471,5 +482,18 @@
{ {
"path": "vendor/xts/gts-tests/hostsidetests/networkstack" "path": "vendor/xts/gts-tests/hostsidetests/networkstack"
} }
],
"wear-cts-presubmit": [
{
"name": "CtsNetTestCases",
"options": [
{
"exclude-filter": "android.net.cts.NetworkValidationTest#testCapportApiCallbacks"
}
]
},
{
"name": "CtsNetTestCasesUpdateStatsPermission"
}
] ]
} }

View file

@ -22,7 +22,10 @@ package {
java_defaults { java_defaults {
name: "TetheringApiLevel", name: "TetheringApiLevel",
sdk_version: "module_current", sdk_version: "module_current",
min_sdk_version: "30", min_sdk_version: select(release_flag("RELEASE_DEPRECATE_MAINLINE_R_SUPPORT"), {
true: "31",
default: "30",
}),
} }
java_defaults { java_defaults {
@ -65,6 +68,8 @@ java_defaults {
"androidx.annotation_annotation", "androidx.annotation_annotation",
"connectivity-net-module-utils-bpf", "connectivity-net-module-utils-bpf",
"com.android.net.flags-aconfig-java", "com.android.net.flags-aconfig-java",
"com.android.tethering.beta.test.flags-aconfig-java",
"com.android.tethering.mainline.beta.flags-aconfig-java",
"modules-utils-build", "modules-utils-build",
"modules-utils-statemachine", "modules-utils-statemachine",
"networkstack-client", "networkstack-client",

View file

@ -67,6 +67,7 @@ apex {
"libservice-connectivity", "libservice-connectivity",
"libservice-thread-jni", "libservice-thread-jni",
"libandroid_net_connectivity_com_android_net_module_util_jni", "libandroid_net_connectivity_com_android_net_module_util_jni",
"libandroid_net_connectivity_com_android_net_module_util_jni_CommonConnectivityJni",
], ],
native_shared_libs: [ native_shared_libs: [
"libcom.android.tethering.dns_helper", "libcom.android.tethering.dns_helper",

View file

@ -33,20 +33,17 @@ import androidx.annotation.Nullable;
import com.android.net.module.util.IBpfMap; import com.android.net.module.util.IBpfMap;
import com.android.net.module.util.IBpfMap.ThrowingBiConsumer; import com.android.net.module.util.IBpfMap.ThrowingBiConsumer;
import com.android.net.module.util.SharedLog; import com.android.net.module.util.SharedLog;
import com.android.net.module.util.Struct.S32;
import com.android.net.module.util.Struct.S64;
import com.android.net.module.util.bpf.Tether4Key; import com.android.net.module.util.bpf.Tether4Key;
import com.android.net.module.util.bpf.Tether4Value; import com.android.net.module.util.bpf.Tether4Value;
import com.android.net.module.util.bpf.TetherStatsKey;
import com.android.net.module.util.bpf.TetherStatsValue; import com.android.net.module.util.bpf.TetherStatsValue;
import com.android.networkstack.tethering.BpfCoordinator.Dependencies; import com.android.networkstack.tethering.BpfCoordinator.Dependencies;
import com.android.networkstack.tethering.BpfCoordinator.Ipv6DownstreamRule; import com.android.networkstack.tethering.BpfCoordinator.Ipv6DownstreamRule;
import com.android.networkstack.tethering.BpfCoordinator.Ipv6UpstreamRule; import com.android.networkstack.tethering.BpfCoordinator.Ipv6UpstreamRule;
import com.android.networkstack.tethering.BpfUtils; import com.android.networkstack.tethering.BpfUtils;
import com.android.networkstack.tethering.Tether6Value; import com.android.networkstack.tethering.Tether6Value;
import com.android.networkstack.tethering.TetherDevKey;
import com.android.networkstack.tethering.TetherDevValue;
import com.android.networkstack.tethering.TetherDownstream6Key; import com.android.networkstack.tethering.TetherDownstream6Key;
import com.android.networkstack.tethering.TetherLimitKey;
import com.android.networkstack.tethering.TetherLimitValue;
import com.android.networkstack.tethering.TetherUpstream6Key; import com.android.networkstack.tethering.TetherUpstream6Key;
import java.io.FileDescriptor; import java.io.FileDescriptor;
@ -85,15 +82,15 @@ public class BpfCoordinatorShimImpl
// BPF map of tethering statistics of the upstream interface since tethering startup. // BPF map of tethering statistics of the upstream interface since tethering startup.
@Nullable @Nullable
private final IBpfMap<TetherStatsKey, TetherStatsValue> mBpfStatsMap; private final IBpfMap<S32, TetherStatsValue> mBpfStatsMap;
// BPF map of per-interface quota for tethering offload. // BPF map of per-interface quota for tethering offload.
@Nullable @Nullable
private final IBpfMap<TetherLimitKey, TetherLimitValue> mBpfLimitMap; private final IBpfMap<S32, S64> mBpfLimitMap;
// BPF map of interface index mapping for XDP. // BPF map of interface index mapping for XDP.
@Nullable @Nullable
private final IBpfMap<TetherDevKey, TetherDevValue> mBpfDevMap; private final IBpfMap<S32, S32> mBpfDevMap;
// Tracking IPv4 rule count while any rule is using the given upstream interfaces. Used for // Tracking IPv4 rule count while any rule is using the given upstream interfaces. Used for
// reducing the BPF map iteration query. The count is increased or decreased when the rule is // reducing the BPF map iteration query. The count is increased or decreased when the rule is
@ -252,7 +249,7 @@ public class BpfCoordinatorShimImpl
try { try {
// The reported tether stats are total data usage for all currently-active upstream // The reported tether stats are total data usage for all currently-active upstream
// interfaces since tethering start. // interfaces since tethering start.
mBpfStatsMap.forEach((key, value) -> tetherStatsList.put((int) key.ifindex, value)); mBpfStatsMap.forEach((key, value) -> tetherStatsList.put((int) key.val, value));
} catch (ErrnoException e) { } catch (ErrnoException e) {
mLog.e("Fail to fetch tethering stats from BPF map: ", e); mLog.e("Fail to fetch tethering stats from BPF map: ", e);
return null; return null;
@ -269,7 +266,7 @@ public class BpfCoordinatorShimImpl
TetherStatsValue statsValue = null; TetherStatsValue statsValue = null;
try { try {
statsValue = mBpfStatsMap.getValue(new TetherStatsKey(ifIndex)); statsValue = mBpfStatsMap.getValue(new S32(ifIndex));
} catch (ErrnoException e) { } catch (ErrnoException e) {
// The BpfMap#getValue doesn't throw an errno ENOENT exception. Catch other error // The BpfMap#getValue doesn't throw an errno ENOENT exception. Catch other error
// while trying to get stats entry. // while trying to get stats entry.
@ -287,7 +284,7 @@ public class BpfCoordinatorShimImpl
// This function is the *only* thing that can create entries. // This function is the *only* thing that can create entries.
// BpfMap#insertEntry use BPF_NOEXIST to create the entry. The entry is created // BpfMap#insertEntry use BPF_NOEXIST to create the entry. The entry is created
// if and only if it doesn't exist. // if and only if it doesn't exist.
mBpfStatsMap.insertEntry(new TetherStatsKey(ifIndex), new TetherStatsValue( mBpfStatsMap.insertEntry(new S32(ifIndex), new TetherStatsValue(
0 /* rxPackets */, 0 /* rxBytes */, 0 /* rxErrors */, 0 /* txPackets */, 0 /* rxPackets */, 0 /* rxBytes */, 0 /* rxErrors */, 0 /* txPackets */,
0 /* txBytes */, 0 /* txErrors */)); 0 /* txBytes */, 0 /* txErrors */));
} catch (ErrnoException | IllegalArgumentException e) { } catch (ErrnoException | IllegalArgumentException e) {
@ -305,7 +302,7 @@ public class BpfCoordinatorShimImpl
if (newLimit < rxBytes + txBytes) newLimit = QUOTA_UNLIMITED; if (newLimit < rxBytes + txBytes) newLimit = QUOTA_UNLIMITED;
try { try {
mBpfLimitMap.updateEntry(new TetherLimitKey(ifIndex), new TetherLimitValue(newLimit)); mBpfLimitMap.updateEntry(new S32(ifIndex), new S64(newLimit));
} catch (ErrnoException e) { } catch (ErrnoException e) {
mLog.e("Fail to set quota " + quotaBytes + " for interface index " + ifIndex + ": ", e); mLog.e("Fail to set quota " + quotaBytes + " for interface index " + ifIndex + ": ", e);
return false; return false;
@ -331,7 +328,7 @@ public class BpfCoordinatorShimImpl
TetherStatsValue statsValue = null; TetherStatsValue statsValue = null;
try { try {
statsValue = mBpfStatsMap.getValue(new TetherStatsKey(ifIndex)); statsValue = mBpfStatsMap.getValue(new S32(ifIndex));
} catch (ErrnoException e) { } catch (ErrnoException e) {
mLog.e("Could not get stats entry for interface index " + ifIndex + ": ", e); mLog.e("Could not get stats entry for interface index " + ifIndex + ": ", e);
return null; return null;
@ -343,14 +340,14 @@ public class BpfCoordinatorShimImpl
} }
try { try {
mBpfStatsMap.deleteEntry(new TetherStatsKey(ifIndex)); mBpfStatsMap.deleteEntry(new S32(ifIndex));
} catch (ErrnoException e) { } catch (ErrnoException e) {
mLog.e("Could not delete stats entry for interface index " + ifIndex + ": ", e); mLog.e("Could not delete stats entry for interface index " + ifIndex + ": ", e);
return null; return null;
} }
try { try {
mBpfLimitMap.deleteEntry(new TetherLimitKey(ifIndex)); mBpfLimitMap.deleteEntry(new S32(ifIndex));
} catch (ErrnoException e) { } catch (ErrnoException e) {
mLog.e("Could not delete limit for interface index " + ifIndex + ": ", e); mLog.e("Could not delete limit for interface index " + ifIndex + ": ", e);
return null; return null;
@ -470,7 +467,7 @@ public class BpfCoordinatorShimImpl
@Override @Override
public boolean addDevMap(int ifIndex) { public boolean addDevMap(int ifIndex) {
try { try {
mBpfDevMap.updateEntry(new TetherDevKey(ifIndex), new TetherDevValue(ifIndex)); mBpfDevMap.updateEntry(new S32(ifIndex), new S32(ifIndex));
} catch (ErrnoException e) { } catch (ErrnoException e) {
mLog.e("Could not add interface " + ifIndex + ": " + e); mLog.e("Could not add interface " + ifIndex + ": " + e);
return false; return false;
@ -481,7 +478,7 @@ public class BpfCoordinatorShimImpl
@Override @Override
public boolean removeDevMap(int ifIndex) { public boolean removeDevMap(int ifIndex) {
try { try {
mBpfDevMap.deleteEntry(new TetherDevKey(ifIndex)); mBpfDevMap.deleteEntry(new S32(ifIndex));
} catch (ErrnoException e) { } catch (ErrnoException e) {
mLog.e("Could not delete interface " + ifIndex + ": " + e); mLog.e("Could not delete interface " + ifIndex + ": " + e);
return false; return false;

View file

@ -34,8 +34,9 @@ java_sdk_library {
// Using for test only // Using for test only
"//cts/tests/netlegacy22.api", "//cts/tests/netlegacy22.api",
// TODO: b/374174952 Remove it when VCN CTS is moved to Connectivity/ // TODO: b/374174952 Clean up VCN paths when the code location is finalized
"//cts/tests/tests/vcn", "//cts/tests/tests/vcn",
"//packages/modules/Connectivity/Vcn/tests:__subpackages__",
"//external/sl4a:__subpackages__", "//external/sl4a:__subpackages__",
"//frameworks/base/core/tests/bandwidthtests", "//frameworks/base/core/tests/bandwidthtests",

View file

@ -18,7 +18,7 @@ package android.net;
/** /**
* Listener interface allowing objects to listen to various module event. * Listener interface allowing objects to listen to various module event.
* {@hide} * @hide
*/ */
oneway interface IIntResultListener { oneway interface IIntResultListener {
void onResult(int resultCode); void onResult(int resultCode);

View file

@ -20,7 +20,7 @@ import android.net.TetheringInterface;
/** /**
* Status details for tethering downstream interfaces. * Status details for tethering downstream interfaces.
* {@hide} * @hide
*/ */
parcelable TetherStatesParcel { parcelable TetherStatesParcel {
TetheringInterface[] availableList; TetheringInterface[] availableList;

View file

@ -381,7 +381,7 @@ public class TetheringManager {
* @param context Context for the manager. * @param context Context for the manager.
* @param connectorSupplier Supplier for the manager connector; may return null while the * @param connectorSupplier Supplier for the manager connector; may return null while the
* service is not connected. * service is not connected.
* {@hide} * @hide
*/ */
@SystemApi(client = MODULE_LIBRARIES) @SystemApi(client = MODULE_LIBRARIES)
public TetheringManager(@NonNull final Context context, public TetheringManager(@NonNull final Context context,
@ -574,7 +574,7 @@ public class TetheringManager {
* already released. * already released.
* 2. This is not synchronous, so it's not useful to use try-with-resources. * 2. This is not synchronous, so it's not useful to use try-with-resources.
* *
* {@hide} * @hide
*/ */
@SystemApi(client = MODULE_LIBRARIES) @SystemApi(client = MODULE_LIBRARIES)
@SuppressLint("NotCloseable") @SuppressLint("NotCloseable")
@ -588,7 +588,7 @@ public class TetheringManager {
/** /**
* Callback for requestTetheredInterface. * Callback for requestTetheredInterface.
* *
* {@hide} * @hide
*/ */
@SystemApi(client = MODULE_LIBRARIES) @SystemApi(client = MODULE_LIBRARIES)
public interface TetheredInterfaceCallback { public interface TetheredInterfaceCallback {
@ -694,7 +694,7 @@ public class TetheringManager {
* @param iface the interface name to tether. * @param iface the interface name to tether.
* @return error a {@code TETHER_ERROR} value indicating success or failure type * @return error a {@code TETHER_ERROR} value indicating success or failure type
* *
* {@hide} * @hide
*/ */
@Deprecated @Deprecated
@SystemApi(client = MODULE_LIBRARIES) @SystemApi(client = MODULE_LIBRARIES)
@ -729,7 +729,7 @@ public class TetheringManager {
* On SDK versions after {@link Build.VERSION_CODES.VANILLA_ICE_CREAM}, this will * On SDK versions after {@link Build.VERSION_CODES.VANILLA_ICE_CREAM}, this will
* throw an UnsupportedOperationException. * throw an UnsupportedOperationException.
* *
* {@hide} * @hide
*/ */
@Deprecated @Deprecated
@SystemApi(client = MODULE_LIBRARIES) @SystemApi(client = MODULE_LIBRARIES)
@ -758,7 +758,7 @@ public class TetheringManager {
* used and an entitlement check is needed, downstream USB tethering will be enabled but will * used and an entitlement check is needed, downstream USB tethering will be enabled but will
* not have any upstream. * not have any upstream.
* *
* {@hide} * @hide
*/ */
@Deprecated @Deprecated
@SystemApi(client = MODULE_LIBRARIES) @SystemApi(client = MODULE_LIBRARIES)
@ -1553,7 +1553,7 @@ public class TetheringManager {
* Helper function of #requestLatestTetheringEntitlementResult to remain backwards compatible * Helper function of #requestLatestTetheringEntitlementResult to remain backwards compatible
* with ConnectivityManager#getLatestTetheringEntitlementResult * with ConnectivityManager#getLatestTetheringEntitlementResult
* *
* {@hide} * @hide
*/ */
// TODO: improve the usage of ResultReceiver, b/145096122 // TODO: improve the usage of ResultReceiver, b/145096122
@SystemApi(client = MODULE_LIBRARIES) @SystemApi(client = MODULE_LIBRARIES)

View file

@ -0,0 +1,37 @@
/*
* Copyright (C) 2025 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "com_android_networkstack_tethering_util_CommonConnectivityJni"
#include <android/log.h>
#include <nativehelper/JNIHelp.h>
namespace android {
int register_CommonConnectivityJni(JNIEnv *env, char const *class_name);
extern "C" jint JNI_OnLoad(JavaVM *vm, void *) {
JNIEnv *env;
if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) !=
JNI_OK) {
__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "ERROR: GetEnv failed");
return JNI_ERR;
}
if (register_CommonConnectivityJni(env,
"com/android/networkstack/tethering/util/CommonConnectivityJni") < 0) return JNI_ERR;
return JNI_VERSION_1_6;
}
}; // namespace android

View file

@ -23,6 +23,7 @@
namespace android { namespace android {
int register_com_android_net_module_util_BpfMap(JNIEnv* env, char const* class_name); int register_com_android_net_module_util_BpfMap(JNIEnv* env, char const* class_name);
int register_com_android_net_module_util_BpfBitmap(JNIEnv* env, char const* class_name);
int register_com_android_net_module_util_TcUtils(JNIEnv* env, char const* class_name); int register_com_android_net_module_util_TcUtils(JNIEnv* env, char const* class_name);
int register_com_android_networkstack_tethering_BpfCoordinator(JNIEnv* env); int register_com_android_networkstack_tethering_BpfCoordinator(JNIEnv* env);
int register_com_android_networkstack_tethering_util_TetheringUtils(JNIEnv* env); int register_com_android_networkstack_tethering_util_TetheringUtils(JNIEnv* env);
@ -39,6 +40,9 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
if (register_com_android_net_module_util_BpfMap(env, if (register_com_android_net_module_util_BpfMap(env,
"com/android/networkstack/tethering/util/BpfMap") < 0) return JNI_ERR; "com/android/networkstack/tethering/util/BpfMap") < 0) return JNI_ERR;
if (register_com_android_net_module_util_BpfBitmap(env,
"com/android/networkstack/tethering/util/BpfBitmap") < 0) return JNI_ERR;
if (register_com_android_net_module_util_TcUtils(env, if (register_com_android_net_module_util_TcUtils(env,
"com/android/networkstack/tethering/util/TcUtils") < 0) return JNI_ERR; "com/android/networkstack/tethering/util/TcUtils") < 0) return JNI_ERR;

View file

@ -39,11 +39,11 @@ import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
import static android.net.util.NetworkConstants.asByte; import static android.net.util.NetworkConstants.asByte;
import static android.system.OsConstants.RT_SCOPE_UNIVERSE; import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
import static com.android.net.module.util.ConnectivityCommonFlags.USE_ROUTE_PARCEL_IPCS;
import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH; import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH;
import static com.android.net.module.util.NetworkStackConstants.RFC7421_PREFIX_LENGTH; import static com.android.net.module.util.NetworkStackConstants.RFC7421_PREFIX_LENGTH;
import static com.android.networkstack.tethering.TetheringConfiguration.USE_SYNC_SM; import static com.android.networkstack.tethering.TetheringConfiguration.USE_SYNC_SM;
import static com.android.networkstack.tethering.TetheringFeatureFlags.TETHERING_LOCAL_NETWORK_AGENT; import static com.android.networkstack.tethering.TetheringFeatureFlags.TETHERING_AND_P2P_GO_LOCAL_AGENT;
import static com.android.networkstack.tethering.TetheringFeatureFlags.WIFIP2PGO_LOCAL_NETWORK_AGENT;
import static com.android.networkstack.tethering.util.PrefixUtils.asIpPrefix; import static com.android.networkstack.tethering.util.PrefixUtils.asIpPrefix;
import static com.android.networkstack.tethering.util.TetheringMessageBase.BASE_IPSERVER; import static com.android.networkstack.tethering.util.TetheringMessageBase.BASE_IPSERVER;
import static com.android.networkstack.tethering.util.TetheringUtils.getTransportTypeForTetherableType; import static com.android.networkstack.tethering.util.TetheringUtils.getTransportTypeForTetherableType;
@ -91,6 +91,7 @@ import com.android.net.module.util.IIpv4PrefixRequest;
import com.android.net.module.util.InterfaceParams; import com.android.net.module.util.InterfaceParams;
import com.android.net.module.util.NetdUtils; import com.android.net.module.util.NetdUtils;
import com.android.net.module.util.RoutingCoordinatorManager; import com.android.net.module.util.RoutingCoordinatorManager;
import com.android.net.module.util.SdkUtil;
import com.android.net.module.util.SharedLog; import com.android.net.module.util.SharedLog;
import com.android.net.module.util.SyncStateMachine.StateInfo; import com.android.net.module.util.SyncStateMachine.StateInfo;
import com.android.net.module.util.ip.InterfaceController; import com.android.net.module.util.ip.InterfaceController;
@ -100,6 +101,7 @@ import com.android.networkstack.tethering.metrics.TetheringMetrics;
import com.android.networkstack.tethering.util.InterfaceSet; import com.android.networkstack.tethering.util.InterfaceSet;
import com.android.networkstack.tethering.util.PrefixUtils; import com.android.networkstack.tethering.util.PrefixUtils;
import com.android.networkstack.tethering.util.StateMachineShim; import com.android.networkstack.tethering.util.StateMachineShim;
import com.android.tethering.mainline.beta.Flags;
import java.net.Inet4Address; import java.net.Inet4Address;
import java.net.Inet6Address; import java.net.Inet6Address;
@ -218,10 +220,24 @@ public class IpServer extends StateMachineShim {
DhcpServerCallbacks cb); DhcpServerCallbacks cb);
/** /**
* @see DeviceConfigUtils#isTetheringFeatureEnabled * Get whether a tethering feature flag is enabled via chickened out.
* @param name the name of the feature.
*/ */
public boolean isFeatureEnabled(Context context, String name) { public boolean isTetheringFeatureNotChickenedOut(@NonNull Context context,
return DeviceConfigUtils.isTetheringFeatureEnabled(context, name); @NonNull String name) {
return DeviceConfigUtils.isTetheringFeatureNotChickenedOut(context, name);
}
/** Get whether tethering and P2P GO local agent flag is enabled via beta flags. */
public boolean isTetheringAndP2pGoLocalAgentBetaFlagEnabled() {
return Flags.tetheringAndP2pGoLocalAgent();
}
/**
* @see DeviceConfigUtils#isTetheringFeatureNotChickenedOut
*/
public boolean isFeatureNotChickenedOut(Context context, String name) {
return DeviceConfigUtils.isTetheringFeatureNotChickenedOut(context, name);
} }
/** Create a NetworkAgent instance to be used by IpServer. */ /** Create a NetworkAgent instance to be used by IpServer. */
@ -288,6 +304,7 @@ public class IpServer extends StateMachineShim {
private final boolean mUsingLegacyDhcp; private final boolean mUsingLegacyDhcp;
private final int mP2pLeasesSubnetPrefixLength; private final int mP2pLeasesSubnetPrefixLength;
private final boolean mIsWifiP2pDedicatedIpEnabled; private final boolean mIsWifiP2pDedicatedIpEnabled;
private final boolean mUseRouteParcel;
private final Dependencies mDeps; private final Dependencies mDeps;
@ -335,8 +352,8 @@ public class IpServer extends StateMachineShim {
private final Handler mHandler; private final Handler mHandler;
private final Context mContext; private final Context mContext;
private final boolean mSupportTetheringLocalAgent; // Whether to enable tethering and Wi-Fi P2p Group Owner mode local network agent.
private final boolean mSupportWifiP2pGroupOwnerLocalAgent; private final boolean mSupportTetheringAndP2pGoLocalAgent;
// This will be null if the TetheredState is not entered or feature not supported. // This will be null if the TetheredState is not entered or feature not supported.
// This will be only accessed from the IpServer handler thread. // This will be only accessed from the IpServer handler thread.
@ -381,11 +398,21 @@ public class IpServer extends StateMachineShim {
mLastError = TETHER_ERROR_NO_ERROR; mLastError = TETHER_ERROR_NO_ERROR;
mServingMode = STATE_AVAILABLE; mServingMode = STATE_AVAILABLE;
// Tethering network agent is supported on V+, and will be rolled out gradually. // Determines support for the Tethering/P2P GO local network agent. This feature is
mSupportTetheringLocalAgent = SdkLevel.isAtLeastV() // gated on Android V+ because it requires NET_CAPABILITY_LOCAL_NETWORK.
&& mDeps.isFeatureEnabled(mContext, TETHERING_LOCAL_NETWORK_AGENT); // For 25Q4+, it is enabled by default with a kill switch to prevent impacting
mSupportWifiP2pGroupOwnerLocalAgent = mSupportTetheringLocalAgent // existing devices if issues arise. For older V+ devices, rollout is controlled
&& mDeps.isFeatureEnabled(mContext, WIFIP2PGO_LOCAL_NETWORK_AGENT); // by a mainline beta flag.
mSupportTetheringAndP2pGoLocalAgent = SdkLevel.isAtLeastV()
&& (SdkUtil.isAtLeast25Q4()
? mDeps.isTetheringFeatureNotChickenedOut(mContext,
TETHERING_AND_P2P_GO_LOCAL_AGENT)
: mDeps.isTetheringAndP2pGoLocalAgentBetaFlagEnabled());
// For post 25Q2 releases always use *RouteParcel methods. For 25Q2 or lower, decide based
// on kill-switch
mUseRouteParcel = SdkUtil.isAtLeast25Q4()
|| mDeps.isFeatureNotChickenedOut(mContext, USE_ROUTE_PARCEL_IPCS);
mInitialState = new InitialState(); mInitialState = new InitialState();
mLocalHotspotState = new LocalHotspotState(); mLocalHotspotState = new LocalHotspotState();
@ -848,6 +875,7 @@ public class IpServer extends StateMachineShim {
String upstreamIface = null; String upstreamIface = null;
InterfaceParams upstreamIfaceParams = null; InterfaceParams upstreamIfaceParams = null;
int upstreamIfIndex = NO_UPSTREAM; int upstreamIfIndex = NO_UPSTREAM;
int pmtu6 = 1400; // default 'safe-ish' value
if (v6only != null) { if (v6only != null) {
upstreamIface = v6only.getInterfaceName(); upstreamIface = v6only.getInterfaceName();
@ -856,7 +884,14 @@ public class IpServer extends StateMachineShim {
upstreamIfIndex = upstreamIfaceParams.index; upstreamIfIndex = upstreamIfaceParams.index;
} }
params = new RaParams(); params = new RaParams();
params.mtu = v6only.getMtu(); pmtu6 = v6only.getMtu();
if (pmtu6 < 1280) pmtu6 = 1400; // we simply don't know what it is, 1400 is safe-ish
for (RouteInfo route : v6only.getRoutes()) {
if (route.getMtu() >= 1280) pmtu6 = Math.min(pmtu6, route.getMtu());
}
// Clamp v6 MTU to 1280-1500 range.
if (pmtu6 > 1500) pmtu6 = 1500;
params.mtu = pmtu6;
params.hasDefaultRoute = v6only.hasIpv6DefaultRoute(); params.hasDefaultRoute = v6only.hasIpv6DefaultRoute();
if (params.hasDefaultRoute) params.hopLimit = getHopLimit(upstreamIface, ttlAdjustment); if (params.hasDefaultRoute) params.hopLimit = getHopLimit(upstreamIface, ttlAdjustment);
@ -874,6 +909,8 @@ public class IpServer extends StateMachineShim {
// CMD_TETHER_CONNECTION_CHANGED. Adding the mapping update here to the avoid potential // CMD_TETHER_CONNECTION_CHANGED. Adding the mapping update here to the avoid potential
// timing issue. It prevents that the IPv6 capability is updated later than // timing issue. It prevents that the IPv6 capability is updated later than
// CMD_TETHER_CONNECTION_CHANGED. // CMD_TETHER_CONNECTION_CHANGED.
//
// TODO: I believe we need to push v6mtu into this call.
mBpfCoordinator.maybeAddUpstreamToLookupTable(upstreamIfIndex, upstreamIface); mBpfCoordinator.maybeAddUpstreamToLookupTable(upstreamIfIndex, upstreamIface);
// If v6only is null, we pass in null to setRaParams(), which handles // If v6only is null, we pass in null to setRaParams(), which handles
@ -886,7 +923,7 @@ public class IpServer extends StateMachineShim {
// mLastIPv6UpstreamIfindex and mLastIPv6UpstreamPrefixes because BpfCoordinator will call // mLastIPv6UpstreamIfindex and mLastIPv6UpstreamPrefixes because BpfCoordinator will call
// IpServer#getIpv6UpstreamIfindex and IpServer#getIpv6UpstreamPrefixes to retrieve current // IpServer#getIpv6UpstreamIfindex and IpServer#getIpv6UpstreamPrefixes to retrieve current
// upstream interface index and prefixes when handling upstream changes. // upstream interface index and prefixes when handling upstream changes.
mBpfCoordinator.updateIpv6UpstreamInterface(this, upstreamIfIndex, upstreamPrefixes); mBpfCoordinator.updateIpv6UpstreamInterface(this, upstreamIfIndex, upstreamPrefixes, pmtu6);
mLastIPv6LinkProperties = v6only; mLastIPv6LinkProperties = v6only;
mLastIPv6UpstreamIfindex = upstreamIfIndex; mLastIPv6UpstreamIfindex = upstreamIfIndex;
mLastIPv6UpstreamPrefixes = upstreamPrefixes; mLastIPv6UpstreamPrefixes = upstreamPrefixes;
@ -896,7 +933,8 @@ public class IpServer extends StateMachineShim {
} }
private void removeRoutesFromNetwork(int netId, @NonNull final List<RouteInfo> toBeRemoved) { private void removeRoutesFromNetwork(int netId, @NonNull final List<RouteInfo> toBeRemoved) {
final int removalFailures = NetdUtils.removeRoutesFromNetwork(mNetd, netId, toBeRemoved); final int removalFailures = NetdUtils.removeRoutesFromNetwork(mNetd, netId, toBeRemoved,
mUseRouteParcel);
if (removalFailures > 0) { if (removalFailures > 0) {
mLog.e("Failed to remove " + removalFailures mLog.e("Failed to remove " + removalFailures
+ " IPv6 routes from network " + netId + "."); + " IPv6 routes from network " + netId + ".");
@ -927,15 +965,14 @@ public class IpServer extends StateMachineShim {
} }
} }
private void addRoutesToNetwork(int netId, private void addRoutesToNetwork(int netId, @NonNull final List<RouteInfo> toBeAdded) {
@NonNull final List<RouteInfo> toBeAdded) {
// It's safe to call addInterfaceToNetwork() even if // It's safe to call addInterfaceToNetwork() even if
// the interface is already in the network. // the interface is already in the network.
addInterfaceToNetwork(netId, mIfaceName); addInterfaceToNetwork(netId, mIfaceName);
try { try {
// Add routes from local network. Note that adding routes that // Add routes from local network. Note that adding routes that
// already exist does not cause an error (EEXIST is silently ignored). // already exist does not cause an error (EEXIST is silently ignored).
NetdUtils.addRoutesToNetwork(mNetd, netId, mIfaceName, toBeAdded); NetdUtils.addRoutesToNetwork(mNetd, netId, mIfaceName, toBeAdded, mUseRouteParcel);
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
mLog.e("Failed to add IPv4/v6 routes to local table: " + e); mLog.e("Failed to add IPv4/v6 routes to local table: " + e);
return; return;
@ -949,6 +986,7 @@ public class IpServer extends StateMachineShim {
final List<RouteInfo> routesToBeRemoved = final List<RouteInfo> routesToBeRemoved =
getLocalRoutesFor(mIfaceName, deprecatedPrefixes); getLocalRoutesFor(mIfaceName, deprecatedPrefixes);
if (mTetheringAgent == null) { if (mTetheringAgent == null) {
// Routes for local network are not considered local routes.
removeRoutesFromNetwork(LOCAL_NET_ID, routesToBeRemoved); removeRoutesFromNetwork(LOCAL_NET_ID, routesToBeRemoved);
} }
for (RouteInfo route : routesToBeRemoved) mLinkProperties.removeRoute(route); for (RouteInfo route : routesToBeRemoved) mLinkProperties.removeRoute(route);
@ -1166,8 +1204,7 @@ public class IpServer extends StateMachineShim {
@SuppressLint("NewApi") @SuppressLint("NewApi")
private void startServingInterface() { private void startServingInterface() {
if (mSupportTetheringLocalAgent && (mSupportWifiP2pGroupOwnerLocalAgent if (mSupportTetheringAndP2pGoLocalAgent) {
|| getScope() != CONNECTIVITY_SCOPE_LOCAL)) {
try { try {
mTetheringAgent = mDeps.makeNetworkAgent(mContext, Looper.myLooper(), TAG, mTetheringAgent = mDeps.makeNetworkAgent(mContext, Looper.myLooper(), TAG,
mInterfaceType, mLinkProperties); mInterfaceType, mLinkProperties);
@ -1197,10 +1234,11 @@ public class IpServer extends StateMachineShim {
20 /* maxAttempts */, 50 /* pollingIntervalMs */); 20 /* maxAttempts */, 50 /* pollingIntervalMs */);
// Activate a route to dest and IPv6 link local. // Activate a route to dest and IPv6 link local.
NetdUtils.modifyRoute(mNetd, NetdUtils.ModifyOperation.ADD, LOCAL_NET_ID, NetdUtils.modifyRoute(mNetd, NetdUtils.ModifyOperation.ADD, LOCAL_NET_ID,
new RouteInfo(asIpPrefix(mIpv4Address), null, mIfaceName, RTN_UNICAST)); new RouteInfo(asIpPrefix(mIpv4Address), null, mIfaceName,
RTN_UNICAST), mUseRouteParcel);
NetdUtils.modifyRoute(mNetd, NetdUtils.ModifyOperation.ADD, LOCAL_NET_ID, NetdUtils.modifyRoute(mNetd, NetdUtils.ModifyOperation.ADD, LOCAL_NET_ID,
new RouteInfo(new IpPrefix("fe80::/64"), null, mIfaceName, new RouteInfo(new IpPrefix("fe80::/64"), null, mIfaceName,
RTN_UNICAST)); RTN_UNICAST), mUseRouteParcel);
} }
} catch (RemoteException | ServiceSpecificException | IllegalStateException e) { } catch (RemoteException | ServiceSpecificException | IllegalStateException e) {
mLog.e("Error Tethering", e); mLog.e("Error Tethering", e);
@ -1330,6 +1368,7 @@ public class IpServer extends StateMachineShim {
final List<RouteInfo> routesToBeRemoved = final List<RouteInfo> routesToBeRemoved =
List.of(getDirectConnectedRoute(deprecatedLinkAddress)); List.of(getDirectConnectedRoute(deprecatedLinkAddress));
if (mTetheringAgent == null) { if (mTetheringAgent == null) {
// Routes for local network are not considered local routes.
removeRoutesFromNetwork(LOCAL_NET_ID, routesToBeRemoved); removeRoutesFromNetwork(LOCAL_NET_ID, routesToBeRemoved);
} }
for (RouteInfo route : routesToBeRemoved) mLinkProperties.removeRoute(route); for (RouteInfo route : routesToBeRemoved) mLinkProperties.removeRoute(route);
@ -1440,7 +1479,7 @@ public class IpServer extends StateMachineShim {
for (String ifname : mUpstreamIfaceSet.ifnames) cleanupUpstreamInterface(ifname); for (String ifname : mUpstreamIfaceSet.ifnames) cleanupUpstreamInterface(ifname);
mUpstreamIfaceSet = null; mUpstreamIfaceSet = null;
mBpfCoordinator.updateIpv6UpstreamInterface(IpServer.this, NO_UPSTREAM, mBpfCoordinator.updateIpv6UpstreamInterface(IpServer.this, NO_UPSTREAM,
Collections.emptySet()); Collections.emptySet(), 1400);
} }
private void cleanupUpstreamInterface(String upstreamIface) { private void cleanupUpstreamInterface(String upstreamIface) {

View file

@ -74,9 +74,9 @@ import com.android.net.module.util.InterfaceParams;
import com.android.net.module.util.NetworkStackConstants; import com.android.net.module.util.NetworkStackConstants;
import com.android.net.module.util.SharedLog; import com.android.net.module.util.SharedLog;
import com.android.net.module.util.Struct.S32; import com.android.net.module.util.Struct.S32;
import com.android.net.module.util.Struct.S64;
import com.android.net.module.util.bpf.Tether4Key; import com.android.net.module.util.bpf.Tether4Key;
import com.android.net.module.util.bpf.Tether4Value; import com.android.net.module.util.bpf.Tether4Value;
import com.android.net.module.util.bpf.TetherStatsKey;
import com.android.net.module.util.bpf.TetherStatsValue; import com.android.net.module.util.bpf.TetherStatsValue;
import com.android.net.module.util.ip.ConntrackMonitor; import com.android.net.module.util.ip.ConntrackMonitor;
import com.android.net.module.util.ip.ConntrackMonitor.ConntrackEventConsumer; import com.android.net.module.util.ip.ConntrackMonitor.ConntrackEventConsumer;
@ -448,11 +448,11 @@ public class BpfCoordinator {
} }
/** Get stats BPF map. */ /** Get stats BPF map. */
@Nullable public IBpfMap<TetherStatsKey, TetherStatsValue> getBpfStatsMap() { @Nullable public IBpfMap<S32, TetherStatsValue> getBpfStatsMap() {
if (!isAtLeastS()) return null; if (!isAtLeastS()) return null;
try { try {
return new BpfMap<>(TETHER_STATS_MAP_PATH, return new BpfMap<>(TETHER_STATS_MAP_PATH,
TetherStatsKey.class, TetherStatsValue.class); S32.class, TetherStatsValue.class);
} catch (ErrnoException e) { } catch (ErrnoException e) {
Log.e(TAG, "Cannot create stats map: " + e); Log.e(TAG, "Cannot create stats map: " + e);
return null; return null;
@ -460,11 +460,11 @@ public class BpfCoordinator {
} }
/** Get limit BPF map. */ /** Get limit BPF map. */
@Nullable public IBpfMap<TetherLimitKey, TetherLimitValue> getBpfLimitMap() { @Nullable public IBpfMap<S32, S64> getBpfLimitMap() {
if (!isAtLeastS()) return null; if (!isAtLeastS()) return null;
try { try {
return new BpfMap<>(TETHER_LIMIT_MAP_PATH, return new BpfMap<>(TETHER_LIMIT_MAP_PATH,
TetherLimitKey.class, TetherLimitValue.class); S32.class, S64.class);
} catch (ErrnoException e) { } catch (ErrnoException e) {
Log.e(TAG, "Cannot create limit map: " + e); Log.e(TAG, "Cannot create limit map: " + e);
return null; return null;
@ -472,11 +472,11 @@ public class BpfCoordinator {
} }
/** Get dev BPF map. */ /** Get dev BPF map. */
@Nullable public IBpfMap<TetherDevKey, TetherDevValue> getBpfDevMap() { @Nullable public IBpfMap<S32, S32> getBpfDevMap() {
if (!isAtLeastS()) return null; if (!isAtLeastS()) return null;
try { try {
return new BpfMap<>(TETHER_DEV_MAP_PATH, return new BpfMap<>(TETHER_DEV_MAP_PATH,
TetherDevKey.class, TetherDevValue.class); S32.class, S32.class);
} catch (ErrnoException e) { } catch (ErrnoException e) {
Log.e(TAG, "Cannot create dev map: " + e); Log.e(TAG, "Cannot create dev map: " + e);
return null; return null;
@ -501,6 +501,12 @@ public class BpfCoordinator {
lastMaxSessionCount); lastMaxSessionCount);
} }
/** Send a BpfCoordinatorShimInitError event. */
public void sendBpfCoordinatorShimInitError() {
ConnectivityStatsLog.write(ConnectivityStatsLog.CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED,
ConnectivityStatsLog.CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_BPF_COORDINATOR_SHIM_INIT_ERROR);
}
/** /**
* @see DeviceConfigUtils#isTetheringFeatureEnabled * @see DeviceConfigUtils#isTetheringFeatureEnabled
*/ */
@ -542,6 +548,7 @@ public class BpfCoordinator {
mBpfCoordinatorShim = BpfCoordinatorShim.getBpfCoordinatorShim(deps); mBpfCoordinatorShim = BpfCoordinatorShim.getBpfCoordinatorShim(deps);
if (!mBpfCoordinatorShim.isInitialized()) { if (!mBpfCoordinatorShim.isInitialized()) {
mLog.e("Bpf shim not initialized"); mLog.e("Bpf shim not initialized");
mDeps.sendBpfCoordinatorShimInitError();
} }
// BPF IPv4 forwarding only supports on S+. // BPF IPv4 forwarding only supports on S+.
@ -790,7 +797,7 @@ public class BpfCoordinator {
*/ */
private void updateAllIpv6Rules(@NonNull final IpServer ipServer, private void updateAllIpv6Rules(@NonNull final IpServer ipServer,
final InterfaceParams interfaceParams, int newUpstreamIfindex, final InterfaceParams interfaceParams, int newUpstreamIfindex,
@NonNull final Set<IpPrefix> newUpstreamPrefixes) { @NonNull final Set<IpPrefix> newUpstreamPrefixes, int pmtu) {
if (!isUsingBpf()) return; if (!isUsingBpf()) return;
// Remove IPv6 downstream rules. Remove the old ones before adding the new rules, otherwise // Remove IPv6 downstream rules. Remove the old ones before adding the new rules, otherwise
@ -816,7 +823,7 @@ public class BpfCoordinator {
for (final IpPrefix ipPrefix : newUpstreamPrefixes) { for (final IpPrefix ipPrefix : newUpstreamPrefixes) {
addIpv6UpstreamRule(ipServer, new Ipv6UpstreamRule( addIpv6UpstreamRule(ipServer, new Ipv6UpstreamRule(
newUpstreamIfindex, interfaceParams.index, ipPrefix, newUpstreamIfindex, interfaceParams.index, ipPrefix,
interfaceParams.macAddr, NULL_MAC_ADDRESS, NULL_MAC_ADDRESS)); interfaceParams.macAddr, NULL_MAC_ADDRESS, NULL_MAC_ADDRESS, pmtu));
} }
} }
@ -958,7 +965,7 @@ public class BpfCoordinator {
* Note that this can be only called on handler thread. * Note that this can be only called on handler thread.
*/ */
public void updateIpv6UpstreamInterface(@NonNull final IpServer ipServer, int upstreamIfindex, public void updateIpv6UpstreamInterface(@NonNull final IpServer ipServer, int upstreamIfindex,
@NonNull Set<IpPrefix> upstreamPrefixes) { @NonNull Set<IpPrefix> upstreamPrefixes, int pmtu) {
if (!isUsingBpf()) return; if (!isUsingBpf()) return;
// If the upstream interface has changed, remove all rules and re-add them with the new // If the upstream interface has changed, remove all rules and re-add them with the new
@ -971,7 +978,7 @@ public class BpfCoordinator {
final boolean upstreamSupportsBpf = checkUpstreamSupportsBpf(upstreamIfindex); final boolean upstreamSupportsBpf = checkUpstreamSupportsBpf(upstreamIfindex);
updateAllIpv6Rules(ipServer, interfaceParams, updateAllIpv6Rules(ipServer, interfaceParams,
getInterfaceIndexForRule(upstreamIfindex, upstreamSupportsBpf), getInterfaceIndexForRule(upstreamIfindex, upstreamSupportsBpf),
upstreamPrefixes); upstreamPrefixes, pmtu);
} }
} }
@ -1059,12 +1066,12 @@ public class BpfCoordinator {
// Find the rules which are related with the given client. // Find the rules which are related with the given client.
mBpfCoordinatorShim.tetherOffloadRuleForEach(UPSTREAM, (k, v) -> { mBpfCoordinatorShim.tetherOffloadRuleForEach(UPSTREAM, (k, v) -> {
if (Arrays.equals(k.src4, clientAddr.getAddress())) { if (Objects.equals(k.src4, clientAddr)) {
deleteUpstreamRuleKeys.add(k); deleteUpstreamRuleKeys.add(k);
} }
}); });
mBpfCoordinatorShim.tetherOffloadRuleForEach(DOWNSTREAM, (k, v) -> { mBpfCoordinatorShim.tetherOffloadRuleForEach(DOWNSTREAM, (k, v) -> {
if (Arrays.equals(v.dst46, toIpv4MappedAddressBytes(clientAddr))) { if (Objects.equals(v.dst46, clientAddr)) {
deleteDownstreamRuleKeys.add(k); deleteDownstreamRuleKeys.add(k);
upstreamIndiceSet.add((int) k.iif); upstreamIndiceSet.add((int) k.iif);
} }
@ -1370,7 +1377,7 @@ public class BpfCoordinator {
} }
} }
private void dumpBpfStats(@NonNull IndentingPrintWriter pw) { private void dumpBpfStats(@NonNull IndentingPrintWriter pw) {
try (IBpfMap<TetherStatsKey, TetherStatsValue> map = mDeps.getBpfStatsMap()) { try (IBpfMap<S32, TetherStatsValue> map = mDeps.getBpfStatsMap()) {
if (map == null) { if (map == null) {
pw.println("No BPF stats map"); pw.println("No BPF stats map");
return; return;
@ -1439,9 +1446,10 @@ public class BpfCoordinator {
} }
private String ipv6UpstreamRuleToString(TetherUpstream6Key key, Tether6Value value) { private String ipv6UpstreamRuleToString(TetherUpstream6Key key, Tether6Value value) {
return String.format("%d(%s) [%s] [%s] -> %d(%s) %04x [%s] [%s]", return String.format("%d(%s) [%s] [%s] -> %d(%s) %04x [%s] [%s] %d",
key.iif, getIfName(key.iif), key.dstMac, bytesToPrefix(key.src64), value.oif, key.iif, getIfName(key.iif), key.dstMac, bytesToPrefix(key.src64), value.oif,
getIfName(value.oif), value.ethProto, value.ethSrcMac, value.ethDstMac); getIfName(value.oif), value.ethProto, value.ethSrcMac, value.ethDstMac,
value.pmtu);
} }
private void dumpIpv6UpstreamRules(IndentingPrintWriter pw) { private void dumpIpv6UpstreamRules(IndentingPrintWriter pw) {
@ -1467,9 +1475,9 @@ public class BpfCoordinator {
} catch (UnknownHostException impossible) { } catch (UnknownHostException impossible) {
throw new AssertionError("IP address array not valid IPv6 address!"); throw new AssertionError("IP address array not valid IPv6 address!");
} }
return String.format("%d(%s) [%s] %s -> %d(%s) %04x [%s] [%s]", return String.format("%d(%s) [%s] %s -> %d(%s) %04x [%s] [%s] %d",
key.iif, getIfName(key.iif), key.dstMac, neigh6, value.oif, getIfName(value.oif), key.iif, getIfName(key.iif), key.dstMac, neigh6, value.oif, getIfName(value.oif),
value.ethProto, value.ethSrcMac, value.ethDstMac); value.ethProto, value.ethSrcMac, value.ethDstMac, value.pmtu);
} }
private void dumpIpv6DownstreamRules(IndentingPrintWriter pw) { private void dumpIpv6DownstreamRules(IndentingPrintWriter pw) {
@ -1492,13 +1500,13 @@ public class BpfCoordinator {
// duplicate bpf map dump code. // duplicate bpf map dump code.
private void dumpBpfForwardingRulesIpv6(IndentingPrintWriter pw) { private void dumpBpfForwardingRulesIpv6(IndentingPrintWriter pw) {
pw.println("IPv6 Upstream: iif(iface) [inDstMac] [sourcePrefix] -> oif(iface) etherType " pw.println("IPv6 Upstream: iif(iface) [inDstMac] [sourcePrefix] -> oif(iface) etherType "
+ "[outSrcMac] [outDstMac]"); + "[outSrcMac] [outDstMac] pmtu");
pw.increaseIndent(); pw.increaseIndent();
dumpIpv6UpstreamRules(pw); dumpIpv6UpstreamRules(pw);
pw.decreaseIndent(); pw.decreaseIndent();
pw.println("IPv6 Downstream: iif(iface) [inDstMac] neigh6 -> oif(iface) etherType " pw.println("IPv6 Downstream: iif(iface) [inDstMac] neigh6 -> oif(iface) etherType "
+ "[outSrcMac] [outDstMac]"); + "[outSrcMac] [outDstMac] pmtu");
pw.increaseIndent(); pw.increaseIndent();
dumpIpv6DownstreamRules(pw); dumpIpv6DownstreamRules(pw);
pw.decreaseIndent(); pw.decreaseIndent();
@ -1522,7 +1530,7 @@ public class BpfCoordinator {
// expected argument order. // expected argument order.
// TODO: dump downstream4 map. // TODO: dump downstream4 map.
if (CollectionUtils.contains(args, DUMPSYS_RAWMAP_ARG_STATS)) { if (CollectionUtils.contains(args, DUMPSYS_RAWMAP_ARG_STATS)) {
try (IBpfMap<TetherStatsKey, TetherStatsValue> statsMap = mDeps.getBpfStatsMap()) { try (IBpfMap<S32, TetherStatsValue> statsMap = mDeps.getBpfStatsMap()) {
BpfDump.dumpRawMap(statsMap, pw); BpfDump.dumpRawMap(statsMap, pw);
} catch (IOException e) { } catch (IOException e) {
pw.println("Error dumping stats map: " + e); pw.println("Error dumping stats map: " + e);
@ -1552,20 +1560,15 @@ public class BpfCoordinator {
Tether4Key key, Tether4Value value) { Tether4Key key, Tether4Value value) {
final String src4, public4, dst4; final String src4, public4, dst4;
final int publicPort; final int publicPort;
try { src4 = key.src4.getHostAddress();
src4 = InetAddress.getByAddress(key.src4).getHostAddress(); if (downstream) {
if (downstream) { public4 = key.dst4.getHostAddress();
public4 = InetAddress.getByAddress(key.dst4).getHostAddress(); publicPort = key.dstPort;
publicPort = key.dstPort; } else {
} else { public4 = value.src46.getHostAddress();
public4 = InetAddress.getByAddress(value.src46).getHostAddress(); publicPort = value.srcPort;
publicPort = value.srcPort;
}
dst4 = InetAddress.getByAddress(value.dst46).getHostAddress();
} catch (UnknownHostException impossible) {
throw new AssertionError("IP address array not valid IPv4 address!");
} }
dst4 = value.dst46.getHostAddress();
final String ageStr = (value.lastUsed == 0) ? "-" final String ageStr = (value.lastUsed == 0) ? "-"
: String.format("%dms", (now - value.lastUsed) / 1_000_000); : String.format("%dms", (now - value.lastUsed) / 1_000_000);
return String.format("%s [%s] %d(%s) %s:%d -> %d(%s) %s:%d -> %s:%d [%s] %d %s", return String.format("%s [%s] %d(%s) %s:%d -> %d(%s) %s:%d -> %s:%d [%s] %d %s",
@ -1636,7 +1639,7 @@ public class BpfCoordinator {
} }
private void dumpDevmap(@NonNull IndentingPrintWriter pw) { private void dumpDevmap(@NonNull IndentingPrintWriter pw) {
try (IBpfMap<TetherDevKey, TetherDevValue> map = mDeps.getBpfDevMap()) { try (IBpfMap<S32, S32> map = mDeps.getBpfDevMap()) {
if (map == null) { if (map == null) {
pw.println("No devmap support"); pw.println("No devmap support");
return; return;
@ -1651,8 +1654,8 @@ public class BpfCoordinator {
// Only get upstream interface name. Just do the best to make the index readable. // Only get upstream interface name. Just do the best to make the index readable.
// TODO: get downstream interface name because the index is either upstream or // TODO: get downstream interface name because the index is either upstream or
// downstream interface in dev map. // downstream interface in dev map.
pw.println(String.format("%d (%s) -> %d (%s)", k.ifIndex, getIfName(k.ifIndex), pw.println(String.format("%d (%s) -> %d (%s)", k.val, getIfName(k.val),
v.ifIndex, getIfName(v.ifIndex))); v.val, getIfName(v.val)));
}); });
} catch (ErrnoException | IOException e) { } catch (ErrnoException | IOException e) {
pw.println("Error dumping dev map: " + e); pw.println("Error dumping dev map: " + e);
@ -1692,7 +1695,7 @@ public class BpfCoordinator {
// |field |oif |ethDst|ethSrc|ethPro|pmtu | // |field |oif |ethDst|ethSrc|ethPro|pmtu |
// | | |mac |mac |to | | // | | |mac |mac |to | |
// +------+------+------+------+------+------+ // +------+------+------+------+------+------+
// |value |upstre|-- |-- |ETH_P_|1500 | // |value |upstre|-- |-- |ETH_P_|pmtu |
// | |am | | |IP | | // | |am | | |IP | |
// +------+------+------+------+------+------+ // +------+------+------+------+------+------+
// //
@ -1706,16 +1709,19 @@ public class BpfCoordinator {
public final MacAddress outSrcMac; public final MacAddress outSrcMac;
@NonNull @NonNull
public final MacAddress outDstMac; public final MacAddress outDstMac;
public final int pmtu;
public Ipv6UpstreamRule(int upstreamIfindex, int downstreamIfindex, public Ipv6UpstreamRule(int upstreamIfindex, int downstreamIfindex,
@NonNull IpPrefix sourcePrefix, @NonNull MacAddress inDstMac, @NonNull IpPrefix sourcePrefix, @NonNull MacAddress inDstMac,
@NonNull MacAddress outSrcMac, @NonNull MacAddress outDstMac) { @NonNull MacAddress outSrcMac, @NonNull MacAddress outDstMac,
int pmtu) {
this.upstreamIfindex = upstreamIfindex; this.upstreamIfindex = upstreamIfindex;
this.downstreamIfindex = downstreamIfindex; this.downstreamIfindex = downstreamIfindex;
this.sourcePrefix = sourcePrefix; this.sourcePrefix = sourcePrefix;
this.inDstMac = inDstMac; this.inDstMac = inDstMac;
this.outSrcMac = outSrcMac; this.outSrcMac = outSrcMac;
this.outDstMac = outDstMac; this.outDstMac = outDstMac;
this.pmtu = pmtu;
} }
/** /**
@ -1732,8 +1738,7 @@ public class BpfCoordinator {
*/ */
@NonNull @NonNull
public Tether6Value makeTether6Value() { public Tether6Value makeTether6Value() {
return new Tether6Value(upstreamIfindex, outDstMac, outSrcMac, ETH_P_IPV6, return new Tether6Value(upstreamIfindex, outDstMac, outSrcMac, ETH_P_IPV6, pmtu);
NetworkStackConstants.ETHER_MTU);
} }
@Override @Override
@ -2032,20 +2037,6 @@ public class BpfCoordinator {
return null; return null;
} }
@NonNull
@VisibleForTesting
static 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;
}
// TODO: parse CTA_PROTOINFO of conntrack event in ConntrackMonitor. For TCP, only add rules // TODO: parse CTA_PROTOINFO of conntrack event in ConntrackMonitor. For TCP, only add rules
// while TCP status is established. // while TCP status is established.
@VisibleForTesting @VisibleForTesting
@ -2111,16 +2102,16 @@ public class BpfCoordinator {
private Tether4Key makeTetherUpstream4Key( private Tether4Key makeTetherUpstream4Key(
@NonNull ConntrackEvent e, @NonNull ClientInfo c) { @NonNull ConntrackEvent e, @NonNull ClientInfo c) {
return new Tether4Key(c.downstreamIfindex, c.downstreamMac, return new Tether4Key(c.downstreamIfindex, c.downstreamMac,
e.tupleOrig.protoNum, e.tupleOrig.srcIp.getAddress(), e.tupleOrig.protoNum, e.tupleOrig.srcIp, e.tupleOrig.dstIp,
e.tupleOrig.dstIp.getAddress(), e.tupleOrig.srcPort, e.tupleOrig.dstPort); e.tupleOrig.srcPort, e.tupleOrig.dstPort);
} }
@NonNull @NonNull
private Tether4Key makeTetherDownstream4Key( private Tether4Key makeTetherDownstream4Key(
@NonNull ConntrackEvent e, @NonNull ClientInfo c, int upstreamIndex) { @NonNull ConntrackEvent e, @NonNull ClientInfo c, int upstreamIndex) {
return new Tether4Key(upstreamIndex, NULL_MAC_ADDRESS /* dstMac (rawip) */, return new Tether4Key(upstreamIndex, NULL_MAC_ADDRESS /* dstMac (rawip) */,
e.tupleReply.protoNum, e.tupleReply.srcIp.getAddress(), e.tupleReply.protoNum, e.tupleReply.srcIp, e.tupleReply.dstIp,
e.tupleReply.dstIp.getAddress(), e.tupleReply.srcPort, e.tupleReply.dstPort); e.tupleReply.srcPort, e.tupleReply.dstPort);
} }
@NonNull @NonNull
@ -2129,8 +2120,7 @@ public class BpfCoordinator {
return new Tether4Value(upstreamInfo.ifIndex, return new Tether4Value(upstreamInfo.ifIndex,
NULL_MAC_ADDRESS /* ethDstMac (rawip) */, NULL_MAC_ADDRESS /* ethDstMac (rawip) */,
NULL_MAC_ADDRESS /* ethSrcMac (rawip) */, ETH_P_IP, NULL_MAC_ADDRESS /* ethSrcMac (rawip) */, ETH_P_IP,
upstreamInfo.mtu, toIpv4MappedAddressBytes(e.tupleReply.dstIp), upstreamInfo.mtu, e.tupleReply.dstIp, e.tupleReply.srcIp, e.tupleReply.dstPort,
toIpv4MappedAddressBytes(e.tupleReply.srcIp), e.tupleReply.dstPort,
e.tupleReply.srcPort, 0 /* lastUsed, filled by bpf prog only */); e.tupleReply.srcPort, 0 /* lastUsed, filled by bpf prog only */);
} }
@ -2139,8 +2129,7 @@ public class BpfCoordinator {
@NonNull ClientInfo c, @NonNull UpstreamInfo upstreamInfo) { @NonNull ClientInfo c, @NonNull UpstreamInfo upstreamInfo) {
return new Tether4Value(c.downstreamIfindex, return new Tether4Value(c.downstreamIfindex,
c.clientMac, c.downstreamMac, ETH_P_IP, upstreamInfo.mtu, c.clientMac, c.downstreamMac, ETH_P_IP, upstreamInfo.mtu,
toIpv4MappedAddressBytes(e.tupleOrig.dstIp), e.tupleOrig.dstIp, e.tupleOrig.srcIp,
toIpv4MappedAddressBytes(e.tupleOrig.srcIp),
e.tupleOrig.dstPort, e.tupleOrig.srcPort, e.tupleOrig.dstPort, e.tupleOrig.srcPort,
0 /* lastUsed, filled by bpf prog only */); 0 /* lastUsed, filled by bpf prog only */);
} }
@ -2465,17 +2454,6 @@ public class BpfCoordinator {
return Math.max(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS, configInterval); 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 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 // Update CTA_TUPLE_ORIG timeout for a given conntrack entry. Note that there will also be
// coming a conntrack event to notify updated timeout. // coming a conntrack event to notify updated timeout.
private void updateConntrackTimeout(byte proto, Inet4Address src4, short srcPort, private void updateConntrackTimeout(byte proto, Inet4Address src4, short srcPort,
@ -2532,9 +2510,8 @@ public class BpfCoordinator {
// both directions for TCP. // both directions for TCP.
mBpfCoordinatorShim.tetherOffloadRuleForEach(UPSTREAM, (k, v) -> { mBpfCoordinatorShim.tetherOffloadRuleForEach(UPSTREAM, (k, v) -> {
if ((now - v.lastUsed) / 1_000_000 < CONNTRACK_TIMEOUT_UPDATE_INTERVAL_MS) { if ((now - v.lastUsed) / 1_000_000 < CONNTRACK_TIMEOUT_UPDATE_INTERVAL_MS) {
updateConntrackTimeout((byte) k.l4proto, updateConntrackTimeout((byte) k.l4proto, k.src4, (short) k.srcPort, k.dst4,
parseIPv4Address(k.src4), (short) k.srcPort, (short) k.dstPort);
parseIPv4Address(k.dst4), (short) k.dstPort);
} }
}); });
@ -2543,9 +2520,8 @@ public class BpfCoordinator {
// which is opposite direction for downstream map value. // which is opposite direction for downstream map value.
mBpfCoordinatorShim.tetherOffloadRuleForEach(DOWNSTREAM, (k, v) -> { mBpfCoordinatorShim.tetherOffloadRuleForEach(DOWNSTREAM, (k, v) -> {
if ((now - v.lastUsed) / 1_000_000 < CONNTRACK_TIMEOUT_UPDATE_INTERVAL_MS) { if ((now - v.lastUsed) / 1_000_000 < CONNTRACK_TIMEOUT_UPDATE_INTERVAL_MS) {
updateConntrackTimeout((byte) k.l4proto, updateConntrackTimeout((byte) k.l4proto, (Inet4Address) v.dst46, (short) v.dstPort,
parseIPv4Address(v.dst46), (short) v.dstPort, (Inet4Address) v.src46, (short) v.srcPort);
parseIPv4Address(v.src46), (short) v.srcPort);
} }
}); });
} }

View file

@ -30,7 +30,7 @@ import java.io.IOException;
/** /**
* The classes and the methods for BPF utilization. * The classes and the methods for BPF utilization.
* *
* {@hide} * @hide
*/ */
public class BpfUtils { public class BpfUtils {
static { static {

View file

@ -32,6 +32,7 @@ import static android.net.TetheringManager.TETHERING_WIFI;
import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN; import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN;
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR; import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
import static android.net.TetheringManager.TETHER_ERROR_PROVISIONING_FAILED; import static android.net.TetheringManager.TETHER_ERROR_PROVISIONING_FAILED;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE; import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;
import static com.android.networkstack.apishim.ConstantsShim.ACTION_TETHER_UNSUPPORTED_CARRIER_UI; import static com.android.networkstack.apishim.ConstantsShim.ACTION_TETHER_UNSUPPORTED_CARRIER_UI;
@ -448,7 +449,8 @@ public class EntitlementManager {
return TETHERING_PROVISIONING_CARRIER_UNSUPPORT; return TETHERING_PROVISIONING_CARRIER_UNSUPPORT;
} }
if (!config.isCarrierConfigAffirmsEntitlementCheckRequired) { if (!config.isCarrierConfigAffirmsEntitlementCheckRequired
|| INVALID_SUBSCRIPTION_ID == config.activeDataSubId) {
return TETHERING_PROVISIONING_NOT_REQUIRED; return TETHERING_PROVISIONING_NOT_REQUIRED;
} }
return (config.provisioningApp.length == 2) return (config.provisioningApp.length == 2)

View file

@ -1,35 +0,0 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.networkstack.tethering;
import com.android.net.module.util.Struct;
import com.android.net.module.util.Struct.Field;
import com.android.net.module.util.Struct.Type;
/** The value of BpfMap which is used for tethering per-interface limit. */
public class TetherLimitValue extends Struct {
// Use the signed long variable to store the int64 limit on limit BPF map.
// S64 is enough for each interface limit even at 5Gbps for ~468 years.
// 2^63 / (5 * 1000 * 1000 * 1000) * 8 / 86400 / 365 = 468.
// Note that QUOTA_UNLIMITED (-1) indicates there is no limit.
@Field(order = 0, type = Type.S64)
public final long limit;
public TetherLimitValue(final long limit) {
this.limit = limit;
}
}

View file

@ -138,9 +138,8 @@ public abstract class TetheringDependencies {
IBinder binder; IBinder binder;
if (!SdkLevel.isAtLeastS()) { if (!SdkLevel.isAtLeastS()) {
final ConnectivityManager cm = context.getSystemService(ConnectivityManager.class); final ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
binder = binder = new RoutingCoordinatorService(getINetd(context, log), cm::getAllNetworks,
new RoutingCoordinatorService( context, false /* bluetoothTetheringUseRandomAddress */);
getINetd(context, log), cm::getAllNetworks, context);
} else { } else {
binder = ConnectivityInternalApiUtil.getRoutingCoordinator(context); binder = ConnectivityInternalApiUtil.getRoutingCoordinator(context);
} }

View file

@ -61,15 +61,8 @@ public class TetheringFeatureFlags {
public static final String TETHER_ACTIVE_SESSIONS_METRICS = "tether_active_sessions_metrics"; public static final String TETHER_ACTIVE_SESSIONS_METRICS = "tether_active_sessions_metrics";
/** /**
* A feature flag to control whether the tethering local network agent should be enabled. * A kill switch to control whether the TETHERING_AND_P2P_GO_LOCAL_AGENT is enabled.
* Disabled by default.
*/ */
public static final String TETHERING_LOCAL_NETWORK_AGENT = "tethering_local_network_agent"; public static final String TETHERING_AND_P2P_GO_LOCAL_AGENT =
"tethering_and_p2p_go_local_agent";
/**
* A feature flag to control whether the Wifi P2P Group Owner local network agent
* should be enabled. Disabled by default. This depends on TETHERING_LOCAL_AGENT
* and will not be enabled if that flag is off.
*/
public static final String WIFIP2PGO_LOCAL_NETWORK_AGENT = "wifip2pgo_local_network_agent";
} }

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