Test tethered callback with TetheringInterface
The old callback only report interface list, new callback could provide
the mapping of interface and type. Replace old callback usage in cts
with new callback and check whether old callback could get the correct
interface list by comparing the result between old and new callback.
Bug: 162920185
Bug: 152203943
Test: atest CtsTetheringTest on S
atest CtsTetheringTestLatestSdk on R
atest MtsTetheringTestLatestSdk on S and R
Ignore-AOSP-First: Its dependences CL is not in aosp currently.
Change-Id: I2a0b8c43fb340c3eaed7f0f90464199222a24280
This commit is contained in:
@@ -80,6 +80,7 @@ import java.nio.ByteBuffer;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@@ -349,7 +350,7 @@ public class EthernetTetheringTest {
|
|||||||
private final CountDownLatch mLocalOnlyStartedLatch = new CountDownLatch(1);
|
private final CountDownLatch mLocalOnlyStartedLatch = new CountDownLatch(1);
|
||||||
private final CountDownLatch mLocalOnlyStoppedLatch = new CountDownLatch(1);
|
private final CountDownLatch mLocalOnlyStoppedLatch = new CountDownLatch(1);
|
||||||
private final CountDownLatch mClientConnectedLatch = new CountDownLatch(1);
|
private final CountDownLatch mClientConnectedLatch = new CountDownLatch(1);
|
||||||
private final String mIface;
|
private final TetheringInterface mIface;
|
||||||
|
|
||||||
private volatile boolean mInterfaceWasTethered = false;
|
private volatile boolean mInterfaceWasTethered = false;
|
||||||
private volatile boolean mInterfaceWasLocalOnly = false;
|
private volatile boolean mInterfaceWasLocalOnly = false;
|
||||||
@@ -358,20 +359,24 @@ public class EthernetTetheringTest {
|
|||||||
|
|
||||||
MyTetheringEventCallback(TetheringManager tm, String iface) {
|
MyTetheringEventCallback(TetheringManager tm, String iface) {
|
||||||
mTm = tm;
|
mTm = tm;
|
||||||
mIface = iface;
|
mIface = new TetheringInterface(TETHERING_ETHERNET, iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unregister() {
|
public void unregister() {
|
||||||
mTm.unregisterTetheringEventCallback(this);
|
mTm.unregisterTetheringEventCallback(this);
|
||||||
mUnregistered = true;
|
mUnregistered = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTetheredInterfacesChanged(List<String> interfaces) {
|
public void onTetheredInterfacesChanged(List<String> interfaces) {
|
||||||
|
fail("Should only call callback that takes a Set<TetheringInterface>");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTetheredInterfacesChanged(Set<TetheringInterface> interfaces) {
|
||||||
// Ignore stale callbacks registered by previous test cases.
|
// Ignore stale callbacks registered by previous test cases.
|
||||||
if (mUnregistered) return;
|
if (mUnregistered) return;
|
||||||
|
|
||||||
if (!mInterfaceWasTethered && (mIface == null || interfaces.contains(mIface))) {
|
if (!mInterfaceWasTethered && interfaces.contains(mIface)) {
|
||||||
// This interface is being tethered for the first time.
|
// This interface is being tethered for the first time.
|
||||||
Log.d(TAG, "Tethering started: " + interfaces);
|
Log.d(TAG, "Tethering started: " + interfaces);
|
||||||
mInterfaceWasTethered = true;
|
mInterfaceWasTethered = true;
|
||||||
@@ -384,10 +389,15 @@ public class EthernetTetheringTest {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLocalOnlyInterfacesChanged(List<String> interfaces) {
|
public void onLocalOnlyInterfacesChanged(List<String> interfaces) {
|
||||||
|
fail("Should only call callback that takes a Set<TetheringInterface>");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLocalOnlyInterfacesChanged(Set<TetheringInterface> interfaces) {
|
||||||
// Ignore stale callbacks registered by previous test cases.
|
// Ignore stale callbacks registered by previous test cases.
|
||||||
if (mUnregistered) return;
|
if (mUnregistered) return;
|
||||||
|
|
||||||
if (!mInterfaceWasLocalOnly && (mIface == null || interfaces.contains(mIface))) {
|
if (!mInterfaceWasLocalOnly && interfaces.contains(mIface)) {
|
||||||
// This interface is being put into local-only mode for the first time.
|
// This interface is being put into local-only mode for the first time.
|
||||||
Log.d(TAG, "Local-only started: " + interfaces);
|
Log.d(TAG, "Local-only started: " + interfaces);
|
||||||
mInterfaceWasLocalOnly = true;
|
mInterfaceWasLocalOnly = true;
|
||||||
|
|||||||
@@ -20,12 +20,12 @@ import static android.Manifest.permission.NETWORK_SETTINGS;
|
|||||||
import static android.Manifest.permission.READ_DEVICE_CONFIG;
|
import static android.Manifest.permission.READ_DEVICE_CONFIG;
|
||||||
import static android.Manifest.permission.TETHER_PRIVILEGED;
|
import static android.Manifest.permission.TETHER_PRIVILEGED;
|
||||||
import static android.Manifest.permission.WRITE_SETTINGS;
|
import static android.Manifest.permission.WRITE_SETTINGS;
|
||||||
|
import static android.net.TetheringManager.TETHERING_WIFI;
|
||||||
import static android.net.cts.util.CtsTetheringUtils.isWifiTetheringSupported;
|
import static android.net.cts.util.CtsTetheringUtils.isWifiTetheringSupported;
|
||||||
import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
|
import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
|
||||||
|
|
||||||
import static com.android.testutils.TestNetworkTrackerKt.initTestNetwork;
|
import static com.android.testutils.TestNetworkTrackerKt.initTestNetwork;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
@@ -35,6 +35,7 @@ import android.app.UiAutomation;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.IpPrefix;
|
import android.net.IpPrefix;
|
||||||
import android.net.LinkAddress;
|
import android.net.LinkAddress;
|
||||||
|
import android.net.TetheringInterface;
|
||||||
import android.net.TetheringManager;
|
import android.net.TetheringManager;
|
||||||
import android.net.cts.util.CtsTetheringUtils;
|
import android.net.cts.util.CtsTetheringUtils;
|
||||||
import android.net.cts.util.CtsTetheringUtils.TestTetheringEventCallback;
|
import android.net.cts.util.CtsTetheringUtils.TestTetheringEventCallback;
|
||||||
@@ -102,12 +103,13 @@ public class TetheringModuleTest {
|
|||||||
try {
|
try {
|
||||||
tetherEventCallback.assumeTetheringSupported();
|
tetherEventCallback.assumeTetheringSupported();
|
||||||
assumeTrue(isWifiTetheringSupported(tetherEventCallback));
|
assumeTrue(isWifiTetheringSupported(tetherEventCallback));
|
||||||
|
tetherEventCallback.expectNoTetheringActive();
|
||||||
|
|
||||||
mCtsTetheringUtils.startWifiTethering(tetherEventCallback);
|
final TetheringInterface tetheredIface =
|
||||||
|
mCtsTetheringUtils.startWifiTethering(tetherEventCallback);
|
||||||
|
|
||||||
final List<String> tetheredIfaces = tetherEventCallback.getTetheredInterfaces();
|
assertNotNull(tetheredIface);
|
||||||
assertEquals(1, tetheredIfaces.size());
|
final String wifiTetheringIface = tetheredIface.getInterface();
|
||||||
final String wifiTetheringIface = tetheredIfaces.get(0);
|
|
||||||
|
|
||||||
NetworkInterface nif = NetworkInterface.getByName(wifiTetheringIface);
|
NetworkInterface nif = NetworkInterface.getByName(wifiTetheringIface);
|
||||||
// Tethering downstream only have one ipv4 address.
|
// Tethering downstream only have one ipv4 address.
|
||||||
@@ -120,11 +122,11 @@ public class TetheringModuleTest {
|
|||||||
tnt = setUpTestNetwork(
|
tnt = setUpTestNetwork(
|
||||||
new LinkAddress(testPrefix.getAddress(), testPrefix.getPrefixLength()));
|
new LinkAddress(testPrefix.getAddress(), testPrefix.getPrefixLength()));
|
||||||
|
|
||||||
tetherEventCallback.expectTetheredInterfacesChanged(null);
|
tetherEventCallback.expectNoTetheringActive();
|
||||||
final List<String> wifiRegexs =
|
final List<String> wifiRegexs =
|
||||||
tetherEventCallback.getTetheringInterfaceRegexps().getTetherableWifiRegexs();
|
tetherEventCallback.getTetheringInterfaceRegexps().getTetherableWifiRegexs();
|
||||||
|
|
||||||
tetherEventCallback.expectTetheredInterfacesChanged(wifiRegexs);
|
tetherEventCallback.expectTetheredInterfacesChanged(wifiRegexs, TETHERING_WIFI);
|
||||||
nif = NetworkInterface.getByName(wifiTetheringIface);
|
nif = NetworkInterface.getByName(wifiTetheringIface);
|
||||||
final LinkAddress newHotspotAddr = getFirstIpv4Address(nif);
|
final LinkAddress newHotspotAddr = getFirstIpv4Address(nif);
|
||||||
assertNotNull(newHotspotAddr);
|
assertNotNull(newHotspotAddr);
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ 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_STARTED;
|
||||||
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED;
|
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED;
|
||||||
|
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
@@ -35,6 +35,7 @@ import android.content.IntentFilter;
|
|||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.net.Network;
|
import android.net.Network;
|
||||||
import android.net.TetheredClient;
|
import android.net.TetheredClient;
|
||||||
|
import android.net.TetheringInterface;
|
||||||
import android.net.TetheringManager;
|
import android.net.TetheringManager;
|
||||||
import android.net.TetheringManager.TetheringEventCallback;
|
import android.net.TetheringManager.TetheringEventCallback;
|
||||||
import android.net.TetheringManager.TetheringInterfaceRegexps;
|
import android.net.TetheringManager.TetheringInterfaceRegexps;
|
||||||
@@ -51,6 +52,7 @@ import com.android.net.module.util.ArrayTrackRecord;
|
|||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public final class CtsTetheringUtils {
|
public final class CtsTetheringUtils {
|
||||||
private TetheringManager mTm;
|
private TetheringManager mTm;
|
||||||
@@ -116,23 +118,38 @@ public final class CtsTetheringUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isIfaceMatch(final List<String> ifaceRegexs, final List<String> ifaces) {
|
private static boolean isRegexMatch(final String[] ifaceRegexs, String iface) {
|
||||||
return isIfaceMatch(ifaceRegexs.toArray(new String[0]), ifaces);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isIfaceMatch(final String[] ifaceRegexs, final List<String> ifaces) {
|
|
||||||
if (ifaceRegexs == null) fail("ifaceRegexs should not be null");
|
if (ifaceRegexs == null) fail("ifaceRegexs should not be null");
|
||||||
|
|
||||||
|
for (String regex : ifaceRegexs) {
|
||||||
|
if (iface.matches(regex)) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isAnyIfaceMatch(final String[] ifaceRegexs, final List<String> ifaces) {
|
||||||
if (ifaces == null) return false;
|
if (ifaces == null) return false;
|
||||||
|
|
||||||
for (String s : ifaces) {
|
for (String s : ifaces) {
|
||||||
for (String regex : ifaceRegexs) {
|
if (isRegexMatch(ifaceRegexs, s)) return true;
|
||||||
if (s.matches(regex)) {
|
}
|
||||||
return true;
|
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TetheringInterface getFirstMatchingTetheringInterface(final List<String> regexs,
|
||||||
|
final int type, final Set<TetheringInterface> ifaces) {
|
||||||
|
if (ifaces == null || regexs == null) return null;
|
||||||
|
|
||||||
|
final String[] regexArray = regexs.toArray(new String[0]);
|
||||||
|
for (TetheringInterface iface : ifaces) {
|
||||||
|
if (isRegexMatch(regexArray, iface.getInterface()) && type == iface.getType()) {
|
||||||
|
return iface;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Must poll the callback before looking at the member.
|
// Must poll the callback before looking at the member.
|
||||||
@@ -171,6 +188,8 @@ public final class CtsTetheringUtils {
|
|||||||
private TetheringInterfaceRegexps mTetherableRegex;
|
private TetheringInterfaceRegexps mTetherableRegex;
|
||||||
private List<String> mTetherableIfaces;
|
private List<String> mTetherableIfaces;
|
||||||
private List<String> mTetheredIfaces;
|
private List<String> mTetheredIfaces;
|
||||||
|
private String mErrorIface;
|
||||||
|
private int mErrorCode;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTetheringSupported(boolean supported) {
|
public void onTetheringSupported(boolean supported) {
|
||||||
@@ -191,17 +210,41 @@ public final class CtsTetheringUtils {
|
|||||||
@Override
|
@Override
|
||||||
public void onTetherableInterfacesChanged(List<String> interfaces) {
|
public void onTetherableInterfacesChanged(List<String> interfaces) {
|
||||||
mTetherableIfaces = interfaces;
|
mTetherableIfaces = interfaces;
|
||||||
|
}
|
||||||
|
// Call the interface default implementation, which will call
|
||||||
|
// onTetherableInterfacesChanged(List<String>). This ensures that the default implementation
|
||||||
|
// of the new callback method calls the old callback method and avoids the need to convert
|
||||||
|
// Set<TetheringInterface> to List<String> in this code.
|
||||||
|
@Override
|
||||||
|
public void onTetherableInterfacesChanged(Set<TetheringInterface> interfaces) {
|
||||||
|
TetheringEventCallback.super.onTetherableInterfacesChanged(interfaces);
|
||||||
|
assertHasAllTetheringInterfaces(interfaces, mTetherableIfaces);
|
||||||
mHistory.add(new CallbackValue(CallbackType.ON_TETHERABLE_IFACES, interfaces, 0));
|
mHistory.add(new CallbackValue(CallbackType.ON_TETHERABLE_IFACES, interfaces, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTetheredInterfacesChanged(List<String> interfaces) {
|
public void onTetheredInterfacesChanged(List<String> interfaces) {
|
||||||
mTetheredIfaces = interfaces;
|
mTetheredIfaces = interfaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTetheredInterfacesChanged(Set<TetheringInterface> interfaces) {
|
||||||
|
TetheringEventCallback.super.onTetheredInterfacesChanged(interfaces);
|
||||||
|
assertHasAllTetheringInterfaces(interfaces, mTetheredIfaces);
|
||||||
mHistory.add(new CallbackValue(CallbackType.ON_TETHERED_IFACES, interfaces, 0));
|
mHistory.add(new CallbackValue(CallbackType.ON_TETHERED_IFACES, interfaces, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(String ifName, int error) {
|
public void onError(String ifName, int error) {
|
||||||
|
mErrorIface = ifName;
|
||||||
|
mErrorCode = error;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(TetheringInterface ifName, int error) {
|
||||||
|
TetheringEventCallback.super.onError(ifName, error);
|
||||||
|
assertEquals(ifName.getInterface(), mErrorIface);
|
||||||
|
assertEquals(error, mErrorCode);
|
||||||
mHistory.add(new CallbackValue(CallbackType.ON_ERROR, ifName, error));
|
mHistory.add(new CallbackValue(CallbackType.ON_ERROR, ifName, error));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,30 +258,66 @@ public final class CtsTetheringUtils {
|
|||||||
mHistory.add(new CallbackValue(CallbackType.ON_OFFLOAD_STATUS, status, 0));
|
mHistory.add(new CallbackValue(CallbackType.ON_OFFLOAD_STATUS, status, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void expectTetherableInterfacesChanged(@NonNull List<String> regexs) {
|
private void assertHasAllTetheringInterfaces(Set<TetheringInterface> tetheringIfaces,
|
||||||
|
List<String> ifaces) {
|
||||||
|
// This does not check that the interfaces are the same. This checks that the
|
||||||
|
// List<String> has all the interface names contained by the Set<TetheringInterface>.
|
||||||
|
assertEquals(tetheringIfaces.size(), ifaces.size());
|
||||||
|
for (TetheringInterface tether : tetheringIfaces) {
|
||||||
|
assertTrue("iface " + tether.getInterface()
|
||||||
|
+ " seen by new callback but not old callback",
|
||||||
|
ifaces.contains(tether.getInterface()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void expectTetherableInterfacesChanged(@NonNull final List<String> regexs,
|
||||||
|
final int type) {
|
||||||
assertNotNull("No expected tetherable ifaces callback", mCurrent.poll(TIMEOUT_MS,
|
assertNotNull("No expected tetherable ifaces callback", mCurrent.poll(TIMEOUT_MS,
|
||||||
(cv) -> {
|
(cv) -> {
|
||||||
if (cv.callbackType != CallbackType.ON_TETHERABLE_IFACES) return false;
|
if (cv.callbackType != CallbackType.ON_TETHERABLE_IFACES) return false;
|
||||||
final List<String> interfaces = (List<String>) cv.callbackParam;
|
final Set<TetheringInterface> interfaces =
|
||||||
return isIfaceMatch(regexs, interfaces);
|
(Set<TetheringInterface>) cv.callbackParam;
|
||||||
|
return getFirstMatchingTetheringInterface(regexs, type, interfaces) != null;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void expectTetheredInterfacesChanged(@NonNull List<String> regexs) {
|
public void expectNoTetheringActive() {
|
||||||
assertNotNull("No expected tethered ifaces callback", mCurrent.poll(TIMEOUT_MS,
|
assertNotNull("At least one tethering type unexpectedly active",
|
||||||
(cv) -> {
|
mCurrent.poll(TIMEOUT_MS, (cv) -> {
|
||||||
if (cv.callbackType != CallbackType.ON_TETHERED_IFACES) return false;
|
if (cv.callbackType != CallbackType.ON_TETHERED_IFACES) return false;
|
||||||
|
|
||||||
final List<String> interfaces = (List<String>) cv.callbackParam;
|
return ((Set<TetheringInterface>) cv.callbackParam).isEmpty();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
// Null regexs means no active tethering.
|
public TetheringInterface expectTetheredInterfacesChanged(
|
||||||
if (regexs == null) return interfaces.isEmpty();
|
@NonNull final List<String> regexs, final int type) {
|
||||||
|
while (true) {
|
||||||
|
final CallbackValue cv = mCurrent.poll(TIMEOUT_MS, c -> true);
|
||||||
|
if (cv == null) {
|
||||||
|
fail("No expected tethered ifaces callback, expected type: " + type);
|
||||||
|
}
|
||||||
|
|
||||||
return isIfaceMatch(regexs, interfaces);
|
if (cv.callbackType != CallbackType.ON_TETHERED_IFACES) continue;
|
||||||
}));
|
|
||||||
|
final Set<TetheringInterface> interfaces =
|
||||||
|
(Set<TetheringInterface>) cv.callbackParam;
|
||||||
|
|
||||||
|
final TetheringInterface iface =
|
||||||
|
getFirstMatchingTetheringInterface(regexs, type, interfaces);
|
||||||
|
|
||||||
|
if (iface != null) return iface;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void expectCallbackStarted() {
|
public void expectCallbackStarted() {
|
||||||
|
// This method uses its own readhead because it just check whether last tethering status
|
||||||
|
// is updated after TetheringEventCallback get registered but do not check content
|
||||||
|
// of received callbacks. Using shared readhead (mCurrent) only when the callbacks the
|
||||||
|
// method polled is also not necessary for other methods which using shared readhead.
|
||||||
|
// All of methods using mCurrent is order mattered.
|
||||||
|
final ArrayTrackRecord<CallbackValue>.ReadHead history =
|
||||||
|
mHistory.newReadHead();
|
||||||
int receivedBitMap = 0;
|
int receivedBitMap = 0;
|
||||||
// The each bit represent a type from CallbackType.ON_*.
|
// The each bit represent a type from CallbackType.ON_*.
|
||||||
// Expect all of callbacks except for ON_ERROR.
|
// Expect all of callbacks except for ON_ERROR.
|
||||||
@@ -246,7 +325,7 @@ public final class CtsTetheringUtils {
|
|||||||
// Receive ON_ERROR on started callback is not matter. It just means tethering is
|
// Receive ON_ERROR on started callback is not matter. It just means tethering is
|
||||||
// failed last time, should able to continue the test this time.
|
// failed last time, should able to continue the test this time.
|
||||||
while ((receivedBitMap & expectedBitMap) != expectedBitMap) {
|
while ((receivedBitMap & expectedBitMap) != expectedBitMap) {
|
||||||
final CallbackValue cv = mCurrent.poll(TIMEOUT_MS, c -> true);
|
final CallbackValue cv = history.poll(TIMEOUT_MS, c -> true);
|
||||||
if (cv == null) {
|
if (cv == null) {
|
||||||
fail("No expected callbacks, " + "expected bitmap: "
|
fail("No expected callbacks, " + "expected bitmap: "
|
||||||
+ expectedBitMap + ", actual: " + receivedBitMap);
|
+ expectedBitMap + ", actual: " + receivedBitMap);
|
||||||
@@ -269,14 +348,14 @@ public final class CtsTetheringUtils {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void expectErrorOrTethered(final String iface) {
|
public void expectErrorOrTethered(final TetheringInterface iface) {
|
||||||
assertNotNull("No expected callback", mCurrent.poll(TIMEOUT_MS, (cv) -> {
|
assertNotNull("No expected callback", mCurrent.poll(TIMEOUT_MS, (cv) -> {
|
||||||
if (cv.callbackType == CallbackType.ON_ERROR
|
if (cv.callbackType == CallbackType.ON_ERROR
|
||||||
&& iface.equals((String) cv.callbackParam)) {
|
&& iface.equals((TetheringInterface) cv.callbackParam)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (cv.callbackType == CallbackType.ON_TETHERED_IFACES
|
if (cv.callbackType == CallbackType.ON_TETHERED_IFACES
|
||||||
&& ((List<String>) cv.callbackParam).contains(iface)) {
|
&& ((Set<TetheringInterface>) cv.callbackParam).contains(iface)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,14 +407,6 @@ public final class CtsTetheringUtils {
|
|||||||
public TetheringInterfaceRegexps getTetheringInterfaceRegexps() {
|
public TetheringInterfaceRegexps getTetheringInterfaceRegexps() {
|
||||||
return mTetherableRegex;
|
return mTetherableRegex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getTetherableInterfaces() {
|
|
||||||
return mTetherableIfaces;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getTetheredInterfaces() {
|
|
||||||
return mTetheredIfaces;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void waitForWifiEnabled(final Context ctx) throws Exception {
|
private static void waitForWifiEnabled(final Context ctx) throws Exception {
|
||||||
@@ -386,10 +457,9 @@ public final class CtsTetheringUtils {
|
|||||||
return !getWifiTetherableInterfaceRegexps(callback).isEmpty();
|
return !getWifiTetherableInterfaceRegexps(callback).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startWifiTethering(final TestTetheringEventCallback callback)
|
public TetheringInterface startWifiTethering(final TestTetheringEventCallback callback)
|
||||||
throws InterruptedException {
|
throws InterruptedException {
|
||||||
final List<String> wifiRegexs = getWifiTetherableInterfaceRegexps(callback);
|
final List<String> wifiRegexs = getWifiTetherableInterfaceRegexps(callback);
|
||||||
assertFalse(isIfaceMatch(wifiRegexs, callback.getTetheredInterfaces()));
|
|
||||||
|
|
||||||
final StartTetheringCallback startTetheringCallback = new StartTetheringCallback();
|
final StartTetheringCallback startTetheringCallback = new StartTetheringCallback();
|
||||||
final TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI)
|
final TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI)
|
||||||
@@ -397,11 +467,14 @@ public final class CtsTetheringUtils {
|
|||||||
mTm.startTethering(request, c -> c.run() /* executor */, startTetheringCallback);
|
mTm.startTethering(request, c -> c.run() /* executor */, startTetheringCallback);
|
||||||
startTetheringCallback.verifyTetheringStarted();
|
startTetheringCallback.verifyTetheringStarted();
|
||||||
|
|
||||||
callback.expectTetheredInterfacesChanged(wifiRegexs);
|
final TetheringInterface iface =
|
||||||
|
callback.expectTetheredInterfacesChanged(wifiRegexs, TETHERING_WIFI);
|
||||||
|
|
||||||
callback.expectOneOfOffloadStatusChanged(
|
callback.expectOneOfOffloadStatusChanged(
|
||||||
TETHER_HARDWARE_OFFLOAD_STARTED,
|
TETHER_HARDWARE_OFFLOAD_STARTED,
|
||||||
TETHER_HARDWARE_OFFLOAD_FAILED);
|
TETHER_HARDWARE_OFFLOAD_FAILED);
|
||||||
|
|
||||||
|
return iface;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class StopSoftApCallback implements SoftApCallback {
|
private static class StopSoftApCallback implements SoftApCallback {
|
||||||
@@ -441,7 +514,7 @@ public final class CtsTetheringUtils {
|
|||||||
public void stopWifiTethering(final TestTetheringEventCallback callback) {
|
public void stopWifiTethering(final TestTetheringEventCallback callback) {
|
||||||
mTm.stopTethering(TETHERING_WIFI);
|
mTm.stopTethering(TETHERING_WIFI);
|
||||||
expectSoftApDisabled();
|
expectSoftApDisabled();
|
||||||
callback.expectTetheredInterfacesChanged(null);
|
callback.expectNoTetheringActive();
|
||||||
callback.expectOneOfOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
|
callback.expectOneOfOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,8 +26,7 @@ import static android.net.TetheringManager.TETHERING_WIFI_P2P;
|
|||||||
import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN;
|
import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN;
|
||||||
import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION;
|
import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION;
|
||||||
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
|
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
|
||||||
import static android.net.cts.util.CtsTetheringUtils.isIfaceMatch;
|
import static android.net.cts.util.CtsTetheringUtils.isAnyIfaceMatch;
|
||||||
import static android.net.cts.util.CtsTetheringUtils.isWifiTetheringSupported;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
@@ -48,6 +47,7 @@ import android.net.ConnectivityManager;
|
|||||||
import android.net.LinkAddress;
|
import android.net.LinkAddress;
|
||||||
import android.net.Network;
|
import android.net.Network;
|
||||||
import android.net.NetworkCapabilities;
|
import android.net.NetworkCapabilities;
|
||||||
|
import android.net.TetheringInterface;
|
||||||
import android.net.TetheringManager;
|
import android.net.TetheringManager;
|
||||||
import android.net.TetheringManager.OnTetheringEntitlementResultListener;
|
import android.net.TetheringManager.OnTetheringEntitlementResultListener;
|
||||||
import android.net.TetheringManager.TetheringInterfaceRegexps;
|
import android.net.TetheringManager.TetheringInterfaceRegexps;
|
||||||
@@ -190,13 +190,13 @@ public class TetheringManagerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isIfaceActive(final String[] ifaceRegexs, final TetherState state) {
|
private boolean isIfaceActive(final String[] ifaceRegexs, final TetherState state) {
|
||||||
return isIfaceMatch(ifaceRegexs, state.mActive);
|
return isAnyIfaceMatch(ifaceRegexs, state.mActive);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertNoErroredIfaces(final TetherState state, final String[] ifaceRegexs) {
|
private void assertNoErroredIfaces(final TetherState state, final String[] ifaceRegexs) {
|
||||||
if (state == null || state.mErrored == null) return;
|
if (state == null || state.mErrored == null) return;
|
||||||
|
|
||||||
if (isIfaceMatch(ifaceRegexs, state.mErrored)) {
|
if (isAnyIfaceMatch(ifaceRegexs, state.mErrored)) {
|
||||||
fail("Found failed tethering interfaces: " + Arrays.toString(state.mErrored.toArray()));
|
fail("Found failed tethering interfaces: " + Arrays.toString(state.mErrored.toArray()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -256,12 +256,13 @@ public class TetheringManagerTest {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
tetherEventCallback.assumeWifiTetheringSupported(mContext);
|
tetherEventCallback.assumeWifiTetheringSupported(mContext);
|
||||||
|
tetherEventCallback.expectNoTetheringActive();
|
||||||
|
|
||||||
mCtsTetheringUtils.startWifiTethering(tetherEventCallback);
|
final TetheringInterface tetheredIface =
|
||||||
|
mCtsTetheringUtils.startWifiTethering(tetherEventCallback);
|
||||||
|
|
||||||
final List<String> tetheredIfaces = tetherEventCallback.getTetheredInterfaces();
|
assertNotNull(tetheredIface);
|
||||||
assertEquals(1, tetheredIfaces.size());
|
final String wifiTetheringIface = tetheredIface.getInterface();
|
||||||
final String wifiTetheringIface = tetheredIfaces.get(0);
|
|
||||||
|
|
||||||
mCtsTetheringUtils.stopWifiTethering(tetherEventCallback);
|
mCtsTetheringUtils.stopWifiTethering(tetherEventCallback);
|
||||||
|
|
||||||
@@ -272,7 +273,8 @@ public class TetheringManagerTest {
|
|||||||
if (ret == TETHER_ERROR_NO_ERROR) {
|
if (ret == TETHER_ERROR_NO_ERROR) {
|
||||||
// If calling #tether successful, there is a callback to tell the result of
|
// If calling #tether successful, there is a callback to tell the result of
|
||||||
// tethering setup.
|
// tethering setup.
|
||||||
tetherEventCallback.expectErrorOrTethered(wifiTetheringIface);
|
tetherEventCallback.expectErrorOrTethered(
|
||||||
|
new TetheringInterface(TETHERING_WIFI, wifiTetheringIface));
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
mTM.untether(wifiTetheringIface);
|
mTM.untether(wifiTetheringIface);
|
||||||
@@ -319,7 +321,7 @@ public class TetheringManagerTest {
|
|||||||
mCtsTetheringUtils.startWifiTethering(tetherEventCallback);
|
mCtsTetheringUtils.startWifiTethering(tetherEventCallback);
|
||||||
|
|
||||||
mTM.stopAllTethering();
|
mTM.stopAllTethering();
|
||||||
tetherEventCallback.expectTetheredInterfacesChanged(null);
|
tetherEventCallback.expectNoTetheringActive();
|
||||||
} finally {
|
} finally {
|
||||||
mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback);
|
mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback);
|
||||||
}
|
}
|
||||||
@@ -417,6 +419,7 @@ public class TetheringManagerTest {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
tetherEventCallback.assumeWifiTetheringSupported(mContext);
|
tetherEventCallback.assumeWifiTetheringSupported(mContext);
|
||||||
|
tetherEventCallback.expectNoTetheringActive();
|
||||||
|
|
||||||
previousWifiEnabledState = mWm.isWifiEnabled();
|
previousWifiEnabledState = mWm.isWifiEnabled();
|
||||||
if (previousWifiEnabledState) {
|
if (previousWifiEnabledState) {
|
||||||
|
|||||||
Reference in New Issue
Block a user