diff --git a/Tethering/tests/mts/src/android/tethering/mts/TetheringModuleTest.java b/Tethering/tests/mts/src/android/tethering/mts/TetheringModuleTest.java index 85ee466d54..dd2ff9e031 100644 --- a/Tethering/tests/mts/src/android/tethering/mts/TetheringModuleTest.java +++ b/Tethering/tests/mts/src/android/tethering/mts/TetheringModuleTest.java @@ -56,6 +56,7 @@ import java.util.List; public class TetheringModuleTest { private Context mContext; private CtsTetheringUtils mCtsTetheringUtils; + private final long mRestartTimeOutMs = 5_000; @Before public void setUp() throws Exception { @@ -103,8 +104,20 @@ public class TetheringModuleTest { final List wifiRegexs = tetherEventCallback.getTetheringInterfaceRegexps().getTetherableWifiRegexs(); - tetherEventCallback.expectTetheredInterfacesChanged(wifiRegexs, TETHERING_WIFI); - nif = NetworkInterface.getByName(wifiTetheringIface); + final TetheringInterface restartedIface = + tetherEventCallback.pollTetheredInterfacesChanged(wifiRegexs, TETHERING_WIFI, + mRestartTimeOutMs); + final TetheringInterface newIface; + if (restartedIface != null) { + newIface = restartedIface; + } else { + // Because of race inside tethering module, there is no guarantee wifi tethering + // would restart successfully. If tethering don't auto restarted, restarting it + // manually. TODO(b/242649651): remove this when tethering auto restart is reliable. + newIface = mCtsTetheringUtils.startWifiTethering(tetherEventCallback); + } + + nif = NetworkInterface.getByName(newIface.getInterface()); final LinkAddress newHotspotAddr = getFirstIpv4Address(nif); assertNotNull(newHotspotAddr); diff --git a/tests/cts/net/util/java/android/net/cts/util/CtsTetheringUtils.java b/tests/cts/net/util/java/android/net/cts/util/CtsTetheringUtils.java index d5e9c9e43c..8b904bc3d6 100644 --- a/tests/cts/net/util/java/android/net/cts/util/CtsTetheringUtils.java +++ b/tests/cts/net/util/java/android/net/cts/util/CtsTetheringUtils.java @@ -52,6 +52,7 @@ import android.net.wifi.WifiManager.SoftApCallback; import android.os.ConditionVariable; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.android.compatibility.common.util.SystemUtil; import com.android.net.module.util.ArrayTrackRecord; @@ -296,13 +297,12 @@ public final class CtsTetheringUtils { })); } - public TetheringInterface expectTetheredInterfacesChanged( - @NonNull final List regexs, final int type) { + @Nullable + public TetheringInterface pollTetheredInterfacesChanged( + @NonNull final List regexs, final int type, long timeOutMs) { while (true) { - final CallbackValue cv = mCurrent.poll(TIMEOUT_MS, c -> true); - if (cv == null) { - fail("No expected tethered ifaces callback, expected type: " + type); - } + final CallbackValue cv = mCurrent.poll(timeOutMs, c -> true); + if (cv == null) return null; if (cv.callbackType != CallbackType.ON_TETHERED_IFACES) continue; @@ -316,6 +316,19 @@ public final class CtsTetheringUtils { } } + @NonNull + public TetheringInterface expectTetheredInterfacesChanged( + @NonNull final List regexs, final int type) { + final TetheringInterface iface = pollTetheredInterfacesChanged(regexs, type, + TIMEOUT_MS); + + if (iface == null) { + fail("No expected tethered ifaces callback, expected type: " + type); + } + + return iface; + } + 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