summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--service/java/com/android/server/wifi/LocalOnlyHotspotRequestInfo.java48
-rw-r--r--service/java/com/android/server/wifi/WifiServiceImpl.java132
-rw-r--r--tests/wifitests/src/com/android/server/wifi/LocalOnlyHotspotRequestInfoTest.java48
-rw-r--r--tests/wifitests/src/com/android/server/wifi/TestUtil.java15
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java241
5 files changed, 456 insertions, 28 deletions
diff --git a/service/java/com/android/server/wifi/LocalOnlyHotspotRequestInfo.java b/service/java/com/android/server/wifi/LocalOnlyHotspotRequestInfo.java
index 2925d966b..9e3b4fb2c 100644
--- a/service/java/com/android/server/wifi/LocalOnlyHotspotRequestInfo.java
+++ b/service/java/com/android/server/wifi/LocalOnlyHotspotRequestInfo.java
@@ -17,6 +17,8 @@
package com.android.server.wifi;
import android.annotation.NonNull;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
import android.os.Binder;
import android.os.IBinder;
import android.os.Message;
@@ -31,7 +33,9 @@ import com.android.internal.util.Preconditions;
* @hide
*/
public class LocalOnlyHotspotRequestInfo implements IBinder.DeathRecipient {
- private final int mUid;
+ static final int HOTSPOT_NO_ERROR = -1;
+
+ private final int mPid;
private final IBinder mBinder;
private final RequestingApplicationDeathCallback mCallback;
private final Messenger mMessenger;
@@ -48,7 +52,7 @@ public class LocalOnlyHotspotRequestInfo implements IBinder.DeathRecipient {
LocalOnlyHotspotRequestInfo(@NonNull IBinder binder, @NonNull Messenger messenger,
@NonNull RequestingApplicationDeathCallback callback) {
- mUid = Binder.getCallingUid();
+ mPid = Binder.getCallingPid();
mBinder = Preconditions.checkNotNull(binder);
mMessenger = Preconditions.checkNotNull(messenger);
mCallback = Preconditions.checkNotNull(callback);
@@ -76,21 +80,45 @@ public class LocalOnlyHotspotRequestInfo implements IBinder.DeathRecipient {
}
/**
- * Send a message to WifiManager for the calling application.
+ * Send a HOTSPOT_FAILED message to WifiManager for the calling application with the error code.
+ *
+ * @param reasonCode error code for the message
+ *
+ * @throws RemoteException
+ */
+ public void sendHotspotFailedMessage(int reasonCode) throws RemoteException {
+ Message message = Message.obtain();
+ message.what = WifiManager.HOTSPOT_FAILED;
+ message.arg1 = reasonCode;
+ mMessenger.send(message);
+ }
+
+ /**
+ * Send a HOTSPOT_STARTED message to WifiManager for the calling application with the config.
+ *
+ * @param config WifiConfiguration for the callback
*
- * @param what Message type to send
- * @param arg1 arg1 for the message
+ * @throws RemoteException
+ */
+ public void sendHotspotStartedMessage(WifiConfiguration config) throws RemoteException {
+ Message message = Message.obtain();
+ message.what = WifiManager.HOTSPOT_STARTED;
+ message.obj = config;
+ mMessenger.send(message);
+ }
+
+ /**
+ * Send a HOTSPOT_STOPPED message to WifiManager for the calling application.
*
* @throws RemoteException
*/
- public void sendMessage(int what, int arg1) throws RemoteException {
+ public void sendHotspotStoppedMessage() throws RemoteException {
Message message = Message.obtain();
- message.what = what;
- message.arg1 = arg1;
+ message.what = WifiManager.HOTSPOT_STOPPED;
mMessenger.send(message);
}
- public int getUid() {
- return mUid;
+ public int getPid() {
+ return mPid;
}
}
diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java
index 6a5c6d2f5..ce9784d2e 100644
--- a/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -16,7 +16,18 @@
package com.android.server.wifi;
+import static android.net.wifi.WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE;
+import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_FAILURE_REASON;
+import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
+import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_GENERIC;
+import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_NO_CHANNEL;
+import static android.net.wifi.WifiManager.SAP_START_FAILURE_NO_CHANNEL;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED;
+
import static com.android.server.connectivity.tethering.IControlsTethering.STATE_TETHERED;
+import static com.android.server.wifi.LocalOnlyHotspotRequestInfo.HOTSPOT_NO_ERROR;
import static com.android.server.wifi.WifiController.CMD_AIRPLANE_TOGGLED;
import static com.android.server.wifi.WifiController.CMD_BATTERY_CHANGED;
import static com.android.server.wifi.WifiController.CMD_EMERGENCY_CALL_STATE_CHANGED;
@@ -475,6 +486,21 @@ public class WifiServiceImpl extends IWifiManager.Stub {
},
new IntentFilter(TelephonyIntents.ACTION_SIM_STATE_CHANGED));
+ mContext.registerReceiver(
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final int currentState = intent.getIntExtra(EXTRA_WIFI_AP_STATE,
+ WIFI_AP_STATE_DISABLED);
+ final int prevState = intent.getIntExtra(EXTRA_PREVIOUS_WIFI_AP_STATE,
+ WIFI_AP_STATE_DISABLED);
+ final int errorCode = intent.getIntExtra(EXTRA_WIFI_AP_FAILURE_REASON,
+ HOTSPOT_NO_ERROR);
+ handleWifiApStateChange(currentState, prevState, errorCode);
+ }
+ },
+ new IntentFilter(WifiManager.WIFI_AP_STATE_CHANGED_ACTION));
+
// Adding optimizations of only receiving broadcasts when wifi is enabled
// can result in race conditions when apps toggle wifi in the background
// without active user involvement. Always receive broadcasts.
@@ -907,6 +933,108 @@ public class WifiServiceImpl extends IWifiManager.Stub {
}
/**
+ * Private method to handle SoftAp state changes
+ */
+ private void handleWifiApStateChange(int currentState, int previousState, int errorCode) {
+ // The AP state update from WifiStateMachine for softap
+ Slog.d(TAG, "handleWifiApStateChange: currentState=" + currentState
+ + " previousState=" + previousState + " errorCode= " + errorCode);
+
+ // check if we have a failure - since it is possible (worst case scenario where
+ // WifiController and WifiStateMachine are out of sync wrt modes) to get two FAILED
+ // notifications in a row, we need to handle this first.
+ if (currentState == WIFI_AP_STATE_FAILED) {
+ // update registered LOHS callbacks if we see a failure
+ synchronized (mLocalOnlyHotspotRequests) {
+ int errorToReport = ERROR_GENERIC;
+ if (errorCode == SAP_START_FAILURE_NO_CHANNEL) {
+ errorToReport = ERROR_NO_CHANNEL;
+ }
+ // holding the required lock: send message to requestors and clear the list
+ sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked(
+ errorToReport);
+ }
+ return;
+ }
+
+ if (currentState == WIFI_AP_STATE_DISABLING || currentState == WIFI_AP_STATE_DISABLED) {
+ // softap is shutting down or is down... let requestors know via the onStopped call
+ synchronized (mLocalOnlyHotspotRequests) {
+ // holding the required lock: send message to requestors and clear the list
+ sendHotspotStoppedMessageToAllLOHSRequestInfoEntriesLocked();
+ }
+ return;
+ }
+
+ // remaining states are enabling or enabled... those are not used for the callbacks
+ }
+
+ /**
+ * Helper method to send a HOTSPOT_FAILED message to all registered LocalOnlyHotspotRequest
+ * callers and clear the registrations.
+ *
+ * Callers should already hold the mLocalOnlyHotspotRequests lock.
+ */
+ private void sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked(int arg1) {
+ for (LocalOnlyHotspotRequestInfo requestor : mLocalOnlyHotspotRequests.values()) {
+ try {
+ requestor.sendHotspotFailedMessage(arg1);
+ } catch (RemoteException e) {
+ // This will be cleaned up by binder death handling
+ }
+ }
+
+ // Since all callers were notified, now clear the registrations.
+ mLocalOnlyHotspotRequests.clear();
+ }
+
+ /**
+ * Helper method to send a HOTSPOT_STOPPED message to all registered LocalOnlyHotspotRequest
+ * callers and clear the registrations.
+ *
+ * Callers should already hold the mLocalOnlyHotspotRequests lock.
+ */
+ private void sendHotspotStoppedMessageToAllLOHSRequestInfoEntriesLocked() {
+ for (LocalOnlyHotspotRequestInfo requestor : mLocalOnlyHotspotRequests.values()) {
+ try {
+ requestor.sendHotspotStoppedMessage();
+ } catch (RemoteException e) {
+ // This will be cleaned up by binder death handling
+ }
+ }
+
+ // Since all callers were notified, now clear the registrations.
+ mLocalOnlyHotspotRequests.clear();
+ }
+
+ /**
+ * Helper method to send a HOTSPOT_STARTED message to all registered LocalOnlyHotspotRequest
+ * callers.
+ *
+ * Callers should already hold the mLocalOnlyHotspotRequests lock.
+ */
+ private void sendHotspotStartedMessageToAllLOHSRequestInfoEntriesLocked() {
+ for (LocalOnlyHotspotRequestInfo requestor : mLocalOnlyHotspotRequests.values()) {
+ try {
+ requestor.sendHotspotStartedMessage(mLocalOnlyHotspotConfig);
+ } catch (RemoteException e) {
+ // This will be cleaned up by binder death handling
+ }
+ }
+ }
+
+ /**
+ * Temporary method used for testing while startLocalOnlyHotspot is not fully implemented. This
+ * method allows unit tests to register callbacks directly for testing mechanisms triggered by
+ * softap mode changes.
+ * TODO: remove when startLocalOnlyHotspot is implemented.
+ */
+ @VisibleForTesting
+ void registerLOHSForTest(int pid, LocalOnlyHotspotRequestInfo request) {
+ mLocalOnlyHotspotRequests.put(pid, request);
+ }
+
+ /**
* Method to start LocalOnlyHotspot. In this method, permissions, settings and modes are
* checked to verify that we can enter softapmode. This method returns
* {@link LocalOnlyHotspotCallback#REQUEST_REGISTERED} if we will attempt to start, otherwise,
@@ -980,10 +1108,10 @@ public class WifiServiceImpl extends IWifiManager.Stub {
* Helper method to unregister LocalOnlyHotspot requestors and stop the hotspot if needed.
*/
private void unregisterCallingAppAndStopLocalOnlyHotspot(LocalOnlyHotspotRequestInfo request) {
- mLog.trace("unregisterCallingAppAndStopLocalOnlyHotspot uid=%").c(request.getUid()).flush();
+ mLog.trace("unregisterCallingAppAndStopLocalOnlyHotspot pid=%").c(request.getPid()).flush();
synchronized (mLocalOnlyHotspotRequests) {
- if (mLocalOnlyHotspotRequests.remove(request.getUid()) == null) {
+ if (mLocalOnlyHotspotRequests.remove(request.getPid()) == null) {
mLog.trace("LocalOnlyHotspotRequestInfo not found to remove");
return;
}
diff --git a/tests/wifitests/src/com/android/server/wifi/LocalOnlyHotspotRequestInfoTest.java b/tests/wifitests/src/com/android/server/wifi/LocalOnlyHotspotRequestInfoTest.java
index 0e8ead2e6..5f170b8f3 100644
--- a/tests/wifitests/src/com/android/server/wifi/LocalOnlyHotspotRequestInfoTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/LocalOnlyHotspotRequestInfoTest.java
@@ -17,11 +17,10 @@
package com.android.server.wifi;
import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.*;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
@@ -129,23 +128,48 @@ public class LocalOnlyHotspotRequestInfoTest {
}
/**
- * Verify the uid is properly set.
+ * Verify the pid is properly set.
*/
@Test
- public void verifyUid() {
+ public void verifyPid() {
mLOHSRequestInfo = new LocalOnlyHotspotRequestInfo(mAppBinder, mMessenger, mCallback);
- assertEquals(Process.myUid(), mLOHSRequestInfo.getUid());
+ assertEquals(Process.myPid(), mLOHSRequestInfo.getPid());
}
/**
- * Verify that sendMessage does send a Message properly
+ * Verify that sendHotspotFailedMessage does send a Message properly
*/
@Test
- public void verifySendMessenger() throws Exception {
+ public void verifySendFailedMessage() throws Exception {
mLOHSRequestInfo = new LocalOnlyHotspotRequestInfo(mAppBinder, mMessenger, mCallback);
- mLOHSRequestInfo.sendMessage(1, 1);
+ mLOHSRequestInfo.sendHotspotFailedMessage(
+ WifiManager.LocalOnlyHotspotCallback.ERROR_GENERIC);
Message message = mTestLooper.nextMessage();
- assertEquals(1, message.what);
- assertEquals(1, message.arg1);
+ assertEquals(WifiManager.HOTSPOT_FAILED, message.what);
+ assertEquals(WifiManager.LocalOnlyHotspotCallback.ERROR_GENERIC, message.arg1);
+ }
+
+ /**
+ * Verify that sendHotspotStartedMessage does send a Message properly
+ */
+ @Test
+ public void verifySendStartedMessage() throws Exception {
+ mLOHSRequestInfo = new LocalOnlyHotspotRequestInfo(mAppBinder, mMessenger, mCallback);
+ WifiConfiguration config = mock(WifiConfiguration.class);
+ mLOHSRequestInfo.sendHotspotStartedMessage(config);
+ Message message = mTestLooper.nextMessage();
+ assertEquals(WifiManager.HOTSPOT_STARTED, message.what);
+ assertEquals(config, (WifiConfiguration) message.obj);
+ }
+
+ /**
+ * Verify that sendHotspotStoppedMessage does send a Message properly
+ */
+ @Test
+ public void verifySendStoppedMessage() throws Exception {
+ mLOHSRequestInfo = new LocalOnlyHotspotRequestInfo(mAppBinder, mMessenger, mCallback);
+ mLOHSRequestInfo.sendHotspotStoppedMessage();
+ Message message = mTestLooper.nextMessage();
+ assertEquals(WifiManager.HOTSPOT_STOPPED, message.what);
}
}
diff --git a/tests/wifitests/src/com/android/server/wifi/TestUtil.java b/tests/wifitests/src/com/android/server/wifi/TestUtil.java
index 3b43ad8c5..90df07a61 100644
--- a/tests/wifitests/src/com/android/server/wifi/TestUtil.java
+++ b/tests/wifitests/src/com/android/server/wifi/TestUtil.java
@@ -71,6 +71,21 @@ public class TestUtil {
}
/**
+ * Send {@link WifiManager#WIFI_AP_STATE_CHANGED} broadcast.
+ */
+ public static void sendWifiApStateChanged(BroadcastReceiver broadcastReceiver,
+ Context context, int apState, int previousState, int error) {
+ Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
+ intent.putExtra(WifiManager.EXTRA_WIFI_AP_STATE, apState);
+ intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE, previousState);
+ if (apState == WifiManager.WIFI_AP_STATE_FAILED) {
+ //only set reason number when softAP start failed
+ intent.putExtra(WifiManager.EXTRA_WIFI_AP_FAILURE_REASON, error);
+ }
+ broadcastReceiver.onReceive(context, intent);
+ }
+
+ /**
* Send {@link ConnectivityManager#ACTION_TETHER_STATE_CHANGED} broadcast.
*/
public static void sendTetherStateChanged(BroadcastReceiver broadcastReceiver,
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
index bef3fc104..f1c19e6b3 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
@@ -16,12 +16,21 @@
package com.android.server.wifi;
+import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_GENERIC;
import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE;
+import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_NO_CHANNEL;
import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_TETHERING_DISALLOWED;
+import static android.net.wifi.WifiManager.SAP_START_FAILURE_GENERAL;
+import static android.net.wifi.WifiManager.SAP_START_FAILURE_NO_CHANNEL;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED;
import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED;
import static android.provider.Settings.Secure.LOCATION_MODE_HIGH_ACCURACY;
import static android.provider.Settings.Secure.LOCATION_MODE_OFF;
+import static com.android.server.wifi.LocalOnlyHotspotRequestInfo.HOTSPOT_NO_ERROR;
import static com.android.server.wifi.WifiController.CMD_SET_AP;
import static com.android.server.wifi.WifiController.CMD_WIFI_TOGGLED;
@@ -35,8 +44,10 @@ import static org.mockito.Mockito.*;
import android.app.ActivityManager;
import android.app.AppOpsManager;
+import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.IntentFilter;
import android.content.res.Resources;
import android.net.IpConfiguration;
import android.net.wifi.ScanSettings;
@@ -64,6 +75,8 @@ import com.android.server.wifi.util.WifiPermissionsUtil;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
@@ -89,14 +102,21 @@ public class WifiServiceImplTest {
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";
- private static final int TEST_UID = 6789;
+ private static final int TEST_PID = 6789;
+ private static final int TEST_PID2 = 9876;
private WifiServiceImpl mWifiServiceImpl;
private TestLooper mLooper;
private PowerManager mPowerManager;
private Handler mHandler;
private Messenger mAppMessenger;
- private int mUid;
+ private int mPid;
+
+ final ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+ final ArgumentCaptor<IntentFilter> mIntentFilterCaptor =
+ ArgumentCaptor.forClass(IntentFilter.class);
+
@Mock Context mContext;
@Mock WifiInjector mWifiInjector;
@@ -182,10 +202,10 @@ public class WifiServiceImplTest {
@Before public void setUp() {
MockitoAnnotations.initMocks(this);
mLooper = new TestLooper();
- mHandler = new Handler(mLooper.getLooper());
+ mHandler = spy(new Handler(mLooper.getLooper()));
mAppMessenger = new Messenger(mHandler);
- when(mRequestInfo.getUid()).thenReturn(mUid);
+ when(mRequestInfo.getPid()).thenReturn(mPid);
when(mWifiInjector.getUserManager()).thenReturn(mUserManager);
when(mWifiInjector.getWifiController()).thenReturn(mWifiController);
when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics);
@@ -824,6 +844,219 @@ public class WifiServiceImplTest {
verify(mWifiController, never()).sendMessage(eq(CMD_SET_AP), eq(0), eq(0));
}
+ private class IntentFilterMatcher implements ArgumentMatcher<IntentFilter> {
+ @Override
+ public boolean matches(IntentFilter filter) {
+ return filter.hasAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
+ }
+ }
+
+ /**
+ * Verify that onFailed is called for registered LOHS callers when a WIFI_AP_STATE_CHANGE
+ * broadcast is received.
+ */
+ @Test
+ public void testRegisteredCallbacksTriggeredOnSoftApFailureGeneric() throws Exception {
+ when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(false);
+ when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
+ mWifiServiceImpl.checkAndStartWifi();
+
+ verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
+ (IntentFilter) argThat(new IntentFilterMatcher()));
+
+ mWifiServiceImpl.registerLOHSForTest(TEST_PID, mRequestInfo);
+
+ TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
+ WIFI_AP_STATE_FAILED, WIFI_AP_STATE_DISABLED, SAP_START_FAILURE_GENERAL);
+
+ verify(mRequestInfo).sendHotspotFailedMessage(ERROR_GENERIC);
+ }
+
+ /**
+ * Verify that onFailed is called for registered LOHS callers when a WIFI_AP_STATE_CHANGE
+ * broadcast is received with the SAP_START_FAILURE_NO_CHANNEL error.
+ */
+ @Test
+ public void testRegisteredCallbacksTriggeredOnSoftApFailureNoChannel() throws Exception {
+ when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(false);
+ when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
+ mWifiServiceImpl.checkAndStartWifi();
+
+ verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
+ (IntentFilter) argThat(new IntentFilterMatcher()));
+
+ mWifiServiceImpl.registerLOHSForTest(TEST_PID, mRequestInfo);
+
+ TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
+ WIFI_AP_STATE_FAILED, WIFI_AP_STATE_DISABLED, SAP_START_FAILURE_NO_CHANNEL);
+
+ verify(mRequestInfo).sendHotspotFailedMessage(ERROR_NO_CHANNEL);
+ }
+
+ /**
+ * Verify that onStopped is called for registered LOHS callers when a WIFI_AP_STATE_CHANGE
+ * broadcast is received with WIFI_AP_STATE_DISABLING.
+ */
+ @Test
+ public void testRegisteredCallbacksTriggeredOnSoftApDisabling() throws Exception {
+ when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(false);
+ when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
+ mWifiServiceImpl.checkAndStartWifi();
+
+ verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
+ (IntentFilter) argThat(new IntentFilterMatcher()));
+
+ mWifiServiceImpl.registerLOHSForTest(TEST_PID, mRequestInfo);
+
+ TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
+ WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR);
+
+ verify(mRequestInfo).sendHotspotStoppedMessage();
+ }
+
+
+ /**
+ * Verify that onStopped is called for registered LOHS callers when a WIFI_AP_STATE_CHANGE
+ * broadcast is received with WIFI_AP_STATE_DISABLED.
+ */
+ @Test
+ public void testRegisteredCallbacksTriggeredOnSoftApDisabled() throws Exception {
+ when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(false);
+ when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
+ mWifiServiceImpl.checkAndStartWifi();
+
+ verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
+ (IntentFilter) argThat(new IntentFilterMatcher()));
+
+ mWifiServiceImpl.registerLOHSForTest(TEST_PID, mRequestInfo);
+
+ TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
+ WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR);
+
+ verify(mRequestInfo).sendHotspotStoppedMessage();
+ }
+
+ /**
+ * Verify that no callbacks are called for registered LOHS callers when a WIFI_AP_STATE_CHANGE
+ * broadcast is received and the softap started.
+ */
+ @Test
+ public void testRegisteredCallbacksNotTriggeredOnSoftApStart() throws Exception {
+ when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(false);
+ when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
+ mWifiServiceImpl.checkAndStartWifi();
+
+ verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
+ (IntentFilter) argThat(new IntentFilterMatcher()));
+
+ mWifiServiceImpl.registerLOHSForTest(TEST_PID, mRequestInfo);
+
+ TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
+ WIFI_AP_STATE_ENABLED, WIFI_AP_STATE_DISABLED, HOTSPOT_NO_ERROR);
+ verifyNoMoreInteractions(mRequestInfo);
+ }
+
+ /**
+ * Verify that onStopped is called only once for registered LOHS callers when
+ * WIFI_AP_STATE_CHANGE broadcasts are received with WIFI_AP_STATE_DISABLING and
+ * WIFI_AP_STATE_DISABLED.
+ */
+ @Test
+ public void testRegisteredCallbacksTriggeredOnlyOnceWhenSoftApDisabling() throws Exception {
+ when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(false);
+ when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
+ mWifiServiceImpl.checkAndStartWifi();
+
+ verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
+ (IntentFilter) argThat(new IntentFilterMatcher()));
+
+ mWifiServiceImpl.registerLOHSForTest(TEST_PID, mRequestInfo);
+
+ TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
+ WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR);
+ TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
+ WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR);
+
+ verify(mRequestInfo).sendHotspotStoppedMessage();
+ }
+
+ /**
+ * Verify that onFailed is called only once for registered LOHS callers when
+ * WIFI_AP_STATE_CHANGE broadcasts are received with WIFI_AP_STATE_FAILED twice.
+ */
+ @Test
+ public void testRegisteredCallbacksTriggeredOnlyOnceWhenSoftApFailsTwice() throws Exception {
+ when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(false);
+ when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
+ mWifiServiceImpl.checkAndStartWifi();
+
+ verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
+ (IntentFilter) argThat(new IntentFilterMatcher()));
+
+ mWifiServiceImpl.registerLOHSForTest(TEST_PID, mRequestInfo);
+
+ TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
+ WIFI_AP_STATE_FAILED, WIFI_AP_STATE_FAILED, ERROR_GENERIC);
+ TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
+ WIFI_AP_STATE_FAILED, WIFI_AP_STATE_FAILED, ERROR_GENERIC);
+
+ verify(mRequestInfo).sendHotspotFailedMessage(ERROR_GENERIC);
+ }
+
+ /**
+ * Verify that onFailed is called for all registered LOHS callers when
+ * WIFI_AP_STATE_CHANGE broadcasts are received with WIFI_AP_STATE_FAILED.
+ */
+ @Test
+ public void testAllRegisteredCallbacksTriggeredWhenSoftApFails() throws Exception {
+ when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(false);
+ when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
+ mWifiServiceImpl.checkAndStartWifi();
+
+ verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
+ (IntentFilter) argThat(new IntentFilterMatcher()));
+
+ // make an additional request for this test
+ LocalOnlyHotspotRequestInfo request2 = mock(LocalOnlyHotspotRequestInfo.class);
+ mWifiServiceImpl.registerLOHSForTest(TEST_PID, mRequestInfo);
+ mWifiServiceImpl.registerLOHSForTest(TEST_PID2, request2);
+
+ TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
+ WIFI_AP_STATE_FAILED, WIFI_AP_STATE_FAILED, ERROR_GENERIC);
+ TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
+ WIFI_AP_STATE_FAILED, WIFI_AP_STATE_FAILED, ERROR_GENERIC);
+
+ verify(mRequestInfo).sendHotspotFailedMessage(ERROR_GENERIC);
+ verify(request2).sendHotspotFailedMessage(ERROR_GENERIC);
+ }
+
+ /**
+ * Verify that onFailed is called for all registered LOHS callers when
+ * WIFI_AP_STATE_CHANGE broadcasts are received with WIFI_AP_STATE_DISABLED.
+ */
+ @Test
+ public void testAllRegisteredCallbacksTriggeredWhenSoftApStops() throws Exception {
+ when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(false);
+ when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
+ mWifiServiceImpl.checkAndStartWifi();
+
+ verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
+ (IntentFilter) argThat(new IntentFilterMatcher()));
+
+ // make an additional request for this test
+ LocalOnlyHotspotRequestInfo request2 = mock(LocalOnlyHotspotRequestInfo.class);
+ mWifiServiceImpl.registerLOHSForTest(TEST_PID, mRequestInfo);
+ mWifiServiceImpl.registerLOHSForTest(TEST_PID2, request2);
+
+ TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
+ WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR);
+ TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
+ WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR);
+
+ verify(mRequestInfo).sendHotspotStoppedMessage();
+ verify(request2).sendHotspotStoppedMessage();
+ }
+
/**
* Verify that a call to startWatchLocalOnlyHotspot is only allowed from callers with the
* signature only NETWORK_SETTINGS permission.