Android 16.0.0 Release 3 (BP3A.250905.014)
-----BEGIN PGP SIGNATURE-----
iF0EABECAB0WIQRDQNE1cO+UXoOBCWTorT+BmrEOeAUCaRO/HAAKCRDorT+BmrEO
eOs9AJ9Yzz2HpDR3pyRIXhvl4k7bNABGvgCeMg5sU16s0CkFIDbZmOsSo4fswZQ=
=1o5/
-----END PGP SIGNATURE-----
gpgsig -----BEGIN SSH SIGNATURE-----
U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgPpdpjxPACTIhnlvYz0GM4BR7FJ
+rYv3jMbfxNKD3JvcAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5
AAAAQIRFF5B6T8EGhzDN+1dhvomEkctFjdVr5DZnhgnEIvcCEuzO36RzY3DBG9AIL+EejJ
Z1zz7uAapzWUsyFpbYAQM=
-----END SSH SIGNATURE-----
Merge tag 'android-16.0.0_r3' into staging/lineage-23.0_merge-android-16.0.0_r3
Android 16.0.0 Release 3 (BP3A.250905.014)
# -----BEGIN PGP SIGNATURE-----
#
# iF0EABECAB0WIQRDQNE1cO+UXoOBCWTorT+BmrEOeAUCaRO/HAAKCRDorT+BmrEO
# eOs9AJ9Yzz2HpDR3pyRIXhvl4k7bNABGvgCeMg5sU16s0CkFIDbZmOsSo4fswZQ=
# =1o5/
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed Nov 12 00:56:28 2025 EET
# gpg: using DSA key 4340D13570EF945E83810964E8AD3F819AB10E78
# gpg: Good signature from "The Android Open Source Project <initial-contribution@android.com>" [ultimate]
# By Patrick Rohr (91) and others
# Via Android (Google) Code Review (233) and others
* tag 'android-16.0.0_r3': (377 commits)
Fix netbpfload version info.
NetBpfLoad: add self-check for bpfGetNext{Prog,Map}Id()
Add NetworkTemplate get/set transport type methods
Pass EthernetPort to EthernetNetworkFactory#updateInterfaceLinkState
Pass EthernetPort to updateInterfaceState
Remove spurious VisibleForTesting and change visibility to public
Pass EthernetPort to EthernetNetworkFactory#removeInterface
Pass EthernetPort to removeInterface
Pass EthernetPort to stopTrackingInterface
Add getEthernetPorts and use it in getAllInterfaces
Rename getClientModeInterfaces to getClientModeInterfacesSorted
Rename getAvailableInterfaces to getInterfacesSorted
Pass EthernetPort into NetworkInterfaceState
Pass EthernetPort into EthernetNetworkFactory#addInterface
Use multicast socket for group membership
Test refactoring of DefaultNetworkRematchMetrics
Fix SatisfiedTime initialization
DHCPv6 addr reg: parse IA Address option.
Pass EthernetPort to addInterface
Change tethering interface to EthernetPort
...
Conflicts:
bpf/progs/netd.c
service/src/com/android/server/ConnectivityService.java
staticlibs/testutils/host/python/apf_test_base.py
tests/cts/multidevices/apfv4_test.py
tests/cts/multidevices/apfv6_test.py
tests/cts/multidevices/run_tests.py
tests/unit/java/com/android/server/connectivityservice/CSNetworkAgentTest.kt
Change-Id: Ifedf92aee90cbcc55ef8f9652de8b5faff1c30d9
This commit is contained in:
commit
c7f07b6a13
345 changed files with 22092 additions and 6606 deletions
|
|
@ -1,9 +1,11 @@
|
|||
[Builtin Hooks]
|
||||
bpfmt = true
|
||||
clang_format = true
|
||||
rustfmt = true
|
||||
|
||||
[Builtin Hooks Options]
|
||||
clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp,hpp
|
||||
rustfmt = --config-path=rustfmt.toml
|
||||
|
||||
[Hook Scripts]
|
||||
checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT}
|
||||
|
|
@ -11,3 +13,8 @@ checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPL
|
|||
ktlint_hook = ${REPO_ROOT}/prebuilts/ktlint/ktlint.py --disabled-rules comment-wrapping -f ${PREUPLOAD_FILES}
|
||||
|
||||
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}
|
||||
|
||||
# go/alint for details
|
||||
alint_hook = ${REPO_ROOT}/vendor/google/tools/alint
|
||||
|
|
|
|||
17
TEST_MAPPING
17
TEST_MAPPING
|
|
@ -435,6 +435,23 @@
|
|||
"name": "CtsNetTestCasesUpdateStatsPermission"
|
||||
}
|
||||
],
|
||||
"tv-presubmit": [
|
||||
{
|
||||
"name": "CtsNetTestCases"
|
||||
},
|
||||
{
|
||||
"name": "CtsNativeNetTestCases"
|
||||
},
|
||||
{
|
||||
"name": "CtsNativeNetDnsTestCases"
|
||||
},
|
||||
{
|
||||
"name": "CtsNetTestCasesInternetPermission"
|
||||
},
|
||||
{
|
||||
"name": "CtsNetTestCasesUpdateStatsPermission"
|
||||
}
|
||||
],
|
||||
"imports": [
|
||||
{
|
||||
"path": "frameworks/base/core/java/android/net"
|
||||
|
|
|
|||
|
|
@ -116,6 +116,10 @@ apex {
|
|||
compat_configs: [
|
||||
"connectivity-platform-compat-config",
|
||||
],
|
||||
licenses: [
|
||||
"Android-Apache-2.0",
|
||||
"opensourcerequest",
|
||||
],
|
||||
}
|
||||
|
||||
apex_key {
|
||||
|
|
@ -218,3 +222,21 @@ systemserverclasspath_fragment {
|
|||
standalone_contents: ["service-connectivity"],
|
||||
apex_available: ["com.android.tethering"],
|
||||
}
|
||||
|
||||
// Extract the version number of the module from the manifest.json, and zip it as a raw resource for
|
||||
// usage in android_test "resource_zips" build rules.
|
||||
// The manifest.json is updated with new module versions in release branches when versions are cut.
|
||||
java_genrule {
|
||||
name: "connectivity-module-version-as-resource-zip",
|
||||
srcs: [
|
||||
"manifest.json",
|
||||
],
|
||||
out: ["connectivity-module-version-as-resource.zip"],
|
||||
tools: ["soong_zip"],
|
||||
|
||||
cmd: "mkdir -p $(genDir)/res/raw && " +
|
||||
// The manifest has a line with '"version": 361099999'. Grep for the line, then for the int.
|
||||
"grep -Eo '\"version\": *[0-9]+' $(in) | grep -Eo '[0-9]+' > " +
|
||||
"$(genDir)/res/raw/target_module_version && " +
|
||||
"$(location soong_zip) -o $(out) -C $(genDir)/res -D $(genDir)/res",
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ package com.android.networkstack.tethering.apishim.api31;
|
|||
import static android.net.netstats.provider.NetworkStatsProvider.QUOTA_UNLIMITED;
|
||||
|
||||
import static com.android.net.module.util.NetworkStackConstants.RFC7421_PREFIX_LENGTH;
|
||||
import static com.android.networkstack.tethering.TetheringConfiguration.TETHER_ACTIVE_SESSIONS_METRICS;
|
||||
import static com.android.networkstack.tethering.TetheringFeatureFlags.TETHER_ACTIVE_SESSIONS_METRICS;
|
||||
|
||||
import android.system.ErrnoException;
|
||||
import android.system.Os;
|
||||
|
|
|
|||
|
|
@ -41,8 +41,9 @@ import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
|
|||
|
||||
import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH;
|
||||
import static com.android.net.module.util.NetworkStackConstants.RFC7421_PREFIX_LENGTH;
|
||||
import static com.android.networkstack.tethering.TetheringConfiguration.TETHERING_LOCAL_NETWORK_AGENT;
|
||||
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.WIFIP2PGO_LOCAL_NETWORK_AGENT;
|
||||
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.TetheringUtils.getTransportTypeForTetherableType;
|
||||
|
|
@ -334,7 +335,8 @@ public class IpServer extends StateMachineShim {
|
|||
private final Handler mHandler;
|
||||
private final Context mContext;
|
||||
|
||||
private final boolean mSupportLocalAgent;
|
||||
private final boolean mSupportTetheringLocalAgent;
|
||||
private final boolean mSupportWifiP2pGroupOwnerLocalAgent;
|
||||
|
||||
// This will be null if the TetheredState is not entered or feature not supported.
|
||||
// This will be only accessed from the IpServer handler thread.
|
||||
|
|
@ -380,8 +382,10 @@ public class IpServer extends StateMachineShim {
|
|||
mServingMode = STATE_AVAILABLE;
|
||||
|
||||
// Tethering network agent is supported on V+, and will be rolled out gradually.
|
||||
mSupportLocalAgent = SdkLevel.isAtLeastV()
|
||||
mSupportTetheringLocalAgent = SdkLevel.isAtLeastV()
|
||||
&& mDeps.isFeatureEnabled(mContext, TETHERING_LOCAL_NETWORK_AGENT);
|
||||
mSupportWifiP2pGroupOwnerLocalAgent = mSupportTetheringLocalAgent
|
||||
&& mDeps.isFeatureEnabled(mContext, WIFIP2PGO_LOCAL_NETWORK_AGENT);
|
||||
|
||||
mInitialState = new InitialState();
|
||||
mLocalHotspotState = new LocalHotspotState();
|
||||
|
|
@ -1162,9 +1166,8 @@ public class IpServer extends StateMachineShim {
|
|||
|
||||
@SuppressLint("NewApi")
|
||||
private void startServingInterface() {
|
||||
// TODO: Enable Network Agent for Wifi P2P Group Owner mode when Network Agent
|
||||
// for Group Client mode is supported.
|
||||
if (mSupportLocalAgent && getScope() == CONNECTIVITY_SCOPE_GLOBAL) {
|
||||
if (mSupportTetheringLocalAgent && (mSupportWifiP2pGroupOwnerLocalAgent
|
||||
|| getScope() != CONNECTIVITY_SCOPE_LOCAL)) {
|
||||
try {
|
||||
mTetheringAgent = mDeps.makeNetworkAgent(mContext, Looper.myLooper(), TAG,
|
||||
mInterfaceType, mLinkProperties);
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ import static com.android.net.module.util.ip.ConntrackMonitor.ConntrackEvent;
|
|||
import static com.android.networkstack.tethering.BpfUtils.DOWNSTREAM;
|
||||
import static com.android.networkstack.tethering.BpfUtils.UPSTREAM;
|
||||
import static com.android.networkstack.tethering.TetheringConfiguration.DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS;
|
||||
import static com.android.networkstack.tethering.TetheringConfiguration.TETHER_ACTIVE_SESSIONS_METRICS;
|
||||
import static com.android.networkstack.tethering.TetheringFeatureFlags.TETHER_ACTIVE_SESSIONS_METRICS;
|
||||
import static com.android.networkstack.tethering.UpstreamNetworkState.isVcnInterface;
|
||||
import static com.android.networkstack.tethering.util.TetheringUtils.getTetheringJniLibraryName;
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
package com.android.networkstack.tethering;
|
||||
|
||||
import static com.android.net.module.util.netlink.NetlinkUtils.SOCKET_RECV_BUFSIZE;
|
||||
import static com.android.net.module.util.netlink.NetlinkUtils.SOCKET_DUMP_RECV_BUFSIZE;
|
||||
import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_DUMP;
|
||||
import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_REQUEST;
|
||||
|
||||
|
|
@ -200,7 +200,7 @@ public class OffloadHardwareInterface {
|
|||
final FileDescriptor fd;
|
||||
try {
|
||||
fd = NetlinkUtils.netlinkSocketForProto(OsConstants.NETLINK_NETFILTER,
|
||||
SOCKET_RECV_BUFSIZE);
|
||||
SOCKET_DUMP_RECV_BUFSIZE);
|
||||
} catch (ErrnoException e) {
|
||||
mLog.e("Unable to create conntrack socket " + e);
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ import java.util.Map;
|
|||
* Note: This class is not thread-safe.
|
||||
*/
|
||||
public class RequestTracker {
|
||||
private static final String TAG = RequestTracker.class.getSimpleName();
|
||||
private static final String TAG = "TetheringRequestTracker";
|
||||
|
||||
@NonNull
|
||||
private final boolean mUseFuzzyMatching;
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ import static android.net.TetheringManager.TETHER_ERROR_UNAVAIL_IFACE;
|
|||
import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_IFACE;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_REQUEST;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_TYPE;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_UNSUPPORTED;
|
||||
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_FAILED;
|
||||
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED;
|
||||
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED;
|
||||
|
|
@ -76,10 +77,6 @@ import static com.android.networkstack.tethering.TetheringConfiguration.TETHER_F
|
|||
import static com.android.networkstack.tethering.TetheringNotificationUpdater.DOWNSTREAM_NONE;
|
||||
import static com.android.networkstack.tethering.UpstreamNetworkMonitor.isCellular;
|
||||
import static com.android.networkstack.tethering.metrics.TetheringStatsLog.CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED;
|
||||
import static com.android.networkstack.tethering.metrics.TetheringStatsLog.CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_LEGACY_TETHER_WITH_TYPE_WIFI;
|
||||
import static com.android.networkstack.tethering.metrics.TetheringStatsLog.CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_LEGACY_TETHER_WITH_TYPE_WIFI_P2P;
|
||||
import static com.android.networkstack.tethering.metrics.TetheringStatsLog.CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_LEGACY_TETHER_WITH_TYPE_WIFI_P2P_SUCCESS;
|
||||
import static com.android.networkstack.tethering.metrics.TetheringStatsLog.CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_LEGACY_TETHER_WITH_TYPE_WIFI_SUCCESS;
|
||||
import static com.android.networkstack.tethering.metrics.TetheringStatsLog.CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_TETHER_WITH_PLACEHOLDER_REQUEST;
|
||||
import static com.android.networkstack.tethering.util.TetheringMessageBase.BASE_MAIN_SM;
|
||||
import static com.android.networkstack.tethering.util.TetheringUtils.createImplicitLocalOnlyTetheringRequest;
|
||||
|
|
@ -153,11 +150,11 @@ import com.android.internal.util.StateMachine;
|
|||
import com.android.modules.utils.build.SdkLevel;
|
||||
import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
|
||||
import com.android.net.module.util.CollectionUtils;
|
||||
import com.android.net.module.util.FrameworkConnectivityStatsLog;
|
||||
import com.android.net.module.util.HandlerUtils;
|
||||
import com.android.net.module.util.NetdUtils;
|
||||
import com.android.net.module.util.RoutingCoordinatorManager;
|
||||
import com.android.net.module.util.SharedLog;
|
||||
import com.android.net.module.util.TerribleErrorLog;
|
||||
import com.android.networkstack.apishim.common.BluetoothPanShim;
|
||||
import com.android.networkstack.apishim.common.BluetoothPanShim.TetheredInterfaceCallbackShim;
|
||||
import com.android.networkstack.apishim.common.BluetoothPanShim.TetheredInterfaceRequestShim;
|
||||
|
|
@ -633,33 +630,40 @@ public class Tethering {
|
|||
if (type == TETHERING_BLUETOOTH && SdkLevel.isAtLeastT()) return;
|
||||
|
||||
// Cannot happen: on S+, tetherableWigigRegexps is always empty.
|
||||
if (type == TETHERING_WIGIG && SdkLevel.isAtLeastS()) return;
|
||||
|
||||
// After V, disallow this legacy codepath from starting tethering of any type:
|
||||
// everything must call ensureIpServerStarted directly.
|
||||
//
|
||||
// Don't touch the teardown path for now. It's more complicated because:
|
||||
// - ensureIpServerStarted and ensureIpServerStopped act on different
|
||||
// tethering types.
|
||||
// - Depending on the type, ensureIpServerStopped is either called twice (once
|
||||
// on interface down and once on interface removed) or just once (on
|
||||
// interface removed).
|
||||
//
|
||||
// Note that this only affects WIFI and WIFI_P2P. The other types are either
|
||||
// ignored above, or ignored by ensureIpServerStarted. Note that even for WIFI
|
||||
// and WIFI_P2P, this code should not ever run in normal use, because the
|
||||
// hotspot and p2p code do not call tether(). It's possible that this could
|
||||
// happen in the field due to unforeseen OEM modifications. If it does happen,
|
||||
// a terrible error is logged in tether().
|
||||
// TODO: fix the teardown path to stop depending on interface state notifications.
|
||||
// These are not necessary since most/all link layers have their own teardown
|
||||
// notifications, and can race with those notifications.
|
||||
if (enabled && SdkLevel.isAtLeastB()) {
|
||||
if (type == TETHERING_WIGIG
|
||||
&& (SdkLevel.isAtLeastS() || !hasSystemFeature(PackageManager.FEATURE_WIFI))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// After V, don't allow this legacy codepath to create IpServers for any tethering type:
|
||||
// everything must call ensureIpServerStarted directly. Also, on any release, don't create
|
||||
// IpServers for WIFI or WIFI_P2P. These types always use the enableIpServing path.
|
||||
//
|
||||
// Don't touch the teardown path for now. It's more complicated because:
|
||||
// - ensureIpServerStarted and ensureIpServerStopped act on different
|
||||
// tethering types, and ensureIpServerStopped doesn't look at the type at all.
|
||||
// - Depending on the type, ensureIpServerStopped is either called twice (once
|
||||
// on interface down and once on interface removed) or just once (on
|
||||
// interface removed). It's not clear whether it's possible to remove one of
|
||||
// these two calls without causing breakage in the field - for example, it's
|
||||
// possible that if the code did not call ensureIpServerStopped on wifi, then
|
||||
// when wifi tethering is disabled and wifi goes into client mode, tethering
|
||||
// has not brought down the IpServer because the WIFI_AP_STATE_CHANGED_ACTION
|
||||
// was delayed.
|
||||
//
|
||||
// TODO: fix the teardown path to stop depending on interface state notifications.
|
||||
// These are not necessary since most/all link layers have their own teardown
|
||||
// notifications, and can race with those notifications.
|
||||
if (enabled && SdkLevel.isAtLeastB()) return;
|
||||
|
||||
if (enabled && (type == TETHERING_WIFI || type == TETHERING_WIFI_P2P)) return;
|
||||
|
||||
// In this method, INVALID includes ETHERNET and VIRTUAL, because ifaceNameToType never
|
||||
// returns these. The legacy codepath does not support these.
|
||||
if (enabled && type == TETHERING_INVALID) return;
|
||||
|
||||
if (enabled) {
|
||||
ensureIpServerStartedForInterface(iface);
|
||||
ensureIpServerStarted(iface, type, false /* isNcm */);
|
||||
} else {
|
||||
ensureIpServerStopped(iface);
|
||||
}
|
||||
|
|
@ -719,6 +723,7 @@ public class Tethering {
|
|||
void startTethering(final TetheringRequest request, final String callerPkg,
|
||||
final IIntResultListener listener) {
|
||||
mHandler.post(() -> {
|
||||
mLog.i("startTethering: " + request);
|
||||
final int type = request.getTetheringType();
|
||||
RequestTracker.AddResult result = mRequestTracker.addPendingRequest(request);
|
||||
// If tethering is already pending with a conflicting request, stop tethering before
|
||||
|
|
@ -748,6 +753,7 @@ public class Tethering {
|
|||
|
||||
void stopTethering(int type) {
|
||||
mHandler.post(() -> {
|
||||
mLog.i("stopTethering: " + type);
|
||||
stopTetheringInternal(type);
|
||||
});
|
||||
}
|
||||
|
|
@ -757,6 +763,7 @@ public class Tethering {
|
|||
if (!isTetheringWithSoftApConfigEnabled()) return;
|
||||
final boolean hasNetworkSettings = hasCallingPermission(NETWORK_SETTINGS);
|
||||
mHandler.post(() -> {
|
||||
mLog.i("stopTetheringRequest: " + request);
|
||||
if (mRequestTracker.findFuzzyMatchedRequest(request, !hasNetworkSettings) != null) {
|
||||
final int type = request.getTetheringType();
|
||||
stopTetheringInternal(type);
|
||||
|
|
@ -1149,43 +1156,20 @@ public class Tethering {
|
|||
if (type == TETHERING_INVALID) {
|
||||
Log.e(TAG, "Ignoring call to legacy tether for unknown iface " + iface);
|
||||
sendTetherResult(listener, TETHER_ERROR_UNKNOWN_IFACE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == TETHERING_WIFI || type == TETHERING_WIFI_P2P) {
|
||||
// Metrics show no usage of this legacy codepath. Stop supporing it.
|
||||
sendTetherResult(listener, TETHER_ERROR_UNSUPPORTED);
|
||||
return;
|
||||
}
|
||||
|
||||
TetheringRequest request = mRequestTracker.getNextPendingRequest(type);
|
||||
if (request == null) {
|
||||
request = createLegacyGlobalScopeTetheringRequest(type);
|
||||
}
|
||||
int result = tetherInternal(request, iface);
|
||||
switch (type) {
|
||||
case TETHERING_WIFI:
|
||||
TerribleErrorLog.logTerribleError(TetheringStatsLog::write,
|
||||
"Legacy tether API called on Wifi iface " + iface,
|
||||
CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED,
|
||||
CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_LEGACY_TETHER_WITH_TYPE_WIFI);
|
||||
if (result == TETHER_ERROR_NO_ERROR) {
|
||||
TerribleErrorLog.logTerribleError(TetheringStatsLog::write,
|
||||
"Legacy tether API succeeded on Wifi iface " + iface,
|
||||
CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED,
|
||||
CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_LEGACY_TETHER_WITH_TYPE_WIFI_SUCCESS);
|
||||
}
|
||||
break;
|
||||
case TETHERING_WIFI_P2P:
|
||||
TerribleErrorLog.logTerribleError(TetheringStatsLog::write,
|
||||
"Legacy tether API called on Wifi P2P iface " + iface,
|
||||
CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED,
|
||||
CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_LEGACY_TETHER_WITH_TYPE_WIFI_P2P);
|
||||
if (result == TETHER_ERROR_NO_ERROR) {
|
||||
TerribleErrorLog.logTerribleError(TetheringStatsLog::write,
|
||||
"Legacy tether API succeeded on Wifi P2P iface " + iface,
|
||||
CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED,
|
||||
CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_LEGACY_TETHER_WITH_TYPE_WIFI_P2P_SUCCESS);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Do nothing
|
||||
break;
|
||||
}
|
||||
sendTetherResult(listener, result);
|
||||
sendTetherResult(listener, tetherInternal(request, iface));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1195,11 +1179,12 @@ public class Tethering {
|
|||
* processInterfaceStateChanged beforehand, which is only possible for
|
||||
* - WIGIG Pre-S
|
||||
* - BLUETOOTH Pre-T
|
||||
* It was previously supported but no longer allowed for:
|
||||
* - WIFI
|
||||
* - WIFI_P2P.
|
||||
* Note that WIFI and WIFI_P2P already start tethering on their respective ifaces via
|
||||
* WIFI_(AP/P2P_STATE_CHANGED broadcasts, which makes this API redundant for those types unless
|
||||
* those broadcasts are disabled by OEM.
|
||||
* because metrics show that there is no usage of this method for these types in production.
|
||||
* These types start tethering on their respective ifaces via WIFI_(AP/P2P_STATE_CHANGED
|
||||
* broadcasts instead.
|
||||
*/
|
||||
void legacyTether(String iface, final IIntResultListener listener) {
|
||||
mHandler.post(() -> handleLegacyTether(iface, listener));
|
||||
|
|
@ -1223,8 +1208,8 @@ public class Tethering {
|
|||
// processed, this will be a no-op and it will not return an error.
|
||||
tetherState.ipServer.enable(request);
|
||||
if (request.getRequestType() == REQUEST_TYPE_PLACEHOLDER) {
|
||||
TerribleErrorLog.logTerribleError(TetheringStatsLog::write,
|
||||
"Started tethering with placeholder request: " + request,
|
||||
Log.i(TAG, "Started tethering with placeholder request: " + request);
|
||||
TetheringStatsLog.write(
|
||||
CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED,
|
||||
CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_TETHER_WITH_PLACEHOLDER_REQUEST);
|
||||
}
|
||||
|
|
@ -1283,13 +1268,6 @@ public class Tethering {
|
|||
return mEntitlementMgr.isTetherProvisioningRequired(cfg);
|
||||
}
|
||||
|
||||
private int getServedUsbType(boolean forNcmFunction) {
|
||||
// TETHERING_NCM is only used if the device does not use NCM for regular USB tethering.
|
||||
if (forNcmFunction && !mConfig.isUsingNcm()) return TETHERING_NCM;
|
||||
|
||||
return TETHERING_USB;
|
||||
}
|
||||
|
||||
// TODO: Figure out how to update for local hotspot mode interfaces.
|
||||
private void notifyTetherStatesChanged() {
|
||||
if (!isTetheringSupported()) return;
|
||||
|
|
@ -1709,7 +1687,7 @@ public class Tethering {
|
|||
}
|
||||
|
||||
private void enableIpServing(@NonNull TetheringRequest request, String ifname, boolean isNcm) {
|
||||
ensureIpServerStartedForType(ifname, request.getTetheringType(), isNcm);
|
||||
ensureIpServerStarted(ifname, request.getTetheringType(), isNcm);
|
||||
if (tetherInternal(request, ifname) != TETHER_ERROR_NO_ERROR) {
|
||||
Log.e(TAG, "unable start tethering on iface " + ifname);
|
||||
}
|
||||
|
|
@ -1758,6 +1736,12 @@ public class Tethering {
|
|||
// After T, tethering always trust the iface pass by state change intent. This allow
|
||||
// tethering to deprecate tetherable p2p regexs after T.
|
||||
final int type = SdkLevel.isAtLeastT() ? TETHERING_WIFI_P2P : ifaceNameToType(ifname);
|
||||
if (type != TETHERING_WIFI_P2P) {
|
||||
FrameworkConnectivityStatsLog.write(
|
||||
FrameworkConnectivityStatsLog.CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED,
|
||||
FrameworkConnectivityStatsLog.CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_TETHER_WIFIP2P_TYPE_MISMATCH);
|
||||
}
|
||||
|
||||
if (!checkTetherableType(type)) {
|
||||
mLog.e(ifname + " is not a tetherable iface, ignoring");
|
||||
return;
|
||||
|
|
@ -1808,6 +1792,11 @@ public class Tethering {
|
|||
mLog.e("Cannot enable IP serving in unknown WiFi mode: " + wifiIpMode);
|
||||
return;
|
||||
}
|
||||
if (type != TETHERING_WIFI) {
|
||||
FrameworkConnectivityStatsLog.write(
|
||||
FrameworkConnectivityStatsLog.CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED,
|
||||
FrameworkConnectivityStatsLog.CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_TETHER_WIFI_TYPE_MISMATCH);
|
||||
}
|
||||
|
||||
// After T, tethering always trust the iface pass by state change intent. This allow
|
||||
// tethering to deprecate tetherable wifi regexs after T.
|
||||
|
|
@ -1830,14 +1819,7 @@ public class Tethering {
|
|||
// - allows requesting either tethering or local hotspot serving states
|
||||
// - only tethers the first matching interface in listInterfaces()
|
||||
// order of a given type
|
||||
private void enableUsbIpServing(boolean forNcmFunction) {
|
||||
// Note: TetheringConfiguration#isUsingNcm can change between the call to
|
||||
// startTethering(TETHERING_USB) and the ACTION_USB_STATE broadcast. If the USB tethering
|
||||
// function changes from NCM to RNDIS, this can lead to Tethering starting NCM tethering
|
||||
// as local-only. But if this happens, the SettingsObserver will call stopTetheringInternal
|
||||
// for both TETHERING_USB and TETHERING_NCM, so the local-only NCM interface will be
|
||||
// stopped immediately.
|
||||
final int tetheringType = getServedUsbType(forNcmFunction);
|
||||
private void enableUsbIpServing(boolean isNcm) {
|
||||
String[] ifaces = null;
|
||||
try {
|
||||
ifaces = mNetd.interfaceGetList();
|
||||
|
|
@ -1846,17 +1828,24 @@ public class Tethering {
|
|||
return;
|
||||
}
|
||||
|
||||
// Note: TetheringConfiguration#isUsingNcm can change between the call to
|
||||
// startTethering(TETHERING_USB) and the ACTION_USB_STATE broadcast. If the USB tethering
|
||||
// function changes from NCM to RNDIS, this can lead to Tethering starting NCM tethering
|
||||
// as local-only. But if this happens, the SettingsObserver will call stopTetheringInternal
|
||||
// for both TETHERING_USB and TETHERING_NCM, so the local-only NCM interface will be
|
||||
// stopped immediately.
|
||||
final int tetheringType = (isNcm && !mConfig.isUsingNcm()) ? TETHERING_NCM : TETHERING_USB;
|
||||
final TetheringRequest request = mRequestTracker.getOrCreatePendingRequest(tetheringType);
|
||||
if (ifaces != null) {
|
||||
for (String iface : ifaces) {
|
||||
if (ifaceNameToType(iface) == tetheringType) {
|
||||
enableIpServing(request, iface, forNcmFunction);
|
||||
enableIpServing(request, iface, isNcm);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mLog.e("could not enable IpServer for function " + (forNcmFunction ? "NCM" : "RNDIS"));
|
||||
mLog.e("could not enable IpServer for function " + (isNcm ? "NCM" : "RNDIS"));
|
||||
}
|
||||
|
||||
private void disableUsbIpServing(boolean forNcmFunction) {
|
||||
|
|
@ -3106,20 +3095,7 @@ public class Tethering {
|
|||
return type != TETHERING_INVALID;
|
||||
}
|
||||
|
||||
private void ensureIpServerStartedForInterface(final String iface) {
|
||||
// If we don't care about this type of interface, ignore.
|
||||
final int interfaceType = ifaceNameToType(iface);
|
||||
if (!checkTetherableType(interfaceType)) {
|
||||
mLog.log(iface + " is used for " + interfaceType + " which is not tetherable"
|
||||
+ " (-1 == INVALID is expected on upstream interface)");
|
||||
return;
|
||||
}
|
||||
|
||||
ensureIpServerStartedForType(iface, interfaceType, false /* isNcm */);
|
||||
}
|
||||
|
||||
private void ensureIpServerStartedForType(final String iface, int interfaceType,
|
||||
boolean isNcm) {
|
||||
private void ensureIpServerStarted(final String iface, int interfaceType, boolean isNcm) {
|
||||
// If we have already started a TISM for this interface, skip.
|
||||
if (mTetherStates.containsKey(iface)) {
|
||||
mLog.log("active iface (" + iface + ") reported as added, ignoring");
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@ import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
|
|||
|
||||
import static com.android.networkstack.apishim.ConstantsShim.KEY_CARRIER_SUPPORTS_TETHERING_BOOL;
|
||||
import static com.android.net.module.util.SdkUtil.isAtLeast25Q2;
|
||||
import static com.android.networkstack.tethering.TetheringFeatureFlags.TETHER_ENABLE_SYNC_SM;
|
||||
import static com.android.networkstack.tethering.TetheringFeatureFlags.TETHER_ENABLE_WEAR_TETHERING;
|
||||
import static com.android.networkstack.tethering.TetheringFeatureFlags.TETHER_FORCE_UPSTREAM_AUTOMATIC_VERSION;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
|
|
@ -101,19 +104,6 @@ public class TetheringConfiguration {
|
|||
public static final String USE_LEGACY_WIFI_P2P_DEDICATED_IP =
|
||||
"use_legacy_wifi_p2p_dedicated_ip";
|
||||
|
||||
/**
|
||||
* Experiment flag to force choosing upstreams automatically.
|
||||
*
|
||||
* This setting is intended to help force-enable the feature on OEM devices that disabled it
|
||||
* via resource overlays, and later noticed issues. To that end, it overrides
|
||||
* config_tether_upstream_automatic when set to true.
|
||||
*
|
||||
* This flag is enabled if !=0 and less than the module APEX version: see
|
||||
* {@link DeviceConfigUtils#isTetheringFeatureEnabled}. It is also ignored after R, as later
|
||||
* devices should just set config_tether_upstream_automatic to true instead.
|
||||
*/
|
||||
public static final String TETHER_FORCE_UPSTREAM_AUTOMATIC_VERSION =
|
||||
"tether_force_upstream_automatic_version";
|
||||
|
||||
/**
|
||||
* Settings key to foce choosing usb functions for usb tethering.
|
||||
|
|
@ -123,14 +113,6 @@ public class TetheringConfiguration {
|
|||
public static final String TETHER_FORCE_USB_FUNCTIONS =
|
||||
"tether_force_usb_functions";
|
||||
|
||||
/**
|
||||
* Experiment flag to enable TETHERING_WEAR.
|
||||
*/
|
||||
public static final String TETHER_ENABLE_WEAR_TETHERING =
|
||||
"tether_enable_wear_tethering";
|
||||
|
||||
public static final String TETHER_ENABLE_SYNC_SM = "tether_enable_sync_sm";
|
||||
|
||||
/**
|
||||
* Default value that used to periodic polls tether offload stats from tethering offload HAL
|
||||
* to make the data warnings work.
|
||||
|
|
@ -140,18 +122,6 @@ public class TetheringConfiguration {
|
|||
/** A flag for using synchronous or asynchronous state machine. */
|
||||
public static boolean USE_SYNC_SM = true;
|
||||
|
||||
/**
|
||||
* A feature flag to control whether the active sessions metrics should be enabled.
|
||||
* Disabled by default.
|
||||
*/
|
||||
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.
|
||||
* Disabled by default.
|
||||
*/
|
||||
public static final String TETHERING_LOCAL_NETWORK_AGENT = "tethering_local_network_agent";
|
||||
|
||||
public final String[] tetherableUsbRegexs;
|
||||
public final String[] tetherableWifiRegexs;
|
||||
public final String[] tetherableWigigRegexs;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.android.networkstack.tethering;
|
||||
|
||||
import com.android.net.module.util.DeviceConfigUtils;
|
||||
|
||||
/**
|
||||
* The class that contains Tethering feature flags;
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class TetheringFeatureFlags {
|
||||
/**
|
||||
* A feature flag to control whether the automatic forced choosing upstreams is enabled.
|
||||
*
|
||||
* This setting is intended to help force-enable the feature on OEM devices that disabled it
|
||||
* via resource overlays, and later noticed issues. To that end, it overrides
|
||||
* config_tether_upstream_automatic when set to true.
|
||||
*
|
||||
* This flag is enabled if !=0 and less than the module APEX version: see
|
||||
* {@link DeviceConfigUtils#isTetheringFeatureEnabled}. It is also ignored after R, as later
|
||||
* devices should just set config_tether_upstream_automatic to true instead.
|
||||
*/
|
||||
public static final String TETHER_FORCE_UPSTREAM_AUTOMATIC_VERSION =
|
||||
"tether_force_upstream_automatic_version";
|
||||
|
||||
/**
|
||||
* A feature flag to control whether the TETHERING_WEAR is enabled.
|
||||
*/
|
||||
public static final String TETHER_ENABLE_WEAR_TETHERING = "tether_enable_wear_tethering";
|
||||
|
||||
/**
|
||||
* A feature flag to control whether the force random prefix base selection is enabled.
|
||||
*/
|
||||
public static final String TETHER_FORCE_RANDOM_PREFIX_BASE_SELECTION =
|
||||
"tether_force_random_prefix_base_selection";
|
||||
|
||||
/**
|
||||
* A feature flag to control whether the synchronize state machine is enabled.
|
||||
*/
|
||||
public static final String TETHER_ENABLE_SYNC_SM = "tether_enable_sync_sm";
|
||||
|
||||
/**
|
||||
* A feature flag to control whether the active sessions metrics should be enabled.
|
||||
* Disabled by default.
|
||||
*/
|
||||
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.
|
||||
* Disabled by default.
|
||||
*/
|
||||
public static final String TETHERING_LOCAL_NETWORK_AGENT = "tethering_local_network_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";
|
||||
}
|
||||
|
|
@ -108,7 +108,7 @@ public abstract class EthernetTetheringTestBase {
|
|||
// See TetheredInterfaceRequester.getInterface, isInterfaceForTetheringAvailable.
|
||||
private static final int SHORT_TIMEOUT_MS = 1000;
|
||||
private static final int TETHER_REACHABILITY_ATTEMPTS = 20;
|
||||
protected static final long WAIT_RA_TIMEOUT_MS = 2000;
|
||||
protected static final long WAIT_RA_TIMEOUT_MS = 10000;
|
||||
|
||||
// Address and NAT prefix definition.
|
||||
protected static final MacAddress TEST_MAC = MacAddress.fromString("1:2:3:4:5:6");
|
||||
|
|
@ -296,7 +296,7 @@ public abstract class EthernetTetheringTestBase {
|
|||
final long deadline = SystemClock.uptimeMillis() + timeoutMs;
|
||||
do {
|
||||
byte[] pkt = reader.popPacket(timeoutMs);
|
||||
if (isExpectedIcmpPacket(pkt, true /* hasEth */, false /* isIpv4 */,
|
||||
if (pkt != null && isExpectedIcmpPacket(pkt, true /* hasEth */, false /* isIpv4 */,
|
||||
ICMPV6_ROUTER_ADVERTISEMENT)) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,8 +93,8 @@ import com.android.testutils.DeviceInfoUtils;
|
|||
import com.android.testutils.DumpTestUtils;
|
||||
import com.android.testutils.NetworkStackModuleTest;
|
||||
import com.android.testutils.PollPacketReader;
|
||||
import com.android.testutils.RecorderCallback.CallbackEntry;
|
||||
import com.android.testutils.TestableNetworkCallback;
|
||||
import com.android.testutils.TestableNetworkCallback.Event;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Rule;
|
||||
|
|
@ -219,6 +219,7 @@ public class EthernetTetheringTest extends EthernetTetheringTestBase {
|
|||
|
||||
// Shamelessly copied from TetheringConfiguration.
|
||||
private static final String TETHERING_LOCAL_NETWORK_AGENT = "tethering_local_network_agent";
|
||||
private static final String WIFIP2PGO_LOCAL_NETWORK_AGENT = "wifip2pgo_local_network_agent";
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
|
|
@ -1245,15 +1246,29 @@ public class EthernetTetheringTest extends EthernetTetheringTestBase {
|
|||
}
|
||||
}
|
||||
|
||||
private void assumeMatchNonThreadLocalNetworksEnabled() {
|
||||
assumeTrue(runAsShell(READ_COMPAT_CHANGE_CONFIG, LOG_COMPAT_CHANGE,
|
||||
() -> CompatChanges.isChangeEnabled(ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS)));
|
||||
}
|
||||
|
||||
@IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
||||
@Test
|
||||
public void testLocalAgent_networkCallbacks() throws Exception {
|
||||
final boolean isMatchNonThreadLocalNetworksEnabled = runAsShell(
|
||||
READ_COMPAT_CHANGE_CONFIG, LOG_COMPAT_CHANGE,
|
||||
() -> CompatChanges.isChangeEnabled(ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS));
|
||||
assumeTrue(isMatchNonThreadLocalNetworksEnabled);
|
||||
|
||||
public void testTetheringLocalAgent_networkCallbacks() throws Exception {
|
||||
assumeMatchNonThreadLocalNetworksEnabled();
|
||||
mDeviceConfigRule.setConfig(NAMESPACE_TETHERING, TETHERING_LOCAL_NETWORK_AGENT, "1");
|
||||
doTestLocalAgent_networkCallbacks(CONNECTIVITY_SCOPE_GLOBAL);
|
||||
}
|
||||
|
||||
@IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
||||
@Test
|
||||
public void testWifiP2pGroupOwnerLocalAgent_networkCallbacks() throws Exception {
|
||||
assumeMatchNonThreadLocalNetworksEnabled();
|
||||
mDeviceConfigRule.setConfig(NAMESPACE_TETHERING, TETHERING_LOCAL_NETWORK_AGENT, "1");
|
||||
mDeviceConfigRule.setConfig(NAMESPACE_TETHERING, WIFIP2PGO_LOCAL_NETWORK_AGENT, "1");
|
||||
doTestLocalAgent_networkCallbacks(CONNECTIVITY_SCOPE_LOCAL);
|
||||
}
|
||||
|
||||
private void doTestLocalAgent_networkCallbacks(int scope) throws Exception {
|
||||
assumeFalse(isInterfaceForTetheringAvailable());
|
||||
setIncludeTestInterfaces(true);
|
||||
|
||||
|
|
@ -1273,17 +1288,30 @@ public class EthernetTetheringTest extends EthernetTetheringTestBase {
|
|||
downstreamIface.getInterfaceName(), iface);
|
||||
|
||||
final TetheringRequest request = new TetheringRequest.Builder(TETHERING_ETHERNET)
|
||||
.setConnectivityScope(CONNECTIVITY_SCOPE_GLOBAL).build();
|
||||
.setConnectivityScope(scope).build();
|
||||
tetheringEventCallback = enableTethering(iface, request, null /* any upstream */);
|
||||
tetheringEventCallback.awaitInterfaceTethered();
|
||||
if (scope == CONNECTIVITY_SCOPE_GLOBAL) {
|
||||
tetheringEventCallback.awaitInterfaceTethered();
|
||||
} else {
|
||||
tetheringEventCallback.awaitInterfaceLocalOnly();
|
||||
}
|
||||
|
||||
// Verify NetworkCallback works accordingly.
|
||||
final Network network = networkCallback.expect(CallbackEntry.AVAILABLE).getNetwork();
|
||||
final CallbackEntry.CapabilitiesChanged capEvent =
|
||||
networkCallback.eventuallyExpect(CallbackEntry.NETWORK_CAPS_UPDATED);
|
||||
final Network network = networkCallback.expect(Event.AVAILABLE).getNetwork();
|
||||
final Event.CapabilitiesChanged capEvent =
|
||||
networkCallback.eventuallyExpect(Event.NETWORK_CAPS_UPDATED);
|
||||
assertEquals(network, capEvent.getNetwork());
|
||||
assertTrue(capEvent.getCaps().hasTransport(TRANSPORT_ETHERNET));
|
||||
assertTrue(capEvent.getCaps().hasCapability(NET_CAPABILITY_LOCAL_NETWORK));
|
||||
|
||||
// Verify details in the LinkPropertiesChanged event.
|
||||
final Event.LinkPropertiesChanged lpEvent =
|
||||
networkCallback.eventuallyExpect(Event.LINK_PROPERTIES_CHANGED);
|
||||
assertEquals(network, lpEvent.getNetwork());
|
||||
assertEquals(iface, lpEvent.getLp().getInterfaceName());
|
||||
assertTrue(lpEvent.getLp().hasIPv4Address());
|
||||
// At least one Ipv4 route for the subnet is needed.
|
||||
assertTrue(lpEvent.getLp().getRoutes().size() >= 1);
|
||||
} finally {
|
||||
stopEthernetTethering(tetheringEventCallback);
|
||||
maybeCloseTestInterface(downstreamIface);
|
||||
|
|
|
|||
|
|
@ -40,7 +40,8 @@ import static android.net.ip.IpServer.getTetherableIpv6Prefixes;
|
|||
import static com.android.modules.utils.build.SdkLevel.isAtLeastT;
|
||||
import static com.android.modules.utils.build.SdkLevel.isAtLeastV;
|
||||
import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH;
|
||||
import static com.android.networkstack.tethering.TetheringConfiguration.TETHERING_LOCAL_NETWORK_AGENT;
|
||||
import static com.android.networkstack.tethering.TetheringFeatureFlags.TETHERING_LOCAL_NETWORK_AGENT;
|
||||
import static com.android.networkstack.tethering.TetheringFeatureFlags.WIFIP2PGO_LOCAL_NETWORK_AGENT;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
|
@ -1123,20 +1124,33 @@ public class IpServerTest {
|
|||
|
||||
@IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
||||
@SetFeatureFlagsRule.FeatureFlag(name = TETHERING_LOCAL_NETWORK_AGENT, enabled = false)
|
||||
@SetFeatureFlagsRule.FeatureFlag(name = WIFIP2PGO_LOCAL_NETWORK_AGENT)
|
||||
@Test
|
||||
public void testTetheringNetworkAgent_tetheringAgentDisabled() throws Exception {
|
||||
doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_GLOBAL, false);
|
||||
// Even if the flag is enabled, no wifip2p network agent if the tethering network
|
||||
// agent feature is not supported.
|
||||
doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_LOCAL, false);
|
||||
}
|
||||
|
||||
// Verify Tethering Network Agent feature doesn't affect Wi-fi P2P Group Owner although
|
||||
// the code is mostly shared.
|
||||
@IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
||||
@SetFeatureFlagsRule.FeatureFlag(name = TETHERING_LOCAL_NETWORK_AGENT)
|
||||
@SetFeatureFlagsRule.FeatureFlag(name = WIFIP2PGO_LOCAL_NETWORK_AGENT, enabled = false)
|
||||
@Test
|
||||
public void testTetheringNetworkAgent_p2pGroupOwnerAgentDisabled() throws Exception {
|
||||
doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_LOCAL, false);
|
||||
}
|
||||
|
||||
@IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
||||
@SetFeatureFlagsRule.FeatureFlag(name = TETHERING_LOCAL_NETWORK_AGENT)
|
||||
@SetFeatureFlagsRule.FeatureFlag(name = WIFIP2PGO_LOCAL_NETWORK_AGENT)
|
||||
@Test
|
||||
public void testTetheringNetworkAgent_p2pGroupOwnerAgentEnabled() throws Exception {
|
||||
doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_LOCAL, true);
|
||||
}
|
||||
|
||||
private void doTestTetheringNetworkAgent(int scope, boolean expectAgentEnabled)
|
||||
throws Exception {
|
||||
initStateMachine(TETHERING_USB);
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ import static com.android.networkstack.tethering.BpfCoordinator.toIpv4MappedAddr
|
|||
import static com.android.networkstack.tethering.BpfUtils.DOWNSTREAM;
|
||||
import static com.android.networkstack.tethering.BpfUtils.UPSTREAM;
|
||||
import static com.android.networkstack.tethering.TetheringConfiguration.DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS;
|
||||
import static com.android.networkstack.tethering.TetheringConfiguration.TETHER_ACTIVE_SESSIONS_METRICS;
|
||||
import static com.android.networkstack.tethering.TetheringFeatureFlags.TETHER_ACTIVE_SESSIONS_METRICS;
|
||||
import static com.android.testutils.MiscAsserts.assertSameElements;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSess
|
|||
import static com.android.networkstack.apishim.ConstantsShim.KEY_CARRIER_SUPPORTS_TETHERING_BOOL;
|
||||
import static com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
|
||||
import static com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
|
||||
import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
|
@ -67,6 +66,7 @@ import android.content.pm.ModuleInfo;
|
|||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.PersistableBundle;
|
||||
|
|
@ -603,7 +603,7 @@ public final class EntitlementManagerTest {
|
|||
.onTetherProvisioningFailed(TETHERING_WIFI, FAILED_TETHERING_REASON);
|
||||
}
|
||||
|
||||
@IgnoreUpTo(SC_V2)
|
||||
@IgnoreUpTo(Build.VERSION_CODES.S_V2)
|
||||
@Test
|
||||
public void testUiProvisioningMultiUser_aboveT_createContextAsUserThrows() {
|
||||
mMockContext.setCreateContextAsUserException(new IllegalStateException());
|
||||
|
|
@ -611,14 +611,14 @@ public final class EntitlementManagerTest {
|
|||
doTestUiProvisioningMultiUser(false, 1);
|
||||
}
|
||||
|
||||
@IgnoreUpTo(SC_V2)
|
||||
@IgnoreUpTo(Build.VERSION_CODES.S_V2)
|
||||
@Test
|
||||
public void testUiProvisioningMultiUser_aboveT() {
|
||||
doTestUiProvisioningMultiUser(true, 1);
|
||||
doTestUiProvisioningMultiUser(false, 0);
|
||||
}
|
||||
|
||||
@IgnoreAfter(SC_V2)
|
||||
@IgnoreAfter(Build.VERSION_CODES.S_V2)
|
||||
@Test
|
||||
public void testUiProvisioningMultiUser_belowT() {
|
||||
doTestUiProvisioningMultiUser(true, 1);
|
||||
|
|
@ -734,7 +734,7 @@ public final class EntitlementManagerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@IgnoreUpTo(SC_V2)
|
||||
@IgnoreUpTo(Build.VERSION_CODES.S_V2)
|
||||
public void requestLatestTetheringEntitlementResult_carrierDoesNotSupport_noProvisionCount()
|
||||
throws Exception {
|
||||
setupCarrierConfig(false);
|
||||
|
|
@ -746,7 +746,7 @@ public final class EntitlementManagerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@IgnoreUpTo(SC_V2)
|
||||
@IgnoreUpTo(Build.VERSION_CODES.S_V2)
|
||||
public void reevaluateSimCardProvisioning_carrierUnsupportAndSimswitch() {
|
||||
setupForRequiredProvisioning();
|
||||
|
||||
|
|
@ -771,7 +771,7 @@ public final class EntitlementManagerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@IgnoreUpTo(SC_V2)
|
||||
@IgnoreUpTo(Build.VERSION_CODES.S_V2)
|
||||
public void startProvisioningIfNeeded_carrierUnsupport()
|
||||
throws Exception {
|
||||
setupCarrierConfig(false);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import static android.net.TetheringManager.TETHERING_WIFI;
|
|||
import static android.net.TetheringManager.TETHERING_WIFI_P2P;
|
||||
import static android.net.ip.IpServer.CMD_NOTIFY_PREFIX_CONFLICT;
|
||||
|
||||
import static com.android.net.module.util.PrivateAddressCoordinator.TETHER_FORCE_RANDOM_PREFIX_BASE_SELECTION;
|
||||
import static com.android.networkstack.tethering.util.PrefixUtils.asIpPrefix;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
|
@ -50,7 +51,6 @@ import android.net.LinkProperties;
|
|||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.ip.IpServer;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
|
@ -58,10 +58,8 @@ import androidx.test.runner.AndroidJUnit4;
|
|||
|
||||
import com.android.net.module.util.IIpv4PrefixRequest;
|
||||
import com.android.net.module.util.PrivateAddressCoordinator;
|
||||
import com.android.testutils.DevSdkIgnoreRule;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
|
|
@ -73,9 +71,6 @@ import java.util.Arrays;
|
|||
@RunWith(AndroidJUnit4.class)
|
||||
@SmallTest
|
||||
public final class PrivateAddressCoordinatorTest {
|
||||
@Rule
|
||||
public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
|
||||
|
||||
private static final String TEST_IFNAME = "test0";
|
||||
|
||||
@Mock private IpServer mHotspotIpServer;
|
||||
|
|
@ -236,9 +231,11 @@ public final class PrivateAddressCoordinatorTest {
|
|||
assertEquals(usbAddress, newUsbAddress);
|
||||
|
||||
final UpstreamNetworkState wifiUpstream = buildUpstreamNetworkState(mWifiNetwork,
|
||||
hotspotAddress, null, makeNetworkCapabilities(TRANSPORT_WIFI));
|
||||
new LinkAddress("192.168.88.23/16"), null,
|
||||
makeNetworkCapabilities(TRANSPORT_WIFI));
|
||||
updateUpstreamPrefix(wifiUpstream);
|
||||
verify(mHotspotIpServer).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
|
||||
verify(mUsbIpServer).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
|
||||
}
|
||||
|
||||
private UpstreamNetworkState buildUpstreamNetworkState(final Network network,
|
||||
|
|
@ -326,9 +323,11 @@ public final class PrivateAddressCoordinatorTest {
|
|||
assertFalse(localHotspotPrefix.containsPrefix(hotspotPrefix));
|
||||
}
|
||||
|
||||
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.VANILLA_ICE_CREAM)
|
||||
@Test
|
||||
public void testStartedPrefixRange() throws Exception {
|
||||
when(mDeps.isFeatureNotChickenedOut(TETHER_FORCE_RANDOM_PREFIX_BASE_SELECTION))
|
||||
.thenReturn(true);
|
||||
|
||||
startedPrefixBaseTest("192.168.0.0/16", 0);
|
||||
|
||||
startedPrefixBaseTest("192.168.0.0/16", 1);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import static com.android.networkstack.tethering.TetheringConfiguration.TETHER_E
|
|||
import static com.android.networkstack.tethering.TetheringConfiguration.TETHER_FORCE_USB_FUNCTIONS;
|
||||
import static com.android.networkstack.tethering.TetheringConfiguration.TETHER_USB_NCM_FUNCTION;
|
||||
import static com.android.networkstack.tethering.TetheringConfiguration.TETHER_USB_RNDIS_FUNCTION;
|
||||
import static com.android.networkstack.tethering.TetheringFeatureFlags.TETHER_FORCE_UPSTREAM_AUTOMATIC_VERSION;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
|
@ -179,7 +180,7 @@ public class TetheringConfigurationTest {
|
|||
|
||||
@Override
|
||||
boolean isTetherForceUpstreamAutomaticFeatureEnabled() {
|
||||
return isMockFlagEnabled(TetheringConfiguration.TETHER_FORCE_UPSTREAM_AUTOMATIC_VERSION,
|
||||
return isMockFlagEnabled(TETHER_FORCE_UPSTREAM_AUTOMATIC_VERSION,
|
||||
false /* defaultEnabled */);
|
||||
}
|
||||
|
||||
|
|
@ -639,8 +640,7 @@ public class TetheringConfigurationTest {
|
|||
}
|
||||
|
||||
private void setTetherForceUpstreamAutomaticFlagEnabled(Boolean enabled) {
|
||||
mDeps.setFeatureEnabled(
|
||||
TetheringConfiguration.TETHER_FORCE_UPSTREAM_AUTOMATIC_VERSION, enabled);
|
||||
mDeps.setFeatureEnabled(TETHER_FORCE_UPSTREAM_AUTOMATIC_VERSION, enabled);
|
||||
}
|
||||
|
||||
private void assertChooseUpstreamAutomaticallyIs(boolean value) {
|
||||
|
|
@ -762,28 +762,22 @@ public class TetheringConfigurationTest {
|
|||
}
|
||||
|
||||
private void setTetherEnableSyncSMFlagEnabled(Boolean enabled) {
|
||||
mDeps.setFeatureEnabled(TetheringConfiguration.TETHER_ENABLE_SYNC_SM, enabled);
|
||||
mDeps.setFeatureEnabled(TetheringFeatureFlags.TETHER_ENABLE_SYNC_SM, enabled);
|
||||
new TetheringConfiguration(
|
||||
mMockContext, mLog, INVALID_SUBSCRIPTION_ID, mDeps).readEnableSyncSM(mMockContext);
|
||||
}
|
||||
|
||||
private void assertEnableSyncSM(boolean value) {
|
||||
assertEquals(value, TetheringConfiguration.USE_SYNC_SM);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnableSyncSMFlag() throws Exception {
|
||||
// Test default enabled
|
||||
setTetherEnableSyncSMFlagEnabled(null);
|
||||
assertEnableSyncSM(true);
|
||||
assertEquals(true, TetheringConfiguration.USE_SYNC_SM);
|
||||
|
||||
setTetherEnableSyncSMFlagEnabled(true);
|
||||
assertEnableSyncSM(true);
|
||||
assertEquals(true, TetheringConfiguration.USE_SYNC_SM);
|
||||
|
||||
// Feature is enabled by default after 25Q2 release.
|
||||
if (!SdkUtil.isAtLeast25Q2()) {
|
||||
setTetherEnableSyncSMFlagEnabled(false);
|
||||
assertEnableSyncSM(false);
|
||||
}
|
||||
// Feature is enabled forcefully after 25Q2 release.
|
||||
setTetherEnableSyncSMFlagEnabled(false);
|
||||
assertEquals(SdkUtil.isAtLeast25Q2(), TetheringConfiguration.USE_SYNC_SM);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
|
|||
import static android.net.TetheringManager.TETHER_ERROR_SERVICE_UNAVAIL;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_IFACE;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_REQUEST;
|
||||
import static android.net.TetheringManager.TETHER_ERROR_UNSUPPORTED;
|
||||
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_FAILED;
|
||||
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED;
|
||||
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED;
|
||||
|
|
@ -84,10 +85,10 @@ import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOA
|
|||
import static com.android.networkstack.tethering.TestConnectivityManager.BROADCAST_FIRST;
|
||||
import static com.android.networkstack.tethering.TestConnectivityManager.CALLBACKS_FIRST;
|
||||
import static com.android.networkstack.tethering.Tethering.UserRestrictionActionListener;
|
||||
import static com.android.networkstack.tethering.TetheringConfiguration.TETHERING_LOCAL_NETWORK_AGENT;
|
||||
import static com.android.networkstack.tethering.TetheringConfiguration.TETHER_FORCE_USB_FUNCTIONS;
|
||||
import static com.android.networkstack.tethering.TetheringConfiguration.TETHER_USB_NCM_FUNCTION;
|
||||
import static com.android.networkstack.tethering.TetheringConfiguration.TETHER_USB_RNDIS_FUNCTION;
|
||||
import static com.android.networkstack.tethering.TetheringFeatureFlags.TETHERING_LOCAL_NETWORK_AGENT;
|
||||
import static com.android.networkstack.tethering.TetheringNotificationUpdater.DOWNSTREAM_NONE;
|
||||
import static com.android.networkstack.tethering.UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES;
|
||||
import static com.android.testutils.TestPermissionUtil.runAsShell;
|
||||
|
|
@ -538,8 +539,8 @@ public class TetheringTest {
|
|||
public RoutingCoordinatorManager getRoutingCoordinator(
|
||||
final Context context, SharedLog log) {
|
||||
ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
|
||||
when(mPrivateAddressCoordinatorDependencies.isFeatureEnabled(anyString()))
|
||||
.thenReturn(false);
|
||||
when(mPrivateAddressCoordinatorDependencies.isFeatureNotChickenedOut(anyString()))
|
||||
.thenReturn(true);
|
||||
RoutingCoordinatorService service = new RoutingCoordinatorService(
|
||||
getINetd(context, log),
|
||||
cm::getAllNetworks,
|
||||
|
|
@ -1007,23 +1008,11 @@ public class TetheringTest {
|
|||
}
|
||||
sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
|
||||
|
||||
// If, and only if, Tethering received an interface status changed then
|
||||
// it creates a IpServer and sends out a broadcast indicating that the
|
||||
// interface is "available".
|
||||
if (emulateInterfaceStatusChanged) {
|
||||
if (!SdkLevel.isAtLeastB()) {
|
||||
// There is 1 IpServer state change event: STATE_AVAILABLE
|
||||
verify(mNotificationUpdater, times(1)).onDownstreamChanged(DOWNSTREAM_NONE);
|
||||
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
|
||||
verify(mWifiManager).updateInterfaceIpState(
|
||||
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
|
||||
} else {
|
||||
// Starting in B, ignore the interfaceStatusChanged
|
||||
verify(mNotificationUpdater, never()).onDownstreamChanged(DOWNSTREAM_NONE);
|
||||
verify(mWifiManager, never()).updateInterfaceIpState(
|
||||
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
|
||||
}
|
||||
}
|
||||
// Wi-Fi tethering ignores interface up events. The behaviour is the same
|
||||
// regardless of whether the interface up event was received or not.
|
||||
verify(mNotificationUpdater, never()).onDownstreamChanged(DOWNSTREAM_NONE);
|
||||
verify(mWifiManager, never()).updateInterfaceIpState(
|
||||
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
|
||||
verifyNoMoreInteractions(mNetd);
|
||||
verifyNoMoreInteractions(mWifiManager);
|
||||
}
|
||||
|
|
@ -2045,18 +2034,10 @@ public class TetheringTest {
|
|||
sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
|
||||
mLooper.dispatchAll();
|
||||
|
||||
if (!SdkLevel.isAtLeastB()) {
|
||||
// There is 1 IpServer state change event: STATE_AVAILABLE from interfaceStatusChanged
|
||||
verify(mNotificationUpdater, times(1)).onDownstreamChanged(DOWNSTREAM_NONE);
|
||||
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
|
||||
verify(mWifiManager).updateInterfaceIpState(
|
||||
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
|
||||
} else {
|
||||
// Starting in B, ignore the interfaceStatusChanged
|
||||
verify(mNotificationUpdater, never()).onDownstreamChanged(DOWNSTREAM_NONE);
|
||||
verify(mWifiManager, never()).updateInterfaceIpState(
|
||||
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
|
||||
}
|
||||
// Wi-Fi tethering ignores interface up events.
|
||||
verify(mNotificationUpdater, never()).onDownstreamChanged(DOWNSTREAM_NONE);
|
||||
verify(mWifiManager, never()).updateInterfaceIpState(
|
||||
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
|
||||
verifyNoMoreInteractions(mNetd);
|
||||
verifyNoMoreInteractions(mWifiManager);
|
||||
}
|
||||
|
|
@ -3420,39 +3401,22 @@ public class TetheringTest {
|
|||
|
||||
@Test
|
||||
@IgnoreAfter(Build.VERSION_CODES.VANILLA_ICE_CREAM)
|
||||
public void testRequestStaticIpLegacyTether() throws Exception {
|
||||
public void testLegacyTetherUnsupported() throws Exception {
|
||||
initTetheringOnTestThread();
|
||||
|
||||
// Call startTethering with static ip
|
||||
final LinkAddress serverLinkAddr = new LinkAddress("192.168.0.123/24");
|
||||
final LinkAddress clientLinkAddr = new LinkAddress("192.168.0.42/24");
|
||||
final String serverAddr = "192.168.0.123";
|
||||
final int clientAddrParceled = 0xc0a8002a;
|
||||
final ArgumentCaptor<DhcpServingParamsParcel> dhcpParamsCaptor =
|
||||
ArgumentCaptor.forClass(DhcpServingParamsParcel.class);
|
||||
mTethering.startTethering(createTetheringRequest(TETHERING_WIFI,
|
||||
serverLinkAddr, clientLinkAddr, false, CONNECTIVITY_SCOPE_GLOBAL, null),
|
||||
TEST_CALLER_PKG, null);
|
||||
mTethering.interfaceAdded(TEST_WIFI_IFNAME);
|
||||
mLooper.dispatchAll();
|
||||
verifyWifiTetheringRequested();
|
||||
mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
|
||||
mTethering.interfaceStatusChanged(TEST_WIFI_IFNAME, false);
|
||||
mTethering.interfaceStatusChanged(TEST_WIFI_IFNAME, true);
|
||||
|
||||
// Call legacyTether on the interface before the link layer event comes back.
|
||||
// This happens, for example, in pre-T bluetooth tethering: Settings calls startTethering,
|
||||
// and then the bluetooth code calls the tether() API.
|
||||
final ResultListener tetherResult = new ResultListener(TETHER_ERROR_NO_ERROR);
|
||||
mTethering.legacyTether(TEST_WLAN_IFNAME, tetherResult);
|
||||
final ResultListener result = new ResultListener(TETHER_ERROR_UNSUPPORTED);
|
||||
mTethering.legacyTether(TEST_WIFI_IFNAME, result);
|
||||
mLooper.dispatchAll();
|
||||
tetherResult.assertHasResult();
|
||||
result.assertHasResult();
|
||||
|
||||
// Verify that the static ip set in startTethering is used
|
||||
verify(mNetd).interfaceSetCfg(argThat(cfg -> serverAddr.equals(cfg.ipv4Addr)));
|
||||
verify(mIpServerDependencies, times(1)).makeDhcpServer(any(), dhcpParamsCaptor.capture(),
|
||||
any());
|
||||
final DhcpServingParamsParcel params = dhcpParamsCaptor.getValue();
|
||||
assertEquals(serverAddr, intToInet4AddressHTH(params.serverAddr).getHostAddress());
|
||||
assertEquals(24, params.serverAddrPrefixLength);
|
||||
assertEquals(clientAddrParceled, params.singleClientAddr);
|
||||
// No IpServer should have been started, so no STATE_AVAILABLE should have been sent, and no
|
||||
// tethering broadcasts should have been sent.
|
||||
assertEquals(0, mIntents.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -42,10 +42,16 @@ static inline void waitForNetProgsLoaded() {
|
|||
// infinite loop until success with 5/10/20/40/60/60/60... delay
|
||||
for (int delay = 5;; delay *= 2) {
|
||||
if (delay > 60) delay = 60;
|
||||
if (base::WaitForProperty("init.svc.mdnsd_netbpfload", "stopped", std::chrono::seconds(delay))
|
||||
&& mainlineNetBpfLoadDone()) return;
|
||||
if (base::WaitForProperty("init.svc.mdnsd_netbpfload", "stopped", std::chrono::seconds(delay)))
|
||||
break;
|
||||
LOG(WARNING) << "Waited " << delay << "s for init.svc.mdnsd_netbpfload=stopped, still waiting.";
|
||||
}
|
||||
if (!mainlineNetBpfLoadDone()) {
|
||||
LOG(ERROR) << "FATAL: init.svc.mdnsd_netbpfload=stopped, yet !mainlineNetBpfLoadDone";
|
||||
// mdnsd_netbpfload is marked 'reboot_on_failure', init should start a reboot very soon now,
|
||||
// spamming logs with an abort is pointless
|
||||
for (;;);
|
||||
}
|
||||
}
|
||||
|
||||
base::Result<void> DnsBpfHelper::init() {
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue