Don't run hotspot related tests if Soft AP is not supported

Also explicitly hold ACCESS_WIFI_STATE permission to avoid
no permission problem when using WifiManager#getScanResults
without shell identity.

Fix: 169219565
Test: "atest CtsTetheringTest" in cuttlefish and phyical device

Change-Id: I3d8fa7e8882bf96f61f3316a70efdf991addbcb2
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 b18c1e7..c95dc28 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
@@ -28,7 +28,11 @@
 import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeTrue;
 
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
 import android.net.Network;
 import android.net.TetheredClient;
 import android.net.TetheringManager;
@@ -42,6 +46,7 @@
 
 import androidx.annotation.NonNull;
 
+import com.android.compatibility.common.util.SystemUtil;
 import com.android.net.module.util.ArrayTrackRecord;
 
 import java.util.Collection;
@@ -300,6 +305,26 @@
             }));
         }
 
+        public void assumeWifiTetheringSupported(final Context ctx) throws Exception {
+            assumeTetheringSupported();
+
+            assumeTrue(!getTetheringInterfaceRegexps().getTetherableWifiRegexs().isEmpty());
+
+            final PackageManager pm = ctx.getPackageManager();
+            assumeTrue(pm.hasSystemFeature(PackageManager.FEATURE_WIFI));
+
+            WifiManager wm = ctx.getSystemService(WifiManager.class);
+            // Wifi feature flags only work when wifi is on.
+            final boolean previousWifiEnabledState = wm.isWifiEnabled();
+            try {
+                if (!previousWifiEnabledState) SystemUtil.runShellCommand("svc wifi enable");
+                waitForWifiEnabled(ctx);
+                assumeTrue(wm.isPortableHotspotSupported());
+            } finally {
+                if (!previousWifiEnabledState) SystemUtil.runShellCommand("svc wifi disable");
+            }
+        }
+
         public TetheringInterfaceRegexps getTetheringInterfaceRegexps() {
             return mTetherableRegex;
         }
@@ -313,6 +338,31 @@
         }
     }
 
+    private static void waitForWifiEnabled(final Context ctx) throws Exception {
+        WifiManager wm = ctx.getSystemService(WifiManager.class);
+        if (wm.isWifiEnabled()) return;
+
+        final ConditionVariable mWaiting = new ConditionVariable();
+        final BroadcastReceiver receiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                String action = intent.getAction();
+                if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
+                    if (wm.isWifiEnabled()) mWaiting.open();
+                }
+            }
+        };
+        try {
+            ctx.registerReceiver(receiver, new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION));
+            if (!mWaiting.block(DEFAULT_TIMEOUT_MS)) {
+                assertTrue("Wifi did not become enabled after " + DEFAULT_TIMEOUT_MS + "ms",
+                        wm.isWifiEnabled());
+            }
+        } finally {
+            ctx.unregisterReceiver(receiver);
+        }
+    }
+
     public TestTetheringEventCallback registerTetheringEventCallback() {
         final TestTetheringEventCallback tetherEventCallback =
                 new TestTetheringEventCallback();
diff --git a/tests/cts/tethering/AndroidManifest.xml b/tests/cts/tethering/AndroidManifest.xml
index 665002e..911dbf2 100644
--- a/tests/cts/tethering/AndroidManifest.xml
+++ b/tests/cts/tethering/AndroidManifest.xml
@@ -19,6 +19,7 @@
     package="android.tethering.cts">
 
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
 
     <application android:debuggable="true">
         <uses-library android:name="android.test.runner" />
diff --git a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java b/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
index 397b4b8..71a81ff 100644
--- a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
+++ b/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
@@ -204,14 +204,15 @@
 
     @Test
     public void testStartTetheringWithStateChangeBroadcast() throws Exception {
-        if (!mTM.isTetheringSupported()) return;
+        final TestTetheringEventCallback tetherEventCallback =
+                mCtsTetheringUtils.registerTetheringEventCallback();
+        try {
+            tetherEventCallback.assumeWifiTetheringSupported(mContext);
+        } finally {
+            mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback);
+        }
 
         final String[] wifiRegexs = mTM.getTetherableWifiRegexs();
-        if (wifiRegexs.length == 0) return;
-
-        final String[] tetheredIfaces = mTM.getTetheredIfaces();
-        assertTrue(tetheredIfaces.length == 0);
-
         final StartTetheringCallback startTetheringCallback = new StartTetheringCallback();
         final TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI)
                 .setShouldShowEntitlementUi(false).build();
@@ -252,33 +253,31 @@
     public void testRegisterTetheringEventCallback() throws Exception {
         final TestTetheringEventCallback tetherEventCallback =
                 mCtsTetheringUtils.registerTetheringEventCallback();
-        tetherEventCallback.assumeTetheringSupported();
-
-        if (!isWifiTetheringSupported(tetherEventCallback)) {
-            mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback);
-            return;
-        }
-
-        mCtsTetheringUtils.startWifiTethering(tetherEventCallback);
-
-        final List<String> tetheredIfaces = tetherEventCallback.getTetheredInterfaces();
-        assertEquals(1, tetheredIfaces.size());
-        final String wifiTetheringIface = tetheredIfaces.get(0);
-
-        mCtsTetheringUtils.stopWifiTethering(tetherEventCallback);
 
         try {
-            final int ret = mTM.tether(wifiTetheringIface);
+            tetherEventCallback.assumeWifiTetheringSupported(mContext);
 
-            // There is no guarantee that the wifi interface will be available after disabling
-            // the hotspot, so don't fail the test if the call to tether() fails.
-            assumeTrue(ret == TETHER_ERROR_NO_ERROR);
+            mCtsTetheringUtils.startWifiTethering(tetherEventCallback);
 
-            // If calling #tether successful, there is a callback to tell the result of tethering
-            // setup.
-            tetherEventCallback.expectErrorOrTethered(wifiTetheringIface);
+            final List<String> tetheredIfaces = tetherEventCallback.getTetheredInterfaces();
+            assertEquals(1, tetheredIfaces.size());
+            final String wifiTetheringIface = tetheredIfaces.get(0);
+
+            mCtsTetheringUtils.stopWifiTethering(tetherEventCallback);
+
+            try {
+                final int ret = mTM.tether(wifiTetheringIface);
+                // There is no guarantee that the wifi interface will be available after disabling
+                // the hotspot, so don't fail the test if the call to tether() fails.
+                if (ret == TETHER_ERROR_NO_ERROR) {
+                    // If calling #tether successful, there is a callback to tell the result of
+                    // tethering setup.
+                    tetherEventCallback.expectErrorOrTethered(wifiTetheringIface);
+                }
+            } finally {
+                mTM.untether(wifiTetheringIface);
+            }
         } finally {
-            mTM.untether(wifiTetheringIface);
             mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback);
         }
     }
@@ -311,10 +310,8 @@
     public void testStopAllTethering() throws Exception {
         final TestTetheringEventCallback tetherEventCallback =
                 mCtsTetheringUtils.registerTetheringEventCallback();
-        tetherEventCallback.assumeTetheringSupported();
-
         try {
-            if (!isWifiTetheringSupported(tetherEventCallback)) return;
+            tetherEventCallback.assumeWifiTetheringSupported(mContext);
 
             // TODO: start ethernet tethering here when TetheringManagerTest is moved to
             // TetheringIntegrationTest.
@@ -415,12 +412,13 @@
         assumeTrue(mPm.hasSystemFeature(FEATURE_TELEPHONY));
         final TestTetheringEventCallback tetherEventCallback =
                 mCtsTetheringUtils.registerTetheringEventCallback();
-        tetherEventCallback.assumeTetheringSupported();
-        final boolean previousWifiEnabledState = mWm.isWifiEnabled();
+
+        boolean previousWifiEnabledState = false;
 
         try {
-            if (!isWifiTetheringSupported(tetherEventCallback)) return;
+            tetherEventCallback.assumeWifiTetheringSupported(mContext);
 
+            previousWifiEnabledState = mWm.isWifiEnabled();
             if (previousWifiEnabledState) {
                 mCtsNetUtils.ensureWifiDisconnected(null);
             }