Introduce interfaceName field into TetheringRequestParcel

Bug: 340376953
API-Coverage-Bug: 365678805
Test: Presubmit
Test: atest EthernetTetheringTest
Test: atest TetheringTest
Test: atest NsdManagerDownstreamTetheringTest -b
Test: atest TetheringManagerTest -b

Change-Id: I8025cc2e238b8f9516bf18d8ea0253f1c58a05e6
This commit is contained in:
Seungjae Yoo 2024-09-10 12:11:34 +09:00 • committed by Quang Anh Luong
commit eab1de47f4
11 changed files with 229 additions and 53 deletions

View file

@ -47,9 +47,14 @@ package android.net {
}
public static final class TetheringManager.TetheringRequest implements android.os.Parcelable {
method @FlaggedApi("com.android.net.flags.tethering_with_soft_ap_config") @Nullable public String getInterfaceName();
method @FlaggedApi("com.android.net.flags.tethering_with_soft_ap_config") @Nullable public String getPackageName();
method @FlaggedApi("com.android.net.flags.tethering_with_soft_ap_config") public int getUid();
}
public static class TetheringManager.TetheringRequest.Builder {
method @FlaggedApi("com.android.net.flags.tethering_with_soft_ap_config") @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public android.net.TetheringManager.TetheringRequest.Builder setInterfaceName(@Nullable String);
}
}

View file

@ -136,6 +136,7 @@ public class TetheringManager {
TETHERING_WIFI_P2P,
TETHERING_NCM,
TETHERING_ETHERNET,
TETHERING_VIRTUAL,
})
public @interface TetheringType {
}
@ -253,6 +254,7 @@ public class TetheringManager {
@Retention(RetentionPolicy.SOURCE)
@IntDef(value = {
TETHER_ERROR_SERVICE_UNAVAIL,
TETHER_ERROR_UNSUPPORTED,
TETHER_ERROR_INTERNAL_ERROR,
TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION,
TETHER_ERROR_UNKNOWN_TYPE,
@ -775,6 +777,7 @@ public class TetheringManager {
mBuilderParcel.connectivityScope = getDefaultConnectivityScope(type);
mBuilderParcel.uid = Process.INVALID_UID;
mBuilderParcel.softApConfig = null;
mBuilderParcel.interfaceName = null;
}
/**
@ -820,6 +823,35 @@ public class TetheringManager {
return this;
}
/**
* Sets the name of the interface. Currently supported only for
* - {@link #TETHERING_VIRTUAL}.
* - {@link #TETHERING_WIFI} (for Local-only Hotspot)
* - {@link #TETHERING_WIFI_P2P}
* @hide
*/
@FlaggedApi(Flags.FLAG_TETHERING_WITH_SOFT_AP_CONFIG)
@RequiresPermission(anyOf = {
android.Manifest.permission.NETWORK_SETTINGS,
android.Manifest.permission.NETWORK_STACK,
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
})
@NonNull
@SystemApi(client = MODULE_LIBRARIES)
public Builder setInterfaceName(@Nullable final String interfaceName) {
switch (mBuilderParcel.tetheringType) {
case TETHERING_VIRTUAL:
case TETHERING_WIFI_P2P:
case TETHERING_WIFI:
break;
default:
throw new IllegalArgumentException("Interface name cannot be set for"
+ " tethering type " + interfaceName);
}
mBuilderParcel.interfaceName = interfaceName;
return this;
}
/**
* Sets the connectivity scope to be provided by this tethering downstream.
*/
@ -905,6 +937,17 @@ public class TetheringManager {
return mRequestParcel.showProvisioningUi;
}
/**
* Get interface name.
* @hide
*/
@FlaggedApi(Flags.FLAG_TETHERING_WITH_SOFT_AP_CONFIG)
@Nullable
@SystemApi(client = MODULE_LIBRARIES)
public String getInterfaceName() {
return mRequestParcel.interfaceName;
}
/**
* Check whether the two addresses are ipv4 and in the same prefix.
* @hide
@ -1022,6 +1065,9 @@ public class TetheringManager {
if (mRequestParcel.packageName != null) {
sj.add("packageName=" + mRequestParcel.packageName);
}
if (mRequestParcel.interfaceName != null) {
sj.add("interfaceName=" + mRequestParcel.interfaceName);
}
return sj.toString();
}
@ -1039,7 +1085,8 @@ public class TetheringManager {
&& parcel.connectivityScope == otherParcel.connectivityScope
&& Objects.equals(parcel.softApConfig, otherParcel.softApConfig)
&& parcel.uid == otherParcel.uid
&& Objects.equals(parcel.packageName, otherParcel.packageName);
&& Objects.equals(parcel.packageName, otherParcel.packageName)
&& Objects.equals(parcel.interfaceName, otherParcel.interfaceName);
}
@Override
@ -1048,7 +1095,7 @@ public class TetheringManager {
return Objects.hash(parcel.tetheringType, parcel.localIPv4Address,
parcel.staticClientAddress, parcel.exemptFromEntitlementCheck,
parcel.showProvisioningUi, parcel.connectivityScope, parcel.softApConfig,
parcel.uid, parcel.packageName);
parcel.uid, parcel.packageName, parcel.interfaceName);
}
}

View file

@ -33,4 +33,5 @@ parcelable TetheringRequestParcel {
SoftApConfiguration softApConfig;
int uid;
String packageName;
String interfaceName;
}

View file

@ -665,7 +665,8 @@ public class Tethering {
// If tethering is already enabled with a different request,
// disable before re-enabling.
if (unfinishedRequest != null && !unfinishedRequest.equals(request)) {
enableTetheringInternal(type, false /* disabled */, null);
enableTetheringInternal(type, false /* disabled */,
unfinishedRequest.getInterfaceName(), null);
mEntitlementMgr.stopProvisioningIfNeeded(type);
}
mActiveTetheringRequests.put(type, request);
@ -676,7 +677,7 @@ public class Tethering {
mEntitlementMgr.startProvisioningIfNeeded(type,
request.getShouldShowEntitlementUi());
}
enableTetheringInternal(type, true /* enabled */, listener);
enableTetheringInternal(type, true /* enabled */, request.getInterfaceName(), listener);
mTetheringMetrics.createBuilder(type, callerPkg);
});
}
@ -689,7 +690,7 @@ public class Tethering {
void stopTetheringInternal(int type) {
mActiveTetheringRequests.remove(type);
enableTetheringInternal(type, false /* disabled */, null);
enableTetheringInternal(type, false /* disabled */, null, null);
mEntitlementMgr.stopProvisioningIfNeeded(type);
}
@ -698,7 +699,7 @@ public class Tethering {
* schedule provisioning rechecks for the specified interface.
*/
private void enableTetheringInternal(int type, boolean enable,
final IIntResultListener listener) {
String iface, final IIntResultListener listener) {
int result = TETHER_ERROR_NO_ERROR;
switch (type) {
case TETHERING_WIFI:
@ -717,7 +718,7 @@ public class Tethering {
result = setEthernetTethering(enable);
break;
case TETHERING_VIRTUAL:
result = setVirtualMachineTethering(enable);
result = setVirtualMachineTethering(enable, iface);
break;
default:
Log.w(TAG, "Invalid tether type.");
@ -972,10 +973,13 @@ public class Tethering {
}
}
private int setVirtualMachineTethering(final boolean enable) {
// TODO(340377643): Use bridge ifname when it's introduced, not fixed TAP ifname.
private int setVirtualMachineTethering(final boolean enable, String iface) {
if (enable) {
mConfiguredVirtualIface = "avf_tap_fixed";
if (TextUtils.isEmpty(iface)) {
mConfiguredVirtualIface = "avf_tap_fixed";
} else {
mConfiguredVirtualIface = iface;
}
enableIpServing(
TETHERING_VIRTUAL,
mConfiguredVirtualIface,
@ -2205,7 +2209,7 @@ public class Tethering {
case EVENT_REQUEST_CHANGE_DOWNSTREAM: {
final boolean enabled = message.arg1 == 1;
final TetheringRequest request = (TetheringRequest) message.obj;
enableTetheringInternal(request.getTetheringType(), enabled, null);
enableTetheringInternal(request.getTetheringType(), enabled, null, null);
break;
}
default:

View file

@ -133,9 +133,11 @@ public class TetheringService extends Service {
@Override
public void startTethering(TetheringRequestParcel request, String callerPkg,
String callingAttributionTag, IIntResultListener listener) {
boolean onlyAllowPrivileged = request.exemptFromEntitlementCheck
|| request.interfaceName != null;
if (checkAndNotifyCommonError(callerPkg,
callingAttributionTag,
request.exemptFromEntitlementCheck /* onlyAllowPrivileged */,
onlyAllowPrivileged,
listener)) {
return;
}
@ -284,6 +286,10 @@ public class TetheringService extends Service {
return false;
}
private boolean hasNetworkSettingsPermission() {
return checkCallingOrSelfPermission(NETWORK_SETTINGS);
}
private boolean hasNetworkStackPermission() {
return checkCallingOrSelfPermission(NETWORK_STACK)
|| checkCallingOrSelfPermission(PERMISSION_MAINLINE_NETWORK_STACK);
@ -299,7 +305,8 @@ public class TetheringService extends Service {
private boolean hasTetherChangePermission(final String callerPkg,
final String callingAttributionTag, final boolean onlyAllowPrivileged) {
if (onlyAllowPrivileged && !hasNetworkStackPermission()) return false;
if (onlyAllowPrivileged && !hasNetworkStackPermission()
&& !hasNetworkSettingsPermission()) return false;
if (hasTetherPrivilegedPermission()) return true;

View file

@ -332,15 +332,16 @@ public abstract class EthernetTetheringTestBase {
// seconds. See b/289881008.
private static final int EXPANDED_TIMEOUT_MS = 30000;
MyTetheringEventCallback(String iface) {
mIface = new TetheringInterface(TETHERING_ETHERNET, iface);
MyTetheringEventCallback(int tetheringType, String iface) {
mIface = new TetheringInterface(tetheringType, iface);
mExpectedUpstream = null;
mAcceptAnyUpstream = true;
}
MyTetheringEventCallback(String iface, @NonNull Network expectedUpstream) {
MyTetheringEventCallback(
int tetheringType, String iface, @NonNull Network expectedUpstream) {
Objects.requireNonNull(expectedUpstream);
mIface = new TetheringInterface(TETHERING_ETHERNET, iface);
mIface = new TetheringInterface(tetheringType, iface);
mExpectedUpstream = expectedUpstream;
mAcceptAnyUpstream = false;
}
@ -392,12 +393,12 @@ public abstract class EthernetTetheringTestBase {
}
public void awaitInterfaceTethered() throws Exception {
assertTrue("Ethernet not tethered after " + EXPANDED_TIMEOUT_MS + "ms",
assertTrue("Interface is not tethered after " + EXPANDED_TIMEOUT_MS + "ms",
mTetheringStartedLatch.await(EXPANDED_TIMEOUT_MS, TimeUnit.MILLISECONDS));
}
public void awaitInterfaceLocalOnly() throws Exception {
assertTrue("Ethernet not local-only after " + EXPANDED_TIMEOUT_MS + "ms",
assertTrue("Interface is not local-only after " + EXPANDED_TIMEOUT_MS + "ms",
mLocalOnlyStartedLatch.await(EXPANDED_TIMEOUT_MS, TimeUnit.MILLISECONDS));
}
@ -501,15 +502,17 @@ public abstract class EthernetTetheringTestBase {
sCallbackErrors.add(error);
}
protected static MyTetheringEventCallback enableEthernetTethering(String iface,
protected static MyTetheringEventCallback enableTethering(String iface,
TetheringRequest request, Network expectedUpstream) throws Exception {
// Enable ethernet tethering with null expectedUpstream means the test accept any upstream
// after etherent tethering started.
// Enable tethering with null expectedUpstream means the test accept any upstream after
// tethering started.
final MyTetheringEventCallback callback;
if (expectedUpstream != null) {
callback = new MyTetheringEventCallback(iface, expectedUpstream);
callback =
new MyTetheringEventCallback(
request.getTetheringType(), iface, expectedUpstream);
} else {
callback = new MyTetheringEventCallback(iface);
callback = new MyTetheringEventCallback(request.getTetheringType(), iface);
}
runAsShell(NETWORK_SETTINGS, () -> {
sTm.registerTetheringEventCallback(c -> c.run() /* executor */, callback);
@ -521,7 +524,7 @@ public abstract class EthernetTetheringTestBase {
StartTetheringCallback startTetheringCallback = new StartTetheringCallback() {
@Override
public void onTetheringStarted() {
Log.d(TAG, "Ethernet tethering started");
Log.d(TAG, "Tethering started");
tetheringStartedLatch.countDown();
}
@ -530,8 +533,8 @@ public abstract class EthernetTetheringTestBase {
addCallbackError("Unexpectedly got onTetheringFailed");
}
};
Log.d(TAG, "Starting Ethernet tethering");
runAsShell(TETHER_PRIVILEGED, () -> {
Log.d(TAG, "Starting tethering");
runAsShell(TETHER_PRIVILEGED, NETWORK_SETTINGS, () -> {
sTm.startTethering(request, c -> c.run() /* executor */, startTetheringCallback);
// Binder call is an async call. Need to hold the shell permission until tethering
// started. This helps to avoid the test become flaky.
@ -557,7 +560,7 @@ public abstract class EthernetTetheringTestBase {
protected static MyTetheringEventCallback enableEthernetTethering(String iface,
Network expectedUpstream) throws Exception {
return enableEthernetTethering(iface,
return enableTethering(iface,
new TetheringRequest.Builder(TETHERING_ETHERNET)
.setShouldShowEntitlementUi(false).build(), expectedUpstream);
}

View file

@ -19,7 +19,9 @@ package android.net;
import static android.Manifest.permission.DUMP;
import static android.net.InetAddresses.parseNumericAddress;
import static android.net.TetheringManager.CONNECTIVITY_SCOPE_LOCAL;
import static android.net.TetheringManager.CONNECTIVITY_SCOPE_GLOBAL;
import static android.net.TetheringManager.TETHERING_ETHERNET;
import static android.net.TetheringManager.TETHERING_VIRTUAL;
import static android.net.TetheringTester.TestDnsPacket;
import static android.net.TetheringTester.buildIcmpEchoPacketV4;
import static android.net.TetheringTester.buildUdpPacket;
@ -236,7 +238,8 @@ public class EthernetTetheringTest extends EthernetTetheringTestBase {
downstreamReader = makePacketReader(fd, mtu);
tetheringEventCallback = enableEthernetTethering(downstreamIface.getInterfaceName(),
null /* any upstream */);
checkTetheredClientCallbacks(downstreamReader, tetheringEventCallback);
checkTetheredClientCallbacks(
downstreamReader, TETHERING_ETHERNET, tetheringEventCallback);
} finally {
maybeStopTapPacketReader(downstreamReader);
maybeCloseTestInterface(downstreamIface);
@ -267,7 +270,8 @@ public class EthernetTetheringTest extends EthernetTetheringTestBase {
downstreamReader = makePacketReader(fd, getMTU(downstreamIface));
tetheringEventCallback = enableEthernetTethering(downstreamIface.getInterfaceName(),
null /* any upstream */);
checkTetheredClientCallbacks(downstreamReader, tetheringEventCallback);
checkTetheredClientCallbacks(
downstreamReader, TETHERING_ETHERNET, tetheringEventCallback);
} finally {
maybeStopTapPacketReader(downstreamReader);
maybeCloseTestInterface(downstreamIface);
@ -302,7 +306,7 @@ public class EthernetTetheringTest extends EthernetTetheringTestBase {
final String localAddr = "192.0.2.3/28";
final String clientAddr = "192.0.2.2/28";
tetheringEventCallback = enableEthernetTethering(iface,
tetheringEventCallback = enableTethering(iface,
requestWithStaticIpv4(localAddr, clientAddr), null /* any upstream */);
tetheringEventCallback.awaitInterfaceTethered();
@ -368,8 +372,7 @@ public class EthernetTetheringTest extends EthernetTetheringTestBase {
final TetheringRequest request = new TetheringRequest.Builder(TETHERING_ETHERNET)
.setConnectivityScope(CONNECTIVITY_SCOPE_LOCAL).build();
tetheringEventCallback = enableEthernetTethering(iface, request,
null /* any upstream */);
tetheringEventCallback = enableTethering(iface, request, null /* any upstream */);
tetheringEventCallback.awaitInterfaceLocalOnly();
// makePacketReader only works after tethering is started, because until then the
@ -424,6 +427,7 @@ public class EthernetTetheringTest extends EthernetTetheringTestBase {
}
private void checkTetheredClientCallbacks(final PollPacketReader packetReader,
final int tetheringType,
final MyTetheringEventCallback tetheringEventCallback) throws Exception {
// Create a fake client.
byte[] clientMacAddr = new byte[6];
@ -438,7 +442,7 @@ public class EthernetTetheringTest extends EthernetTetheringTestBase {
// Check the MAC address.
assertEquals(MacAddress.fromBytes(clientMacAddr), client.getMacAddress());
assertEquals(TETHERING_ETHERNET, client.getTetheringType());
assertEquals(tetheringType, client.getTetheringType());
// Check the hostname.
assertEquals(1, client.getAddresses().size());
@ -475,8 +479,7 @@ public class EthernetTetheringTest extends EthernetTetheringTestBase {
private void assertInvalidStaticIpv4Request(String iface, String local, String client)
throws Exception {
try {
enableEthernetTethering(iface, requestWithStaticIpv4(local, client),
null /* any upstream */);
enableTethering(iface, requestWithStaticIpv4(local, client), null /* any upstream */);
fail("Unexpectedly accepted invalid IPv4 configuration: " + local + ", " + client);
} catch (IllegalArgumentException | NullPointerException expected) { }
}
@ -1180,4 +1183,32 @@ public class EthernetTetheringTest extends EthernetTetheringTestBase {
TX_UDP_PACKET_COUNT * (TX_UDP_PACKET_SIZE + IPV6_HEADER_LEN - IPV4_HEADER_MIN_LEN),
newEgress4.bytes - oldEgress4.bytes);
}
@Test
public void testTetheringVirtual() throws Exception {
assumeFalse(isInterfaceForTetheringAvailable());
setIncludeTestInterfaces(true);
TestNetworkInterface downstreamIface = null;
MyTetheringEventCallback tetheringEventCallback = null;
PollPacketReader downstreamReader = null;
try {
downstreamIface = createTestInterface();
String iface = downstreamIface.getInterfaceName();
final TetheringRequest request = new TetheringRequest.Builder(TETHERING_VIRTUAL)
.setConnectivityScope(CONNECTIVITY_SCOPE_GLOBAL)
.setInterfaceName(iface)
.build();
tetheringEventCallback = enableTethering(iface, request, null /* any upstream */);
FileDescriptor fd = downstreamIface.getFileDescriptor().getFileDescriptor();
downstreamReader = makePacketReader(fd, getMTU(downstreamIface));
checkTetheredClientCallbacks(
downstreamReader, TETHERING_VIRTUAL, tetheringEventCallback);
} finally {
maybeStopTapPacketReader(downstreamReader);
maybeCloseTestInterface(downstreamIface);
maybeUnregisterTetheringEventCallback(tetheringEventCallback);
}
}
}

View file

@ -17,9 +17,11 @@
package com.android.networkstack.tethering;
import static android.Manifest.permission.ACCESS_NETWORK_STATE;
import static android.Manifest.permission.NETWORK_SETTINGS;
import static android.Manifest.permission.TETHER_PRIVILEGED;
import static android.Manifest.permission.WRITE_SETTINGS;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.net.TetheringManager.TETHERING_VIRTUAL;
import static android.net.TetheringManager.TETHERING_WIFI;
import static android.net.TetheringManager.TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION;
import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION;
@ -171,6 +173,10 @@ public final class TetheringServiceTest {
runTetheringCall(test, false /* isTetheringAllowed */, TETHER_PRIVILEGED);
}
private void runAsNetworkSettings(final TestTetheringCall test) throws Exception {
runTetheringCall(test, true /* isTetheringAllowed */, NETWORK_SETTINGS, TETHER_PRIVILEGED);
}
private void runTetheringCall(final TestTetheringCall test, boolean isTetheringAllowed,
String... permissions) throws Exception {
// Allow the test to run even if ACCESS_NETWORK_STATE was granted at the APK level
@ -370,6 +376,32 @@ public final class TetheringServiceTest {
});
}
@Test
public void testStartTetheringWithInterfaceSucceeds() throws Exception {
final TetheringRequestParcel request = new TetheringRequestParcel();
request.tetheringType = TETHERING_VIRTUAL;
request.interfaceName = "avf_tap_fixed";
runAsNetworkSettings((result) -> {
runStartTethering(result, request);
verifyNoMoreInteractionsForTethering();
});
}
@Test
public void testStartTetheringNoNetworkStackPermissionWithInterfaceFails() throws Exception {
final TetheringRequestParcel request = new TetheringRequestParcel();
request.tetheringType = TETHERING_VIRTUAL;
request.interfaceName = "avf_tap_fixed";
runAsTetherPrivileged((result) -> {
mTetheringConnector.startTethering(request, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
result);
result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
verifyNoMoreInteractionsForTethering();
});
}
private void runStartTetheringAndVerifyNoPermission(final TestTetheringResult result)
throws Exception {
final TetheringRequestParcel request = new TetheringRequestParcel();

View file

@ -47,6 +47,7 @@ import static android.net.TetheringManager.TETHERING_BLUETOOTH;
import static android.net.TetheringManager.TETHERING_ETHERNET;
import static android.net.TetheringManager.TETHERING_NCM;
import static android.net.TetheringManager.TETHERING_USB;
import static android.net.TetheringManager.TETHERING_VIRTUAL;
import static android.net.TetheringManager.TETHERING_WIFI;
import static android.net.TetheringManager.TETHERING_WIFI_P2P;
import static android.net.TetheringManager.TETHER_ERROR_IFACE_CFG_ERROR;
@ -255,6 +256,7 @@ public class TetheringTest {
private static final String TEST_P2P_IFNAME = "test_p2p-p2p0-0";
private static final String TEST_NCM_IFNAME = "test_ncm0";
private static final String TEST_ETH_IFNAME = "test_eth0";
private static final String TEST_VIRT_IFNAME = "test_virt0";
private static final String TEST_BT_IFNAME = "test_pan0";
private static final String TETHERING_NAME = "Tethering";
private static final String[] PROVISIONING_APP_NAME = {"some", "app"};
@ -417,11 +419,12 @@ public class TetheringTest {
|| ifName.equals(TEST_P2P_IFNAME)
|| ifName.equals(TEST_NCM_IFNAME)
|| ifName.equals(TEST_ETH_IFNAME)
|| ifName.equals(TEST_BT_IFNAME));
|| ifName.equals(TEST_BT_IFNAME)
|| ifName.equals(TEST_VIRT_IFNAME));
final String[] ifaces = new String[] {
TEST_RNDIS_IFNAME, TEST_WLAN_IFNAME, TEST_WLAN2_IFNAME, TEST_WIFI_IFNAME,
TEST_MOBILE_IFNAME, TEST_DUN_IFNAME, TEST_P2P_IFNAME, TEST_NCM_IFNAME,
TEST_ETH_IFNAME};
TEST_ETH_IFNAME, TEST_VIRT_IFNAME};
return new InterfaceParams(ifName,
CollectionUtils.indexOf(ifaces, ifName) + IFINDEX_OFFSET,
MacAddress.ALL_ZEROS_ADDRESS);
@ -674,7 +677,8 @@ public class TetheringTest {
when(mNetd.interfaceGetList())
.thenReturn(new String[] {
TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_WLAN2_IFNAME, TEST_RNDIS_IFNAME,
TEST_P2P_IFNAME, TEST_NCM_IFNAME, TEST_ETH_IFNAME, TEST_BT_IFNAME});
TEST_P2P_IFNAME, TEST_NCM_IFNAME, TEST_ETH_IFNAME, TEST_BT_IFNAME,
TEST_VIRT_IFNAME});
when(mResources.getString(R.string.config_wifi_tether_enable)).thenReturn("");
mInterfaceConfiguration = new InterfaceConfigurationParcel();
mInterfaceConfiguration.flags = new String[0];
@ -765,12 +769,12 @@ public class TetheringTest {
}
private TetheringRequest createTetheringRequest(final int type) {
return createTetheringRequest(type, null, null, false, CONNECTIVITY_SCOPE_GLOBAL);
return createTetheringRequest(type, null, null, false, CONNECTIVITY_SCOPE_GLOBAL, null);
}
private TetheringRequest createTetheringRequest(final int type,
final LinkAddress localIPv4Address, final LinkAddress staticClientAddress,
final boolean exempt, final int scope) {
final boolean exempt, final int scope, final String interfaceName) {
TetheringRequest.Builder builder = new TetheringRequest.Builder(type)
.setExemptFromEntitlementCheck(exempt)
.setConnectivityScope(scope)
@ -778,6 +782,9 @@ public class TetheringTest {
if (localIPv4Address != null && staticClientAddress != null) {
builder.setStaticIpv4Addresses(localIPv4Address, staticClientAddress);
}
if (interfaceName != null) {
builder.setInterfaceName(interfaceName);
}
return builder.build();
}
@ -2782,7 +2789,7 @@ public class TetheringTest {
// Enable USB tethering with a different request and expect that USB is stopped and
// started.
mTethering.startTethering(createTetheringRequest(TETHERING_USB,
serverLinkAddr, clientLinkAddr, false, CONNECTIVITY_SCOPE_GLOBAL),
serverLinkAddr, clientLinkAddr, false, CONNECTIVITY_SCOPE_GLOBAL, null),
TEST_CALLER_PKG, thirdResult);
mLooper.dispatchAll();
thirdResult.assertHasResult();
@ -2813,7 +2820,7 @@ public class TetheringTest {
final ArgumentCaptor<DhcpServingParamsParcel> dhcpParamsCaptor =
ArgumentCaptor.forClass(DhcpServingParamsParcel.class);
mTethering.startTethering(createTetheringRequest(TETHERING_USB,
serverLinkAddr, clientLinkAddr, false, CONNECTIVITY_SCOPE_GLOBAL),
serverLinkAddr, clientLinkAddr, false, CONNECTIVITY_SCOPE_GLOBAL, null),
TEST_CALLER_PKG, null);
mLooper.dispatchAll();
verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_NCM);
@ -2942,7 +2949,7 @@ public class TetheringTest {
setupForRequiredProvisioning();
final TetheringRequest wifiNotExemptRequest =
createTetheringRequest(TETHERING_WIFI, null, null, false,
CONNECTIVITY_SCOPE_GLOBAL);
CONNECTIVITY_SCOPE_GLOBAL, null);
mTethering.startTethering(wifiNotExemptRequest, TEST_CALLER_PKG, null);
mLooper.dispatchAll();
verify(mEntitleMgr).startProvisioningIfNeeded(TETHERING_WIFI, false);
@ -2956,7 +2963,7 @@ public class TetheringTest {
setupForRequiredProvisioning();
final TetheringRequest wifiExemptRequest =
createTetheringRequest(TETHERING_WIFI, null, null, true,
CONNECTIVITY_SCOPE_GLOBAL);
CONNECTIVITY_SCOPE_GLOBAL, null);
mTethering.startTethering(wifiExemptRequest, TEST_CALLER_PKG, null);
mLooper.dispatchAll();
verify(mEntitleMgr, never()).startProvisioningIfNeeded(TETHERING_WIFI, false);
@ -3779,4 +3786,18 @@ public class TetheringTest {
// TODO: Test that a request for hotspot mode doesn't interfere with an
// already operating tethering mode interface.
@Test
public void testVirtualTetheringWithInterfaceName() throws Exception {
initTetheringOnTestThread();
final TetheringRequest virtualTetheringRequest =
createTetheringRequest(TETHERING_VIRTUAL, null, null, false,
CONNECTIVITY_SCOPE_GLOBAL, TEST_VIRT_IFNAME);
assertEquals(TEST_VIRT_IFNAME, virtualTetheringRequest.getInterfaceName());
mTethering.startTethering(virtualTetheringRequest, TEST_CALLER_PKG, null);
mLooper.dispatchAll();
assertContains(Arrays.asList(mTethering.getTetheredIfaces()), TEST_VIRT_IFNAME);
mTethering.stopTethering(TETHERING_VIRTUAL);
mLooper.dispatchAll();
}
}

View file

@ -92,7 +92,7 @@ class NsdManagerDownstreamTetheringTest : EthernetTetheringTestBase() {
assertEquals(downstreamIface.name, iface)
val request = TetheringRequest.Builder(TETHERING_ETHERNET)
.setConnectivityScope(CONNECTIVITY_SCOPE_LOCAL).build()
tetheringEventCallback = enableEthernetTethering(
tetheringEventCallback = enableTethering(
iface, request,
null /* any upstream */
).apply {
@ -125,7 +125,7 @@ class NsdManagerDownstreamTetheringTest : EthernetTetheringTestBase() {
val request = TetheringRequest.Builder(TETHERING_ETHERNET)
.setStaticIpv4Addresses(localAddr, clientAddr)
.setShouldShowEntitlementUi(false).build()
tetheringEventCallback = enableEthernetTethering(
tetheringEventCallback = enableTethering(
iface, request,
null /* any upstream */
).apply {

View file

@ -28,6 +28,7 @@ import static android.net.TetheringManager.TETHERING_BLUETOOTH;
import static android.net.TetheringManager.TETHERING_ETHERNET;
import static android.net.TetheringManager.TETHERING_NCM;
import static android.net.TetheringManager.TETHERING_USB;
import static android.net.TetheringManager.TETHERING_VIRTUAL;
import static android.net.TetheringManager.TETHERING_WIFI;
import static android.net.TetheringManager.TETHERING_WIFI_P2P;
import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN;
@ -303,6 +304,13 @@ public class TetheringManagerTest {
tr3.setUid(uid);
tr3.setPackageName(packageName);
assertEquals(tr2, tr3);
final String interfaceName = "test_iface";
final TetheringRequest tr4 = new TetheringRequest.Builder(TETHERING_VIRTUAL)
.setInterfaceName(interfaceName)
.setConnectivityScope(CONNECTIVITY_SCOPE_GLOBAL).build();
assertEquals(interfaceName, tr4.getInterfaceName());
assertEquals(CONNECTIVITY_SCOPE_GLOBAL, tr4.getConnectivityScope());
}
@Test
@ -319,24 +327,41 @@ public class TetheringManagerTest {
}
}
@Test
public void testTetheringRequestSetInterfaceNameFailsExceptTetheringVirtual() {
for (int type : List.of(TETHERING_USB, TETHERING_BLUETOOTH, TETHERING_NCM,
TETHERING_ETHERNET)) {
try {
new TetheringRequest.Builder(type).setInterfaceName("test_iface");
fail("Was able to set interface name for tethering type " + type);
} catch (IllegalArgumentException e) {
// Success
}
}
}
@Test
public void testTetheringRequestParcelable() {
final SoftApConfiguration softApConfiguration = createSoftApConfiguration("SSID");
final LinkAddress localAddr = new LinkAddress("192.168.24.5/24");
final LinkAddress clientAddr = new LinkAddress("192.168.24.100/24");
final TetheringRequest withConfig = new TetheringRequest.Builder(TETHERING_WIFI)
final TetheringRequest withApConfig = new TetheringRequest.Builder(TETHERING_WIFI)
.setSoftApConfiguration(softApConfiguration)
.setStaticIpv4Addresses(localAddr, clientAddr)
.setExemptFromEntitlementCheck(true)
.setShouldShowEntitlementUi(false).build();
final TetheringRequest withoutConfig = new TetheringRequest.Builder(TETHERING_WIFI)
final TetheringRequest withoutApConfig = new TetheringRequest.Builder(TETHERING_WIFI)
.setStaticIpv4Addresses(localAddr, clientAddr)
.setExemptFromEntitlementCheck(true)
.setShouldShowEntitlementUi(false).build();
assertEquals(withConfig, ParcelUtils.parcelingRoundTrip(withConfig));
assertEquals(withoutConfig, ParcelUtils.parcelingRoundTrip(withoutConfig));
assertNotEquals(withConfig, ParcelUtils.parcelingRoundTrip(withoutConfig));
assertNotEquals(withoutConfig, ParcelUtils.parcelingRoundTrip(withConfig));
assertEquals(withApConfig, ParcelUtils.parcelingRoundTrip(withApConfig));
assertEquals(withoutApConfig, ParcelUtils.parcelingRoundTrip(withoutApConfig));
assertNotEquals(withApConfig, ParcelUtils.parcelingRoundTrip(withoutApConfig));
assertNotEquals(withoutApConfig, ParcelUtils.parcelingRoundTrip(withApConfig));
final TetheringRequest withIfaceName = new TetheringRequest.Builder(TETHERING_VIRTUAL)
.setInterfaceName("test_iface").build();
assertEquals(withIfaceName, ParcelUtils.parcelingRoundTrip(withIfaceName));
}
@Test