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:
parent
dd87fb0d06
commit
eab1de47f4
11 changed files with 229 additions and 53 deletions
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,4 +33,5 @@ parcelable TetheringRequestParcel {
|
|||
SoftApConfiguration softApConfig;
|
||||
int uid;
|
||||
String packageName;
|
||||
String interfaceName;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue