* Registers a callback for Soft AP. See {@link SoftApCallback}. Caller will receive the current
* soft AP state and number of connected devices immediately after a successful call to this API
* via callback. Note that receiving an immediate WIFI_AP_STATE_FAILED value for soft AP state
- * indicates that the latest attempt to start soft AP has failed. Only one registered callback
- * is allowed for each process, and multiple calls to this API from the same process will simply
- * replace the previously registered callback with the new one.
+ * indicates that the latest attempt to start soft AP has failed. Caller can unregister a
+ * previously registered callback using {@link unregisterSoftApCallback}
+ * <p>
+ * Applications should have the
+ * {@link android.Manifest.permission#NETWORK_SETTINGS NETWORK_SETTINGS} permission. Callers
+ * without the permission will trigger a {@link java.lang.SecurityException}.
+ * <p>
*
- * @param callback A callback for the number of connected clients.
- * @param handler The Handler on whose thread to execute the callbacks of the {@code
- * callback} object. If a null is provided then the application's main thread
- * will be used.
+ * @param callback Callback for soft AP events
+ * @param handler The Handler on whose thread to execute the callbacks of the {@code callback}
+ * object. If null, then the application's main thread will be used.
*
* @hide
*/
public void registerSoftApCallback(@NonNull SoftApCallback callback,
@Nullable Handler handler) {
if (callback == null) throw new IllegalArgumentException("callback cannot be null");
-
Log.v(TAG, "registerSoftApCallback: callback=" + callback + ", handler=" + handler);
Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper();
Binder binder = new Binder();
try {
- mService.registerSoftApCallback(binder, new SoftApCallbackProxy(looper, callback));
+ mService.registerSoftApCallback(binder, new SoftApCallbackProxy(looper, callback),
+ callback.hashCode());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Allow callers to unregister a previously registered callback. After calling this method,
+ * applications will no longer receive soft AP events.
+ *
+ * @param callback Callback to unregister for soft AP events
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+ public void unregisterSoftApCallback(@NonNull SoftApCallback callback) {
+ if (callback == null) throw new IllegalArgumentException("callback cannot be null");
+ Log.v(TAG, "unregisterSoftApCallback: callback=" + callback);
+
+ try {
+ mService.unregisterSoftApCallback(callback.hashCode());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import static org.mockito.Mockito.*;
import android.content.Context;
/**
* Verify an IllegalArgumentException is thrown if callback is not provided.
*/
- @Test(expected = IllegalArgumentException.class)
+ @Test
public void registerSoftApCallbackThrowsIllegalArgumentExceptionOnNullArgumentForCallback() {
- mWifiManager.registerSoftApCallback(null, mHandler);
+ try {
+ mWifiManager.registerSoftApCallback(null, mHandler);
+ fail("expected IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ /**
+ * Verify an IllegalArgumentException is thrown if callback is not provided.
+ */
+ @Test
+ public void unregisterSoftApCallbackThrowsIllegalArgumentExceptionOnNullArgumentForCallback() {
+ try {
+ mWifiManager.unregisterSoftApCallback(null);
+ fail("expected IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ }
}
/**
public void registerSoftApCallbackCallGoesToWifiServiceImpl() throws Exception {
mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler);
verify(mWifiService).registerSoftApCallback(any(IBinder.class),
- any(ISoftApCallback.Stub.class));
+ any(ISoftApCallback.Stub.class), anyInt());
+ }
+
+ /**
+ * Verify the call to unregisterSoftApCallback goes to WifiServiceImpl.
+ */
+ @Test
+ public void unregisterSoftApCallbackCallGoesToWifiServiceImpl() throws Exception {
+ ArgumentCaptor<Integer> callbackIdentifier = ArgumentCaptor.forClass(Integer.class);
+ mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler);
+ verify(mWifiService).registerSoftApCallback(any(IBinder.class),
+ any(ISoftApCallback.Stub.class), callbackIdentifier.capture());
+
+ mWifiManager.unregisterSoftApCallback(mSoftApCallback);
+ verify(mWifiService).unregisterSoftApCallback(eq((int) callbackIdentifier.getValue()));
}
/*
ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler);
- verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture());
+ verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
+ anyInt());
callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_ENABLED, 0);
mLooper.dispatchAll();
ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler);
- verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture());
+ verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
+ anyInt());
final int testNumClients = 3;
callbackCaptor.getValue().onNumClientsChanged(testNumClients);
ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler);
- verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture());
+ verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
+ anyInt());
final int testNumClients = 5;
callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_ENABLING, 0);
TestLooper altLooper = new TestLooper();
Handler altHandler = new Handler(altLooper.getLooper());
mWifiManager.registerSoftApCallback(mSoftApCallback, altHandler);
- verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture());
+ verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
+ anyInt());
callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_ENABLED, 0);
altLooper.dispatchAll();
mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler);
mLooper.dispatchAll();
verify(mWifiService).registerSoftApCallback(any(IBinder.class),
- any(ISoftApCallback.Stub.class));
+ any(ISoftApCallback.Stub.class), anyInt());
verify(mContext, never()).getMainLooper();
}