diff options
author | Nate(Qiang) Jiang <qiangjiang@google.com> | 2019-10-22 13:08:35 -0700 |
---|---|---|
committer | Nate(Qiang) Jiang <qiangjiang@google.com> | 2019-11-07 13:14:38 -0800 |
commit | 194a506c9a5de993caee8888442db7bdb45de3e1 (patch) | |
tree | dd96e94499b64f97a93ef69aa3989bbe29b0e929 | |
parent | 4e74ff724a66310cc51f13fda8acc9bf6c43fa5f (diff) |
[NetworkSuggestion] add network callback
Add a network callback for WifiNetworkSuggestion. Will send event for
both connection success and failure.
Bug: 142062781
Test: atest android.net.wifi
Test: atest com.android.server.wifi
Change-Id: I46d403b784d469538118c9b03556b8236de35fe7
4 files changed, 282 insertions, 8 deletions
diff --git a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java index a16d9684d..cbeb6284c 100644 --- a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java +++ b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java @@ -33,12 +33,15 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.Resources; import android.net.MacAddress; +import android.net.wifi.ISuggestionConnectionStatusListener; import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; import android.net.wifi.WifiNetworkSuggestion; import android.net.wifi.WifiScanner; import android.os.Handler; +import android.os.IBinder; +import android.os.RemoteException; import android.os.UserHandle; import android.telephony.TelephonyManager; import android.text.TextUtils; @@ -49,6 +52,7 @@ import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.notification.SystemNotificationChannels; +import com.android.server.wifi.util.ExternalCallbackTracker; import com.android.server.wifi.util.WifiPermissionsUtil; import java.io.FileDescriptor; @@ -239,6 +243,9 @@ public class WifiNetworkSuggestionsManager { private final Map<String, Set<ExtendedWifiNetworkSuggestion>> mPasspointInfo = new HashMap<>(); + private final HashMap<String, ExternalCallbackTracker<ISuggestionConnectionStatusListener>> + mSuggestionStatusListenerPerApp = new HashMap<>(); + /** * Intent filter for processing notification actions. */ @@ -764,6 +771,9 @@ public class WifiNetworkSuggestionsManager { removeInternal(Collections.EMPTY_LIST, packageName, perAppInfo); // Remove the package fully from the internal database. mActiveNetworkSuggestionsPerApp.remove(packageName); + ExternalCallbackTracker<ISuggestionConnectionStatusListener> listenerTracker = + mSuggestionStatusListenerPerApp.remove(packageName); + if (listenerTracker != null) listenerTracker.clear(); saveToStore(); Log.i(TAG, "Removed " + packageName); } @@ -795,6 +805,7 @@ public class WifiNetworkSuggestionsManager { removeInternal(Collections.EMPTY_LIST, entry.getKey(), entry.getValue()); iter.remove(); } + mSuggestionStatusListenerPerApp.clear(); saveToStore(); Log.i(TAG, "Cleared all internal state"); } @@ -1090,6 +1101,7 @@ public class WifiNetworkSuggestionsManager { mWifiPermissionsUtil.enforceCanAccessScanResults( packageName, matchingSuggestion.suggestorUid); } catch (SecurityException se) { + Log.w(TAG, "Permission denied for sending post connection broadcast to " + packageName); return; } if (mVerboseLoggingEnabled) { @@ -1145,9 +1157,10 @@ public class WifiNetworkSuggestionsManager { * * @param network {@link WifiConfiguration} representing the network that connection failed to. * @param bssid BSSID of the network connection failed to if known, else null. + * @param failureCode failure reason code. */ private void handleConnectionFailure(@NonNull WifiConfiguration network, - @Nullable String bssid) { + @Nullable String bssid, int failureCode) { Set<ExtendedWifiNetworkSuggestion> matchingExtNetworkSuggestions = getNetworkSuggestionsForWifiConfiguration(network, bssid); if (mVerboseLoggingEnabled) { @@ -1160,6 +1173,12 @@ public class WifiNetworkSuggestionsManager { mWifiMetrics.incrementNetworkSuggestionApiNumConnectFailure(); // TODO (b/115504887, b/112196799): Blacklist the corresponding network suggestion if // the connection failed. + + for (ExtendedWifiNetworkSuggestion matchingExtNetworkSuggestion + : matchingExtNetworkSuggestions) { + sendConnectionFailureIfAllowed(matchingExtNetworkSuggestion.perAppInfo.packageName, + matchingExtNetworkSuggestion.wns, failureCode); + } } private void resetConnectionState() { @@ -1182,7 +1201,7 @@ public class WifiNetworkSuggestionsManager { if (failureCode == WifiMetrics.ConnectionEvent.FAILURE_NONE) { handleConnectionSuccess(network, bssid); } else { - handleConnectionFailure(network, bssid); + handleConnectionFailure(network, bssid, failureCode); } } @@ -1197,6 +1216,95 @@ public class WifiNetworkSuggestionsManager { } /** + * Send network connection failure event to app when an connection attempt failure. + * @param packageName package name to send event + * @param matchingSuggestion suggestion on this connection failure + * @param connectionEvent connection failure code + */ + private void sendConnectionFailureIfAllowed(String packageName, + @NonNull WifiNetworkSuggestion matchingSuggestion, + int connectionEvent) { + ExternalCallbackTracker<ISuggestionConnectionStatusListener> listenersTracker = + mSuggestionStatusListenerPerApp.get(packageName); + if (listenersTracker == null || listenersTracker.getNumCallbacks() == 0) { + return; + } + try { + mWifiPermissionsUtil.enforceCanAccessScanResults( + packageName, matchingSuggestion.suggestorUid); + } catch (SecurityException se) { + Log.w(TAG, "Permission denied for sending connection failure event to " + packageName); + return; + } + if (mVerboseLoggingEnabled) { + Log.v(TAG, "Sending connection failure event to " + packageName); + } + for (ISuggestionConnectionStatusListener listener : listenersTracker.getCallbacks()) { + try { + listener.onConnectionStatus(matchingSuggestion, + internalConnectionEventToSuggestionFailureCode(connectionEvent)); + } catch (RemoteException e) { + Log.e(TAG, "sendNetworkCallback: remote exception -- " + e); + } + } + } + + private @WifiManager.SuggestionConnectionStatusCode + int internalConnectionEventToSuggestionFailureCode(int connectionEvent) { + switch (connectionEvent) { + case WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION: + case WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT: + return WifiManager.STATUS_SUGGESTION_CONNECTION_FAILURE_ASSOCIATION; + case WifiMetrics.ConnectionEvent.FAILURE_SSID_TEMP_DISABLED: + case WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE: + return WifiManager.STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION; + case WifiMetrics.ConnectionEvent.FAILURE_DHCP: + return WifiManager.STATUS_SUGGESTION_CONNECTION_FAILURE_IP_PROVISIONING; + default: + return WifiManager.STATUS_SUGGESTION_CONNECTION_FAILURE_UNKNOWN; + } + + } + + /** + * Register a SuggestionConnectionStatusListener on network connection failure. + * @param binder IBinder instance to allow cleanup if the app dies. + * @param listener ISuggestionNetworkCallback instance to add. + * @param listenerIdentifier identifier of the listener, should be hash code of listener. + * @return true if succeed otherwise false. + */ + public boolean registerSuggestionConnectionStatusListener(@NonNull IBinder binder, + @NonNull ISuggestionConnectionStatusListener listener, + int listenerIdentifier, String packageName) { + ExternalCallbackTracker<ISuggestionConnectionStatusListener> listenersTracker = + mSuggestionStatusListenerPerApp.get(packageName); + if (listenersTracker == null) { + listenersTracker = + new ExternalCallbackTracker<>(mHandler); + } + listenersTracker.add(binder, listener, listenerIdentifier); + mSuggestionStatusListenerPerApp.put(packageName, listenersTracker); + return true; + } + + /** + * Unregister a listener on network connection failure. + * @param listenerIdentifier identifier of the listener, should be hash code of listener. + */ + public void unregisterSuggestionConnectionStatusListener(int listenerIdentifier, + String packageName) { + ExternalCallbackTracker<ISuggestionConnectionStatusListener> listenersTracker = + mSuggestionStatusListenerPerApp.get(packageName); + if (listenersTracker == null || listenersTracker.remove(listenerIdentifier) == null) { + Log.w(TAG, "unregisterSuggestionConnectionStatusListener: Listener[" + + listenerIdentifier + "] from " + packageName + " already unregister."); + } + if (listenersTracker.getNumCallbacks() == 0) { + mSuggestionStatusListenerPerApp.remove(packageName); + } + } + + /** * Dump of {@link WifiNetworkSuggestionsManager}. */ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java index 8c398f5c3..fb2ea0f69 100644 --- a/service/java/com/android/server/wifi/WifiServiceImpl.java +++ b/service/java/com/android/server/wifi/WifiServiceImpl.java @@ -55,6 +55,7 @@ import android.net.wifi.INetworkRequestMatchCallback; import android.net.wifi.IOnWifiUsabilityStatsListener; import android.net.wifi.IScanResultsListener; import android.net.wifi.ISoftApCallback; +import android.net.wifi.ISuggestionConnectionStatusListener; import android.net.wifi.ITrafficStateCallback; import android.net.wifi.ITxPacketCountListener; import android.net.wifi.ScanResult; @@ -67,6 +68,7 @@ import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.net.wifi.WifiManager.DeviceMobilityState; import android.net.wifi.WifiManager.LocalOnlyHotspotCallback; +import android.net.wifi.WifiManager.SuggestionConnectionStatusListener; import android.net.wifi.WifiNetworkSuggestion; import android.net.wifi.WifiScanner; import android.net.wifi.WifiSsid; @@ -3479,7 +3481,7 @@ public class WifiServiceImpl extends BaseWifiService { /** * See {@link WifiManager#addScanResultsListener(Executor, WifiManager.ScanResultsListener)} */ - public void registerScanResultsListener(IBinder binder, IScanResultsListener listener, + public void registerScanResultsListener(IBinder binder, @NonNull IScanResultsListener listener, int listenerIdentifier) { if (binder == null) { throw new IllegalArgumentException("Binder must not be null"); @@ -3514,4 +3516,46 @@ public class WifiServiceImpl extends BaseWifiService { .unregisterScanResultsListener(listenerIdentifier)); } + + /** + * See {@link WifiManager#addSuggestionConnectionStatusListener(Executor, + * SuggestionConnectionStatusListener)} + */ + public void registerSuggestionConnectionStatusListener(IBinder binder, + @NonNull ISuggestionConnectionStatusListener listener, + int listenerIdentifier, String packageName) { + if (binder == null) { + throw new IllegalArgumentException("Binder must not be null"); + } + if (listener == null) { + throw new IllegalArgumentException("listener must not be null"); + } + final int uid = Binder.getCallingUid(); + enforceAccessPermission(); + enforceLocationPermission(packageName, uid); + if (mVerboseLoggingEnabled) { + mLog.info("registerSuggestionConnectionStatusListener uid=%").c(uid).flush(); + } + mWifiThreadRunner.post(() -> + mWifiNetworkSuggestionsManager + .registerSuggestionConnectionStatusListener(binder, listener, + listenerIdentifier, packageName)); + } + + /** + * See {@link WifiManager#removeSuggestionConnectionStatusListener( + * SuggestionConnectionStatusListener)} + */ + public void unregisterSuggestionConnectionStatusListener( + int listenerIdentifier, String packageName) { + enforceAccessPermission(); + if (mVerboseLoggingEnabled) { + mLog.info("unregisterSuggestionConnectionStatusListener uid=%") + .c(Binder.getCallingUid()).flush(); + } + mWifiThreadRunner.post(() -> + mWifiNetworkSuggestionsManager + .unregisterSuggestionConnectionStatusListener(listenerIdentifier, + packageName)); + } } diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java index 5755c5858..19dd3c9e9 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java @@ -44,6 +44,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.Resources; import android.net.MacAddress; +import android.net.wifi.ISuggestionConnectionStatusListener; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; import android.net.wifi.WifiNetworkSuggestion; @@ -51,6 +52,7 @@ import android.net.wifi.WifiScanner; import android.net.wifi.hotspot2.PasspointConfiguration; import android.net.wifi.hotspot2.pps.HomeSp; import android.os.Handler; +import android.os.IBinder; import android.os.UserHandle; import android.os.test.TestLooper; import android.test.suitebuilder.annotation.SmallTest; @@ -91,6 +93,7 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { private static final String TEST_FQDN = "FQDN"; private static final int TEST_UID_1 = 5667; private static final int TEST_UID_2 = 4537; + private static final int NETWORK_CALLBACK_ID = 1100; private static final int VALID_CARRIER_ID = 1; private @Mock Context mContext; @@ -106,6 +109,8 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { private @Mock NetworkSuggestionStoreData mNetworkSuggestionStoreData; private @Mock WifiMetrics mWifiMetrics; private @Mock PasspointManager mPasspointManager; + private @Mock ISuggestionConnectionStatusListener mListener; + private @Mock IBinder mBinder; private TestLooper mLooper; private ArgumentCaptor<AppOpsManager.OnOpChangedListener> mAppOpChangedListenerCaptor = ArgumentCaptor.forClass(AppOpsManager.OnOpChangedListener.class); @@ -845,9 +850,13 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { * {@link WifiNetworkSuggestion#isAppInteractionRequired} flag set. * b) The app holds location permission. * This should trigger a broadcast to the app. + * This should trigger not a connection failure callback to the app. */ @Test - public void testOnNetworkConnectionSuccessWithOneMatch() { + public void testOnNetworkConnectionSuccessWithOneMatch() throws Exception { + assertTrue(mWifiNetworkSuggestionsManager + .registerSuggestionConnectionStatusListener(mBinder, mListener, + NETWORK_CALLBACK_ID, TEST_PACKAGE_1)); WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, TEST_UID_1, TEST_PACKAGE_1); @@ -880,12 +889,64 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { mInorder.verifyNoMoreInteractions(); } + @Test + public void testOnNetworkConnectionFailureWithOneMatchButCallbackOnBinderDied() + throws Exception { + ArgumentCaptor<IBinder.DeathRecipient> drCaptor = + ArgumentCaptor.forClass(IBinder.DeathRecipient.class); + assertTrue(mWifiNetworkSuggestionsManager + .registerSuggestionConnectionStatusListener(mBinder, mListener, + NETWORK_CALLBACK_ID, TEST_PACKAGE_1)); + verify(mBinder).linkToDeath(drCaptor.capture(), anyInt()); + WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( + WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, TEST_UID_1, + TEST_PACKAGE_1); + List<WifiNetworkSuggestion> networkSuggestionList = + new ArrayList<WifiNetworkSuggestion>() {{ + add(networkSuggestion); + }}; + assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, + mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, + TEST_PACKAGE_1)); + mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); + // Simulate binder was died. + drCaptor.getValue().binderDied(); + mLooper.dispatchAll(); + verify(mBinder).unlinkToDeath(any(), anyInt()); + // Simulate connecting to the network. + WifiConfiguration connectNetwork = + new WifiConfiguration(networkSuggestion.wifiConfiguration); + connectNetwork.fromWifiNetworkSuggestion = true; + connectNetwork.ephemeral = true; + connectNetwork.creatorName = TEST_APP_NAME_1; + mWifiNetworkSuggestionsManager.handleConnectionAttemptEnded( + WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE, + connectNetwork, TEST_BSSID); + + verify(mWifiMetrics).incrementNetworkSuggestionApiNumConnectFailure(); + // Verify no connection failure event was sent out. + mInorder.verify(mWifiPermissionsUtil, never()) + .enforceCanAccessScanResults(TEST_PACKAGE_1, TEST_UID_1); + verify(mListener, never()).onConnectionStatus(any(), anyInt()); + + // Verify no more broadcast were sent out. + mInorder.verify(mContext, never()).sendBroadcastAsUser( + any(), any()); + } + /** * Verify a successful lookup of a single network suggestion matching the current network * connection failure. + * a) The corresponding network suggestion has the + * {@link WifiNetworkSuggestion#isAppInteractionRequired} flag set. + * b) The app holds location permission. + * This should trigger a connection failure callback to the app */ @Test - public void testOnNetworkConnectionFailureWithOneMatch() { + public void testOnNetworkConnectionFailureWithOneMatch() throws Exception { + assertTrue(mWifiNetworkSuggestionsManager + .registerSuggestionConnectionStatusListener(mBinder, mListener, + NETWORK_CALLBACK_ID, TEST_PACKAGE_1)); WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion( WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, TEST_UID_1, TEST_PACKAGE_1); @@ -906,14 +967,17 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { mWifiNetworkSuggestionsManager.handleConnectionAttemptEnded( WifiMetrics.ConnectionEvent.FAILURE_DHCP, connectNetwork, TEST_BSSID); + // Verify right callback were sent out. + mInorder.verify(mWifiPermissionsUtil) + .enforceCanAccessScanResults(TEST_PACKAGE_1, TEST_UID_1); + verify(mListener) + .onConnectionStatus(networkSuggestion, + WifiManager.STATUS_SUGGESTION_CONNECTION_FAILURE_IP_PROVISIONING); verify(mWifiMetrics).incrementNetworkSuggestionApiNumConnectFailure(); // Verify no more broadcast were sent out. - mInorder.verify(mWifiPermissionsUtil, never()).enforceCanAccessScanResults( - anyString(), anyInt()); mInorder.verify(mContext, never()).sendBroadcastAsUser( any(), any()); - } /** @@ -1138,6 +1202,8 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1)); + verify(mWifiPermissionsUtil, times(2)) + .checkNetworkCarrierProvisioningPermission(TEST_UID_1); assertFalse(mWifiNetworkSuggestionsManager.hasUserApprovedForApp(TEST_PACKAGE_1)); WifiConfiguration connectNetwork = @@ -1176,6 +1242,8 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1)); + verify(mWifiPermissionsUtil, times(2)) + .checkNetworkCarrierProvisioningPermission(TEST_UID_1); mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); WifiConfiguration connectNetwork = @@ -1214,6 +1282,8 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1)); + verify(mWifiPermissionsUtil, times(2)) + .checkNetworkCarrierProvisioningPermission(TEST_UID_1); mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1); doThrow(new SecurityException()) diff --git a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java index a436d97c2..2d994259a 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java @@ -95,6 +95,7 @@ import android.net.wifi.INetworkRequestMatchCallback; import android.net.wifi.IOnWifiUsabilityStatsListener; import android.net.wifi.IScanResultsListener; import android.net.wifi.ISoftApCallback; +import android.net.wifi.ISuggestionConnectionStatusListener; import android.net.wifi.ITrafficStateCallback; import android.net.wifi.ITxPacketCountListener; import android.net.wifi.ScanResult; @@ -201,6 +202,7 @@ public class WifiServiceImplTest extends WifiBaseTest { 5, 1100002, "\"magenta\"", false, false, null, null)); private static final int TEST_AP_FREQUENCY = 2412; private static final int TEST_AP_BANDWIDTH = SoftApInfo.CHANNEL_WIDTH_20MHZ; + private static final int NETWORK_CALLBACK_ID = 1100; private SoftApInfo mTestSoftApInfo; private AsyncChannel mAsyncChannel; @@ -274,6 +276,7 @@ public class WifiServiceImplTest extends WifiBaseTest { @Mock SarManager mSarManager; @Mock ILocalOnlyHotspotCallback mLohsCallback; @Mock IScanResultsListener mClientScanResultsListener; + @Mock ISuggestionConnectionStatusListener mSuggestionConnectionStatusListener; WifiLog mLog = new LogcatLog(TAG); @@ -4390,6 +4393,55 @@ public class WifiServiceImplTest extends WifiBaseTest { verify(mScanRequestProxy).unregisterScanResultsListener(eq(listenerIdentifier)); } + /** + * Test register callback without permission. + */ + @Test(expected = SecurityException.class) + public void testRegisterSuggestionNetworkCallbackWithMissingPermission() { + doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission( + eq(android.Manifest.permission.ACCESS_WIFI_STATE), eq("WifiService")); + mWifiServiceImpl.registerSuggestionConnectionStatusListener(mAppBinder, + mSuggestionConnectionStatusListener, NETWORK_CALLBACK_ID, TEST_PACKAGE_NAME); + } + + /** + * Test register callback without callback + */ + @Test(expected = IllegalArgumentException.class) + public void testRegisterSuggestionNetworkCallbackWithIllegalArgument() { + mWifiServiceImpl.registerSuggestionConnectionStatusListener(mAppBinder, null, + NETWORK_CALLBACK_ID, TEST_PACKAGE_NAME); + } + + /** + * Test unregister callback without permission. + */ + @Test(expected = SecurityException.class) + public void testUnregisterSuggestionNetworkCallbackWithMissingPermission() { + doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission( + eq(android.Manifest.permission.ACCESS_WIFI_STATE), eq("WifiService")); + mWifiServiceImpl.unregisterSuggestionConnectionStatusListener( + NETWORK_CALLBACK_ID, TEST_PACKAGE_NAME); + } + + /** + * Test register nad unregister callback will go to WifiNetworkSuggestionManager + */ + @Test + public void testRegisterUnregisterSuggestionNetworkCallback() throws Exception { + mWifiServiceImpl.registerSuggestionConnectionStatusListener(mAppBinder, + mSuggestionConnectionStatusListener, NETWORK_CALLBACK_ID, TEST_PACKAGE_NAME); + mLooper.dispatchAll(); + verify(mWifiNetworkSuggestionsManager).registerSuggestionConnectionStatusListener( + eq(mAppBinder), eq(mSuggestionConnectionStatusListener), eq(NETWORK_CALLBACK_ID), + eq(TEST_PACKAGE_NAME)); + mWifiServiceImpl.unregisterSuggestionConnectionStatusListener(NETWORK_CALLBACK_ID, + TEST_PACKAGE_NAME); + mLooper.dispatchAll(); + verify(mWifiNetworkSuggestionsManager).unregisterSuggestionConnectionStatusListener( + eq(NETWORK_CALLBACK_ID), eq(TEST_PACKAGE_NAME)); + } + /** * Test to verify that the lock mode is verified before dispatching the operation |