WifiServiceImpl: setWifiApEnabled unit tests

Add unit tests to cover setWifiApEnabled.  This did require a small
change to check a tethering permission and add the user manager.

Bug: 37294233
Test: frameworks/opt/net/wifi/tests/wifitests/runtests.sh
Change-Id: I7bdfdcbdfa60605bc2e61f18aa8abeb4bcaf5c56
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index 1ecf882..8173853 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -231,6 +231,10 @@
         return sWifiInjector;
     }
 
+    public UserManager getUserManager() {
+        return UserManager.get(mContext);
+    }
+
     public WifiMetrics getWifiMetrics() {
         return mWifiMetrics;
     }
diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java
index e177201..e394209 100644
--- a/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -39,7 +39,6 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ParceledListSlice;
 import android.database.ContentObserver;
-import android.net.ConnectivityManager;
 import android.net.DhcpInfo;
 import android.net.DhcpResults;
 import android.net.Network;
@@ -330,7 +329,7 @@
         mFacade = mWifiInjector.getFrameworkFacade();
         mWifiMetrics = mWifiInjector.getWifiMetrics();
         mTrafficPoller = mWifiInjector.getWifiTrafficPoller();
-        mUserManager = UserManager.get(mContext);
+        mUserManager = mWifiInjector.getUserManager();
         mCountryCode = mWifiInjector.getWifiCountryCode();
         mWifiStateMachine = mWifiInjector.getWifiStateMachine();
         mWifiStateMachine.enableRssiPolling(true);
@@ -667,7 +666,7 @@
     @Override
     public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
         enforceChangePermission();
-        ConnectivityManager.enforceTetherChangePermission(mContext);
+        mWifiPermissionsUtil.enforceTetherChangePermission(mContext);
 
         mLog.trace("setWifiApEnabled uid=% enable=%").c(Binder.getCallingUid()).c(enabled).flush();
 
diff --git a/service/java/com/android/server/wifi/util/WifiPermissionsUtil.java b/service/java/com/android/server/wifi/util/WifiPermissionsUtil.java
index 2010dcf..6de39ac 100644
--- a/service/java/com/android/server/wifi/util/WifiPermissionsUtil.java
+++ b/service/java/com/android/server/wifi/util/WifiPermissionsUtil.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
+import android.net.ConnectivityManager;
 import android.net.NetworkScoreManager;
 import android.os.RemoteException;
 import android.os.UserManager;
@@ -75,6 +76,15 @@
     }
 
     /**
+     * Check and enforce tether change permission.
+     *
+     * @param context Context object of the caller.
+     */
+    public void enforceTetherChangePermission(Context context) {
+        ConnectivityManager.enforceTetherChangePermission(context);
+    }
+
+    /**
      * API to determine if the caller has permissions to get
      * scan results.
      * @param pkgName Packagename of the application requesting access
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
index f18aabe..ed0e9c4 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
@@ -18,6 +18,7 @@
 
 import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED;
 
+import static com.android.server.wifi.WifiController.CMD_SET_AP;
 import static com.android.server.wifi.WifiController.CMD_WIFI_TOGGLED;
 
 import static org.junit.Assert.assertEquals;
@@ -40,6 +41,7 @@
 import android.os.Message;
 import android.os.Messenger;
 import android.os.PowerManager;
+import android.os.UserManager;
 import android.os.test.TestLooper;
 import android.test.suitebuilder.annotation.SmallTest;
 
@@ -93,6 +95,8 @@
     @Mock WifiPermissionsUtil mWifiPermissionsUtil;
     @Mock WifiSettingsStore mSettingsStore;
     @Mock ContentResolver mContentResolver;
+    @Mock UserManager mUserManager;
+    @Mock WifiConfiguration mApConfig;
     PowerManager mPowerManager;
 
     private class WifiAsyncChannelTester {
@@ -152,6 +156,7 @@
         MockitoAnnotations.initMocks(this);
         mLooper = new TestLooper();
 
+        when(mWifiInjector.getUserManager()).thenReturn(mUserManager);
         when(mWifiInjector.getWifiController()).thenReturn(mWifiController);
         when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics);
         when(mWifiInjector.getWifiStateMachine()).thenReturn(mWifiStateMachine);
@@ -417,4 +422,84 @@
         verify(mWifiController).start();
         verify(mWifiController).sendMessage(CMD_WIFI_TOGGLED);
     }
+
+    /**
+     * Verify setWifiApEnabled works with the correct permissions and a null config.
+     */
+    @Test
+    public void testSetWifiApEnabledWithProperPermissionsWithNullConfig() {
+        when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true);
+        when(mUserManager.hasUserRestriction(eq(UserManager.DISALLOW_CONFIG_TETHERING)))
+                .thenReturn(false);
+        mWifiServiceImpl.setWifiApEnabled(null, true);
+        verify(mWifiController).sendMessage(eq(CMD_SET_AP), eq(1), eq(0), eq(null));
+    }
+
+    /**
+     * Verify setWifiApEnabled works with correct permissions and a valid config.
+     *
+     * TODO: should really validate that ap configs have a set of basic config settings b/37280779
+     */
+    @Test
+    public void testSetWifiApEnabledWithProperPermissionsWithValidConfig() {
+        when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true);
+        when(mUserManager.hasUserRestriction(eq(UserManager.DISALLOW_CONFIG_TETHERING)))
+                .thenReturn(false);
+        WifiConfiguration apConfig = new WifiConfiguration();
+        mWifiServiceImpl.setWifiApEnabled(apConfig, true);
+        verify(mWifiController).sendMessage(eq(CMD_SET_AP), eq(1), eq(0), eq(apConfig));
+    }
+
+    /**
+     * Verify setWifiApEnabled when disabling softap with correct permissions sends the correct
+     * message to WifiController.
+     */
+    @Test
+    public void testSetWifiApEnabledFalseWithProperPermissionsWithNullConfig() {
+        when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true);
+        when(mUserManager.hasUserRestriction(eq(UserManager.DISALLOW_CONFIG_TETHERING)))
+                .thenReturn(false);
+        mWifiServiceImpl.setWifiApEnabled(null, false);
+        verify(mWifiController).sendMessage(eq(CMD_SET_AP), eq(0), eq(0), eq(null));
+    }
+
+    /**
+     * setWifiApEnabled should fail if the provided config is not valid.
+     */
+    @Test
+    public void testSetWIfiApEnabledWithProperPermissionInvalidConfigFails() {
+        when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true);
+        when(mUserManager.hasUserRestriction(eq(UserManager.DISALLOW_CONFIG_TETHERING)))
+                .thenReturn(false);
+        // mApConfig is a mock and the values are not set - triggering the invalid config.  Testing
+        // will be improved when we actually do test softap configs in b/37280779
+        mWifiServiceImpl.setWifiApEnabled(mApConfig, true);
+        verify(mWifiController, never()).sendMessage(eq(CMD_SET_AP), eq(1), eq(0), eq(mApConfig));
+    }
+
+    /**
+     * setWifiApEnabled should throw a security exception when the caller does not have the correct
+     * permissions.
+     */
+    @Test(expected = SecurityException.class)
+    public void testSetWifiApEnabledThrowsSecurityExceptionWithoutConfigOverridePermission()
+            throws Exception {
+        doThrow(new SecurityException()).when(mContext)
+                .enforceCallingOrSelfPermission(eq(android.Manifest.permission.CHANGE_WIFI_STATE),
+                        eq("WifiService"));
+        mWifiServiceImpl.setWifiApEnabled(null, true);
+    }
+
+    /**
+     * setWifiApEnabled should throw a SecurityException when disallow tethering is set for the
+     * user.
+     */
+    @Test(expected = SecurityException.class)
+    public void testSetWifiApEnabledThrowsSecurityExceptionWithDisallowTethering()
+            throws Exception {
+        when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true);
+        when(mUserManager.hasUserRestriction(eq(UserManager.DISALLOW_CONFIG_TETHERING)))
+                .thenReturn(true);
+        mWifiServiceImpl.setWifiApEnabled(null, true);
+    }
 }