summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--service/java/com/android/server/wifi/WifiServiceImpl.java22
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java113
2 files changed, 132 insertions, 3 deletions
diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java
index c3e80705d..c6166cdb2 100644
--- a/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -122,6 +122,10 @@ public class WifiServiceImpl extends IWifiManager.Stub {
private static final boolean DBG = true;
private static final boolean VDBG = false;
+ // Package names for Settings, QuickSettings and QuickQuickSettings
+ private static final String SYSUI_PACKAGE_NAME = "com.android.systemui";
+ private static final String SETTINGS_PACKAGE_NAME = "com.android.settings";
+
// Dumpsys argument to enable/disable disconnect on IP reachability failures.
private static final String DUMP_ARG_SET_IPREACH_DISCONNECT = "set-ipreach-disconnect";
private static final String DUMP_ARG_SET_IPREACH_DISCONNECT_ENABLED = "enabled";
@@ -590,8 +594,20 @@ public class WifiServiceImpl extends IWifiManager.Stub {
throws RemoteException {
enforceChangePermission();
Slog.d(TAG, "setWifiEnabled: " + enable + " pid=" + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- mLog.trace("setWifiEnabled uid=% enable=%").c(Binder.getCallingUid()).c(enable).flush();
+ + ", uid=" + Binder.getCallingUid() + ", package=" + packageName);
+ mLog.trace("setWifiEnabled package=% uid=% enable=%").c(packageName)
+ .c(Binder.getCallingUid()).c(enable).flush();
+
+ // If SoftAp is enabled, only Settings is allowed to toggle wifi
+ boolean apEnabled =
+ mWifiStateMachine.syncGetWifiApState() != WifiManager.WIFI_AP_STATE_DISABLED;
+ boolean isFromSettings =
+ packageName.equals(SYSUI_PACKAGE_NAME) || packageName.equals(SETTINGS_PACKAGE_NAME);
+ if (apEnabled && !isFromSettings) {
+ mLog.trace("setWifiEnabled SoftAp not disabled: only Settings can enable wifi").flush();
+ return false;
+ }
+
/*
* Caller might not have WRITE_SECURE_SETTINGS,
* only CHANGE_WIFI_STATE is enforced
@@ -663,7 +679,7 @@ public class WifiServiceImpl extends IWifiManager.Stub {
}
// null wifiConfig is a meaningful input for CMD_SET_AP
if (wifiConfig == null || isValid(wifiConfig)) {
- mWifiController.obtainMessage(CMD_SET_AP, enabled ? 1 : 0, 0, wifiConfig).sendToTarget();
+ mWifiController.sendMessage(CMD_SET_AP, enabled ? 1 : 0, 0, wifiConfig);
} else {
Slog.e(TAG, "Invalid WifiConfiguration");
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
index 4cdd0f684..93ee8ea9a 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
@@ -33,6 +33,7 @@ import android.content.Context;
import android.content.res.Resources;
import android.net.IpConfiguration;
import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IPowerManager;
@@ -67,6 +68,10 @@ public class WifiServiceImplTest {
private static final String TAG = "WifiServiceImplTest";
private static final int DEFAULT_VERBOSE_LOGGING = 0;
+ private static final String ANDROID_SYSTEM_PACKAGE = "android";
+ private static final String TEST_PACKAGE_NAME = "TestPackage";
+ private static final String SETTINGS_PACKAGE_NAME = "com.android.settings";
+ private static final String SYSUI_PACKAGE_NAME = "com.android.systemui";
@Mock Context mContext;
@Mock WifiInjector mWifiInjector;
@@ -230,6 +235,112 @@ public class WifiServiceImplTest {
.dump(any(FileDescriptor.class), any(PrintWriter.class), any(String[].class));
}
+
+ /**
+ * Verify that wifi can be enabled by a caller with WIFI_STATE_CHANGE permission when wifi is
+ * off (no hotspot, no airplane mode).
+ */
+ @Test
+ public void testSetWifiEnabledSuccess() throws Exception {
+ when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_DISABLED);
+ when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true);
+ assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true));
+ verify(mWifiController).sendMessage(eq(CMD_WIFI_TOGGLED));
+ }
+
+ /**
+ * Verify that the CMD_TOGGLE_WIFI message won't be sent if wifi is already on.
+ */
+ @Test
+ public void testSetWifiEnabledNoToggle() throws Exception {
+ when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_DISABLED);
+ when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(false);
+ assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true));
+ verify(mWifiController, never()).sendMessage(eq(CMD_WIFI_TOGGLED));
+ }
+
+ /**
+ * Verify a SecurityException is thrown if a caller does not have the correct permission to
+ * toggle wifi.
+ */
+ @Test(expected = SecurityException.class)
+ public void testSetWifiEnableWithoutPermission() throws Exception {
+ doThrow(new SecurityException()).when(mContext)
+ .enforceCallingOrSelfPermission(eq(android.Manifest.permission.CHANGE_WIFI_STATE),
+ eq("WifiService"));
+ mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true);
+ verify(mWifiStateMachine, never()).syncGetWifiApState();
+ }
+
+ /**
+ * Verify that a call from Settings can enable wifi if we are in softap mode.
+ */
+ @Test
+ public void testSetWifiEnabledFromSettingsWhenApEnabled() throws Exception {
+ when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_ENABLED);
+ when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true);
+ assertTrue(mWifiServiceImpl.setWifiEnabled(SETTINGS_PACKAGE_NAME, true));
+ verify(mWifiController).sendMessage(eq(CMD_WIFI_TOGGLED));
+ }
+
+ /**
+ * Verify that a call from SysUI can enable wifi if we are in softap mode.
+ */
+ @Test
+ public void testSetWifiEnabledFromSysUiWhenApEnabled() throws Exception {
+ when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_ENABLED);
+ when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true);
+ assertTrue(mWifiServiceImpl.setWifiEnabled(SYSUI_PACKAGE_NAME, true));
+ verify(mWifiController).sendMessage(eq(CMD_WIFI_TOGGLED));
+ }
+
+ /**
+ * Verify that a call from an app cannot enable wifi if we are in softap mode.
+ */
+ @Test
+ public void testSetWifiEnabledFromAppFailsWhenApEnabled() throws Exception {
+ when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_ENABLED);
+ assertFalse(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true));
+ verify(mSettingsStore, never()).handleWifiToggled(anyBoolean());
+ verify(mWifiController, never()).sendMessage(eq(CMD_WIFI_TOGGLED));
+ }
+
+ /**
+ * Verify that wifi can be disabled by a caller with WIFI_STATE_CHANGE permission when wifi is
+ * on.
+ */
+ @Test
+ public void testSetWifiDisabledSuccess() throws Exception {
+ when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_DISABLED);
+ when(mSettingsStore.handleWifiToggled(eq(false))).thenReturn(true);
+ assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false));
+ verify(mWifiController).sendMessage(eq(CMD_WIFI_TOGGLED));
+ }
+
+ /**
+ * Verify that CMD_TOGGLE_WIFI message won't be sent if wifi is already off.
+ */
+ @Test
+ public void testSetWifiDisabledNoToggle() throws Exception {
+ when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_DISABLED);
+ when(mSettingsStore.handleWifiToggled(eq(false))).thenReturn(false);
+ assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false));
+ verify(mWifiController, never()).sendMessage(eq(CMD_WIFI_TOGGLED));
+ }
+
+ /**
+ * Verify a SecurityException is thrown if a caller does not have the correct permission to
+ * toggle wifi.
+ */
+ @Test(expected = SecurityException.class)
+ public void testSetWifiDisabledWithoutPermission() throws Exception {
+ when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_DISABLED);
+ doThrow(new SecurityException()).when(mContext)
+ .enforceCallingOrSelfPermission(eq(android.Manifest.permission.CHANGE_WIFI_STATE),
+ eq("WifiService"));
+ mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false);
+ }
+
/**
* Ensure unpermitted callers cannot write the SoftApConfiguration.
*
@@ -319,6 +430,8 @@ public class WifiServiceImplTest {
when(mSettingsStore.handleWifiToggled(true)).thenReturn(true);
when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true);
when(mWifiStateMachine.syncGetWifiState()).thenReturn(WIFI_STATE_DISABLED);
+ when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_DISABLED);
+ when(mContext.getPackageName()).thenReturn(ANDROID_SYSTEM_PACKAGE);
mWifiServiceImpl.checkAndStartWifi();
verify(mWifiController).start();
verify(mWifiController).sendMessage(CMD_WIFI_TOGGLED);