Merge "Manual start tethering if it doesn't restart automatically"
diff --git a/Tethering/tests/mts/src/android/tethering/mts/TetheringModuleTest.java b/Tethering/tests/mts/src/android/tethering/mts/TetheringModuleTest.java
index 85ee466..dd2ff9e 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 @@
 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 @@
             final List<String> 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 d5e9c9e..8b904bc 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.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 TetheringInterface expectTetheredInterfacesChanged(
-                @NonNull final List<String> regexs, final int type) {
+        @Nullable
+        public TetheringInterface pollTetheredInterfacesChanged(
+                @NonNull final List<String> 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 @@
             }
         }
 
+        @NonNull
+        public TetheringInterface expectTetheredInterfacesChanged(
+                @NonNull final List<String> 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