Merge "Add config for Wi-Fi Hotspot Settings hidden" into tm-qpr-dev
diff --git a/res/values/config.xml b/res/values/config.xml
index ab7305f..93d82a8 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -331,6 +331,9 @@
     surface in search results or not.-->
     <bool name="config_show_wifi_settings">true</bool>
 
+    <!-- Whether Wi-Fi hotspot settings should be shown or not. -->
+    <bool name="config_show_wifi_hotspot_settings">true</bool>
+
     <!-- Whether toggle_airplane is available or not. -->
     <bool name="config_show_toggle_airplane">true</bool>
 
diff --git a/src/com/android/settings/wifi/WifiUtils.java b/src/com/android/settings/wifi/WifiUtils.java
index 4b94c81..a9010ac 100644
--- a/src/com/android/settings/wifi/WifiUtils.java
+++ b/src/com/android/settings/wifi/WifiUtils.java
@@ -22,14 +22,20 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.net.NetworkCapabilities;
+import android.net.TetheringManager;
 import android.net.wifi.ScanResult;
 import android.net.wifi.SoftApConfiguration;
 import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
 import android.text.TextUtils;
+import android.util.Log;
 
+import androidx.annotation.VisibleForTesting;
+
+import com.android.settings.R;
 import com.android.settings.Utils;
 import com.android.wifitrackerlib.WifiEntry;
 
@@ -38,12 +44,16 @@
 /** A utility class for Wi-Fi functions. */
 public class WifiUtils extends com.android.settingslib.wifi.WifiUtils {
 
+    static final String TAG = "WifiUtils";
+
     private static final int SSID_ASCII_MIN_LENGTH = 1;
     private static final int SSID_ASCII_MAX_LENGTH = 32;
 
     private static final int PSK_PASSPHRASE_ASCII_MIN_LENGTH = 8;
     private static final int PSK_PASSPHRASE_ASCII_MAX_LENGTH = 63;
 
+    private static Boolean sCanShowWifiHotspotCached;
+
     public static boolean isSSIDTooLong(String ssid) {
         if (TextUtils.isEmpty(ssid)) {
             return false;
@@ -240,4 +250,62 @@
 
         return WifiEntry.SECURITY_NONE;
     }
+
+    /**
+     * Check if Wi-Fi hotspot settings can be displayed.
+     *
+     * @param context Context of caller
+     * @return true if Wi-Fi hotspot settings can be displayed
+     */
+    public static boolean checkShowWifiHotspot(Context context) {
+        if (context == null) return false;
+
+        boolean showWifiHotspotSettings =
+                context.getResources().getBoolean(R.bool.config_show_wifi_hotspot_settings);
+        if (!showWifiHotspotSettings) {
+            Log.w(TAG, "config_show_wifi_hotspot_settings:false");
+            return false;
+        }
+
+        WifiManager wifiManager = context.getSystemService(WifiManager.class);
+        if (wifiManager == null) {
+            Log.e(TAG, "WifiManager is null");
+            return false;
+        }
+
+        TetheringManager tetheringManager = context.getSystemService(TetheringManager.class);
+        if (tetheringManager == null) {
+            Log.e(TAG, "TetheringManager is null");
+            return false;
+        }
+        String[] wifiRegexs = tetheringManager.getTetherableWifiRegexs();
+        if (wifiRegexs == null || wifiRegexs.length == 0) {
+            Log.w(TAG, "TetherableWifiRegexs is empty");
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Return the cached result to see if Wi-Fi hotspot settings can be displayed.
+     *
+     * @param context Context of caller
+     * @return true if Wi-Fi hotspot settings can be displayed
+     */
+    public static boolean canShowWifiHotspot(Context context) {
+        if (sCanShowWifiHotspotCached == null) {
+            sCanShowWifiHotspotCached = checkShowWifiHotspot(context);
+        }
+        return sCanShowWifiHotspotCached;
+    }
+
+    /**
+     * Sets the sCanShowWifiHotspotCached for testing purposes.
+     *
+     * @param cached Cached value for #canShowWifiHotspot()
+     */
+    @VisibleForTesting
+    public static void setCanShowWifiHotspotCached(Boolean cached) {
+        sCanShowWifiHotspotCached = cached;
+    }
 }
diff --git a/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java
index 73ff31d..a9c3559 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java
@@ -16,9 +16,10 @@
 
 package com.android.settings.wifi.tether;
 
+import static com.android.settings.wifi.WifiUtils.canShowWifiHotspot;
+
 import android.annotation.NonNull;
 import android.content.Context;
-import android.net.TetheringManager;
 import android.net.wifi.SoftApConfiguration;
 import android.net.wifi.WifiClient;
 import android.net.wifi.WifiManager;
@@ -46,7 +47,6 @@
 
     private static final String WIFI_TETHER_SETTINGS = "wifi_tether";
 
-    private boolean mIsWifiTetherable;
     private WifiManager mWifiManager;
     private boolean mIsWifiTetheringAllow;
     private int mSoftApState;
@@ -57,8 +57,7 @@
 
     public WifiTetherPreferenceController(Context context, Lifecycle lifecycle) {
         this(context, lifecycle,
-                context.getSystemService(WifiManager.class),
-                context.getSystemService(TetheringManager.class),
+                context.getApplicationContext().getSystemService(WifiManager.class),
                 true /* initSoftApManager */,
                 WifiEnterpriseRestrictionUtils.isWifiTetheringAllowed(context));
     }
@@ -68,15 +67,9 @@
             Context context,
             Lifecycle lifecycle,
             WifiManager wifiManager,
-            TetheringManager tetheringManager,
             boolean initSoftApManager,
             boolean isWifiTetheringAllow) {
         super(context);
-        final String[] wifiRegexs = tetheringManager.getTetherableWifiRegexs();
-        if (wifiRegexs != null && wifiRegexs.length != 0) {
-            mIsWifiTetherable = true;
-        }
-
         mIsWifiTetheringAllow = isWifiTetheringAllow;
         if (!isWifiTetheringAllow) return;
 
@@ -92,7 +85,7 @@
 
     @Override
     public boolean isAvailable() {
-        return mIsWifiTetherable && !Utils.isMonkeyRunning();
+        return canShowWifiHotspot(mContext) && !Utils.isMonkeyRunning();
     }
 
     @Override
diff --git a/src/com/android/settings/wifi/tether/WifiTetherSettings.java b/src/com/android/settings/wifi/tether/WifiTetherSettings.java
index e6b4bd6..1ff7746 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherSettings.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherSettings.java
@@ -18,6 +18,8 @@
 
 import static android.net.wifi.WifiManager.WIFI_AP_STATE_CHANGED_ACTION;
 
+import static com.android.settings.wifi.WifiUtils.canShowWifiHotspot;
+
 import android.app.settings.SettingsEnums;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -107,6 +109,13 @@
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
+        if (!canShowWifiHotspot(getContext())) {
+            Log.e(TAG, "can not launch Wi-Fi hotspot settings"
+                    + " because the config is not set to show.");
+            finish();
+            return;
+        }
+
         setIfOnlyAvailableForAdmins(true);
         mUnavailable = isUiRestricted() || !mWifiRestriction.isHotspotAvailable(getContext());
     }
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPreferenceControllerTest.java
index e8ee7c3..bc6053b 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPreferenceControllerTest.java
@@ -16,13 +16,14 @@
 
 package com.android.settings.wifi.tether;
 
+import static com.android.settings.wifi.WifiUtils.setCanShowWifiHotspotCached;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
-import android.net.TetheringManager;
 import android.net.wifi.SoftApConfiguration;
 import android.net.wifi.WifiManager;
 
@@ -62,8 +63,6 @@
     @Mock
     private Lifecycle mLifecycle;
     @Mock
-    private TetheringManager mTetheringManager;
-    @Mock
     private WifiManager mWifiManager;
     @Mock
     private PreferenceScreen mScreen;
@@ -74,38 +73,37 @@
 
     @Before
     public void setUp() {
+        setCanShowWifiHotspotCached(true);
         FakeFeatureFactory.setupForTest();
         mPreference = new PrimarySwitchPreference(mContext);
-        when(mContext.getSystemService(Context.TETHERING_SERVICE)).thenReturn(mTetheringManager);
         when(mContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager);
         when(mScreen.findPreference(anyString())).thenReturn(mPreference);
         mSoftApConfiguration = new SoftApConfiguration.Builder().setSsid(SSID).build();
         when(mWifiManager.getSoftApConfiguration()).thenReturn(mSoftApConfiguration);
 
-        when(mTetheringManager.getTetherableWifiRegexs()).thenReturn(new String[]{"1", "2"});
         mController = new WifiTetherPreferenceController(mContext, mLifecycle, mWifiManager,
-                mTetheringManager, false /* initSoftApManager */, true /* isWifiTetheringAllow */);
+                false /* initSoftApManager */, true /* isWifiTetheringAllow */);
         mController.displayPreference(mScreen);
     }
 
     @Test
-    public void isAvailable_noTetherRegex_shouldReturnFalse() {
-        when(mTetheringManager.getTetherableWifiRegexs()).thenReturn(new String[]{});
-        mController = new WifiTetherPreferenceController(mContext, mLifecycle, mWifiManager,
-                mTetheringManager, false /* initSoftApManager */, true /* isWifiTetheringAllow */);
+    public void isAvailable_canNotShowWifiHotspot_shouldReturnFalse() {
+        setCanShowWifiHotspotCached(false);
 
         assertThat(mController.isAvailable()).isFalse();
     }
 
     @Test
-    public void isAvailable_hasTetherRegex_shouldReturnTrue() {
+    public void isAvailable_canShowWifiHostspot_shouldReturnTrue() {
+        setCanShowWifiHotspotCached(true);
+
         assertThat(mController.isAvailable()).isTrue();
     }
 
     @Test
     public void displayPreference_wifiTetheringNotAllowed_shouldDisable() {
         mController = new WifiTetherPreferenceController(mContext, mLifecycle, mWifiManager,
-                mTetheringManager, false /* initSoftApManager */, false /* isWifiTetheringAllow */);
+                false /* initSoftApManager */, false /* isWifiTetheringAllow */);
 
         mController.displayPreference(mScreen);
 
@@ -116,7 +114,7 @@
     @Test
     public void displayPreference_wifiTetheringAllowed_shouldEnable() {
         mController = new WifiTetherPreferenceController(mContext, mLifecycle, mWifiManager,
-                mTetheringManager, false /* initSoftApManager */, true /* isWifiTetheringAllow */);
+                false /* initSoftApManager */, true /* isWifiTetheringAllow */);
 
         mController.displayPreference(mScreen);
 
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java
index d19bc90..6d3b879 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.wifi.tether;
 
+import static com.android.settings.wifi.WifiUtils.setCanShowWifiHotspotCached;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
@@ -42,6 +44,7 @@
 import androidx.test.core.app.ApplicationProvider;
 
 import com.android.settings.R;
+import com.android.settings.dashboard.RestrictedDashboardFragment;
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.shadow.ShadowFragment;
 
@@ -55,6 +58,8 @@
 import org.mockito.junit.MockitoRule;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
 import org.robolectric.util.ReflectionHelpers;
 
 import java.util.List;
@@ -88,6 +93,7 @@
 
     @Before
     public void setUp() {
+        setCanShowWifiHotspotCached(true);
         doReturn(mWifiManager).when(mContext).getSystemService(WifiManager.class);
         doReturn(mConnectivityManager)
                 .when(mContext).getSystemService(Context.CONNECTIVITY_SERVICE);
@@ -101,6 +107,17 @@
     }
 
     @Test
+    @Config(shadows = ShadowRestrictedDashboardFragment.class)
+    public void onCreate_canNotShowWifiHotspot_shouldFinish() {
+        setCanShowWifiHotspotCached(false);
+        mWifiTetherSettings = spy(new WifiTetherSettings(mWifiRestriction));
+
+        mWifiTetherSettings.onCreate(null);
+
+        verify(mWifiTetherSettings).finish();
+    }
+
+    @Test
     @Config(shadows = ShadowFragment.class)
     public void onStart_uiIsRestricted_removeAllPreferences() {
         spyWifiTetherSettings();
@@ -219,4 +236,13 @@
 
         mWifiTetherSettings.onCreate(Bundle.EMPTY);
     }
+
+    @Implements(RestrictedDashboardFragment.class)
+    public static final class ShadowRestrictedDashboardFragment {
+
+        @Implementation
+        public void onCreate(Bundle icicle) {
+            // do nothing
+        }
+    }
 }
diff --git a/tests/unit/src/com/android/settings/wifi/WifiUtilsTest.java b/tests/unit/src/com/android/settings/wifi/WifiUtilsTest.java
index 1a5e852..2826310 100644
--- a/tests/unit/src/com/android/settings/wifi/WifiUtilsTest.java
+++ b/tests/unit/src/com/android/settings/wifi/WifiUtilsTest.java
@@ -21,19 +21,53 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import android.content.Context;
+import android.content.res.Resources;
+import android.net.TetheringManager;
 import android.net.wifi.SoftApConfiguration;
 import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
 
+import androidx.test.core.app.ApplicationProvider;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 
+import com.android.settings.R;
 import com.android.wifitrackerlib.WifiEntry;
 
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 @RunWith(AndroidJUnit4.class)
 public class WifiUtilsTest {
 
+    static final String[] WIFI_REGEXS = {"wifi_regexs"};
+
+    @Rule
+    public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+    @Spy
+    Context mContext = ApplicationProvider.getApplicationContext();
+    @Mock
+    Resources mResources;
+    @Mock
+    WifiManager mWifiManager;
+    @Mock
+    TetheringManager mTetheringManager;
+
+    @Before
+    public void setUp() {
+        when(mContext.getResources()).thenReturn(mResources);
+        when(mResources.getBoolean(R.bool.config_show_wifi_hotspot_settings)).thenReturn(true);
+        when(mContext.getSystemService(WifiManager.class)).thenReturn(mWifiManager);
+        when(mContext.getSystemService(TetheringManager.class)).thenReturn(mTetheringManager);
+        when(mTetheringManager.getTetherableWifiRegexs()).thenReturn(WIFI_REGEXS);
+    }
+
     @Test
     public void testSSID() {
         assertThat(WifiUtils.isSSIDTooLong("123")).isFalse();
@@ -108,4 +142,53 @@
         WifiConfiguration config = WifiUtils.getWifiConfig(null /* wifiEntry */,
                 null /* scanResult */);
     }
+
+    @Test
+    public void checkShowWifiHotspot_allReady_returnTrue() {
+        assertThat(WifiUtils.checkShowWifiHotspot(mContext)).isTrue();
+    }
+
+    @Test
+    public void checkShowWifiHotspot_contextIsNull_returnFalse() {
+        assertThat(WifiUtils.checkShowWifiHotspot(null)).isFalse();
+    }
+
+    @Test
+    public void checkShowWifiHotspot_configIsNotShow_returnFalse() {
+        when(mResources.getBoolean(R.bool.config_show_wifi_hotspot_settings)).thenReturn(false);
+
+        assertThat(WifiUtils.checkShowWifiHotspot(mContext)).isFalse();
+    }
+
+    @Test
+    public void checkShowWifiHotspot_wifiManagerIsNull_returnFalse() {
+        when(mContext.getSystemService(WifiManager.class)).thenReturn(null);
+
+        assertThat(WifiUtils.checkShowWifiHotspot(mContext)).isFalse();
+    }
+
+    @Test
+    public void checkShowWifiHotspot_tetheringManagerIsNull_returnFalse() {
+        when(mContext.getSystemService(TetheringManager.class)).thenReturn(null);
+
+        assertThat(WifiUtils.checkShowWifiHotspot(mContext)).isFalse();
+    }
+
+    @Test
+    public void checkShowWifiHotspot_wifiRegexsIsEmpty_returnFalse() {
+        when(mTetheringManager.getTetherableWifiRegexs()).thenReturn(null);
+
+        assertThat(WifiUtils.checkShowWifiHotspot(mContext)).isFalse();
+    }
+
+    @Test
+    public void canShowWifiHotspot_cachedIsReady_returnCached() {
+        WifiUtils.setCanShowWifiHotspotCached(true);
+
+        assertThat(WifiUtils.canShowWifiHotspot(null)).isTrue();
+
+        WifiUtils.setCanShowWifiHotspotCached(false);
+
+        assertThat(WifiUtils.canShowWifiHotspot(null)).isFalse();
+    }
 }