diff --git a/api/system-current.txt b/api/system-current.txt index 5d3c2660d486f..2edab4d364649 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -4657,6 +4657,13 @@ package android.net.wifi { field @Deprecated public byte id; } + public final class WifiClient implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public android.net.MacAddress getMacAddress(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + @Deprecated public class WifiConfiguration implements android.os.Parcelable { method @Deprecated public boolean hasNoInternetAccess(); method @Deprecated public boolean isEphemeral(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java index db2be0e78e9a3..4b56f037f8ed1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java @@ -21,6 +21,7 @@ import static com.android.systemui.Dependency.MAIN_HANDLER_NAME; import android.app.ActivityManager; import android.content.Context; import android.net.ConnectivityManager; +import android.net.wifi.WifiClient; import android.net.wifi.WifiManager; import android.os.Handler; import android.os.UserManager; @@ -29,12 +30,14 @@ import android.util.Log; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.List; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; /** + * Controller used to retrieve information related to a hotspot. */ @Singleton public class HotspotControllerImpl implements HotspotController, WifiManager.SoftApCallback { @@ -49,10 +52,11 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof private final Context mContext; private int mHotspotState; - private int mNumConnectedDevices; + private volatile int mNumConnectedDevices; private boolean mWaitingForTerminalState; /** + * Controller used to retrieve information related to a hotspot. */ @Inject public HotspotControllerImpl(Context context, @Named(MAIN_HANDLER_NAME) Handler mainHandler) { @@ -96,7 +100,6 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof /** * Adds {@code callback} to the controller. The controller will update the callback on state * changes. It will immediately trigger the callback added to notify current state. - * @param callback */ @Override public void addCallback(Callback callback) { @@ -108,11 +111,13 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof if (mCallbacks.size() == 1) { mWifiManager.registerSoftApCallback(this, mMainHandler); } else { - // mWifiManager#registerSoftApCallback triggers a call to onNumClientsChanged - // on the Main Handler. In order to always update the callback on added, we - // make this call when adding callbacks after the first. + // mWifiManager#registerSoftApCallback triggers a call to + // onConnectedClientsChanged on the Main Handler. In order to always update + // the callback on added, we make this call when adding callbacks after the + // first. mMainHandler.post(() -> - callback.onHotspotChanged(isHotspotEnabled(), mNumConnectedDevices)); + callback.onHotspotChanged(isHotspotEnabled(), + mNumConnectedDevices)); } } } @@ -217,8 +222,8 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof } @Override - public void onNumClientsChanged(int numConnectedDevices) { - mNumConnectedDevices = numConnectedDevices; + public void onConnectedClientsChanged(List clients) { + mNumConnectedDevices = clients.size(); fireHotspotChangedCallback(); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java index 3e4c4d6a7a8a9..7f32ad5c6c1f9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java @@ -42,6 +42,8 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; +import java.util.ArrayList; + @SmallTest @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper @@ -67,7 +69,8 @@ public class HotspotControllerImplTest extends SysuiTestCase { mContext.addMockSystemService(WifiManager.class, mWifiManager); doAnswer((InvocationOnMock invocation) -> { - ((WifiManager.SoftApCallback) invocation.getArgument(0)).onNumClientsChanged(1); + ((WifiManager.SoftApCallback) invocation.getArgument(0)) + .onConnectedClientsChanged(new ArrayList<>()); return null; }).when(mWifiManager).registerSoftApCallback(any(WifiManager.SoftApCallback.class), any(Handler.class)); diff --git a/wifi/java/android/net/wifi/ISoftApCallback.aidl b/wifi/java/android/net/wifi/ISoftApCallback.aidl index b8d2971e74bb9..8a252dd1e4474 100644 --- a/wifi/java/android/net/wifi/ISoftApCallback.aidl +++ b/wifi/java/android/net/wifi/ISoftApCallback.aidl @@ -16,6 +16,8 @@ package android.net.wifi; +import android.net.wifi.WifiClient; + /** * Interface for Soft AP callback. * @@ -36,9 +38,9 @@ oneway interface ISoftApCallback void onStateChanged(int state, int failureReason); /** - * Service to manager callback providing number of connected clients. + * Service to manager callback providing connected client's information. * - * @param numClients number of connected clients + * @param clients the currently connected clients */ - void onNumClientsChanged(int numClients); + void onConnectedClientsChanged(in List clients); } diff --git a/wifi/java/android/net/wifi/WifiClient.aidl b/wifi/java/android/net/wifi/WifiClient.aidl new file mode 100644 index 0000000000000..accdaddfc848c --- /dev/null +++ b/wifi/java/android/net/wifi/WifiClient.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi; + +@JavaOnlyStableParcelable parcelable WifiClient; \ No newline at end of file diff --git a/wifi/java/android/net/wifi/WifiClient.java b/wifi/java/android/net/wifi/WifiClient.java new file mode 100644 index 0000000000000..3e09580802cea --- /dev/null +++ b/wifi/java/android/net/wifi/WifiClient.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi; + +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.net.MacAddress; +import android.os.Parcel; +import android.os.Parcelable; + +import com.android.internal.util.Preconditions; + +import java.util.Objects; + +/** @hide */ +@SystemApi +public final class WifiClient implements Parcelable { + + private final MacAddress mMacAddress; + + /** + * The mac address of this client. + */ + @NonNull + public MacAddress getMacAddress() { + return mMacAddress; + } + + private WifiClient(Parcel in) { + mMacAddress = in.readParcelable(null); + } + + /** @hide */ + public WifiClient(@NonNull MacAddress macAddress) { + Preconditions.checkNotNull(macAddress, "mMacAddress must not be null."); + + this.mMacAddress = macAddress; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeParcelable(mMacAddress, flags); + } + + @NonNull + public static final Creator CREATOR = new Creator() { + public WifiClient createFromParcel(Parcel in) { + return new WifiClient(in); + } + + public WifiClient[] newArray(int size) { + return new WifiClient[size]; + } + }; + + @NonNull + @Override + public String toString() { + return "WifiClient{" + + "mMacAddress=" + mMacAddress + + '}'; + } + + @Override + public boolean equals(@NonNull Object o) { + if (this == o) return true; + if (!(o instanceof WifiClient)) return false; + WifiClient client = (WifiClient) o; + return mMacAddress.equals(client.mMacAddress); + } + + @Override + public int hashCode() { + return Objects.hash(mMacAddress); + } +} + + diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 0d2e8166994ca..d9c1bf22d4778 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -3125,21 +3125,22 @@ public class WifiManager { /** * Called when soft AP state changes. * - * @param state new new AP state. One of {@link #WIFI_AP_STATE_DISABLED}, - * {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED}, - * {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED} + * @param state new new AP state. One of {@link #WIFI_AP_STATE_DISABLED}, + * {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED}, + * {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED} * @param failureReason reason when in failed state. One of - * {@link #SAP_START_FAILURE_GENERAL}, {@link #SAP_START_FAILURE_NO_CHANNEL} + * {@link #SAP_START_FAILURE_GENERAL}, + * {@link #SAP_START_FAILURE_NO_CHANNEL} */ - public abstract void onStateChanged(@WifiApState int state, + void onStateChanged(@WifiApState int state, @SapStartFailure int failureReason); /** - * Called when number of connected clients to soft AP changes. + * Called when the connected clients to soft AP changes. * - * @param numClients number of connected clients + * @param clients the currently connected clients */ - public abstract void onNumClientsChanged(int numClients); + void onConnectedClientsChanged(@NonNull List clients); } /** @@ -3162,18 +3163,21 @@ public class WifiManager { Log.v(TAG, "SoftApCallbackProxy: onStateChanged: state=" + state + ", failureReason=" + failureReason); } + mHandler.post(() -> { mCallback.onStateChanged(state, failureReason); }); } @Override - public void onNumClientsChanged(int numClients) { + public void onConnectedClientsChanged(List clients) { if (mVerboseLoggingEnabled) { - Log.v(TAG, "SoftApCallbackProxy: onNumClientsChanged: numClients=" + numClients); + Log.v(TAG, "SoftApCallbackProxy: onConnectedClientsChanged: clients=" + + clients.size() + " clients"); } + mHandler.post(() -> { - mCallback.onNumClientsChanged(numClients); + mCallback.onConnectedClientsChanged(clients); }); } } diff --git a/wifi/tests/Android.mk b/wifi/tests/Android.mk index 401b652289cda..3453d6ec827f2 100644 --- a/wifi/tests/Android.mk +++ b/wifi/tests/Android.mk @@ -49,6 +49,7 @@ LOCAL_STATIC_JAVA_LIBRARIES := \ core-test-rules \ guava \ mockito-target-minus-junit4 \ + net-tests-utils \ frameworks-base-testutils \ truth-prebuilt \ diff --git a/wifi/tests/src/android/net/wifi/WifiClientTest.java b/wifi/tests/src/android/net/wifi/WifiClientTest.java new file mode 100644 index 0000000000000..42cab55305b94 --- /dev/null +++ b/wifi/tests/src/android/net/wifi/WifiClientTest.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi; + +import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals; +import static com.android.testutils.ParcelUtilsKt.assertParcelSane; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +import android.net.MacAddress; + +import androidx.test.filters.SmallTest; + +import org.junit.Test; + +/** + * Unit tests for {@link android.net.wifi.WifiClient}. + */ +@SmallTest +public class WifiClientTest { + private static final String INTERFACE_NAME = "wlan0"; + private static final String MAC_ADDRESS_STRING = "00:0a:95:9d:68:16"; + private static final MacAddress MAC_ADDRESS = MacAddress.fromString(MAC_ADDRESS_STRING); + + /** + * Verify parcel write/read with WifiClient. + */ + @Test + public void testWifiClientParcelWriteRead() throws Exception { + WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS); + + assertParcelSane(writeWifiClient, 1); + } + + /** + * Verify equals with WifiClient. + */ + @Test + public void testWifiClientEquals() throws Exception { + WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS); + WifiClient writeWifiClientEquals = new WifiClient(MAC_ADDRESS); + + assertEquals(writeWifiClient, writeWifiClientEquals); + assertEquals(writeWifiClient.hashCode(), writeWifiClientEquals.hashCode()); + assertFieldCountEquals(1, WifiClient.class); + } + + /** + * Verify not-equals with WifiClient. + */ + @Test + public void testWifiClientNotEquals() throws Exception { + final MacAddress macAddressNotEquals = MacAddress.fromString("00:00:00:00:00:00"); + WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS); + WifiClient writeWifiClientNotEquals = new WifiClient(macAddressNotEquals); + + assertNotEquals(writeWifiClient, writeWifiClientNotEquals); + assertNotEquals(writeWifiClient.hashCode(), writeWifiClientNotEquals.hashCode()); + } +} diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java index b75a1acf87c90..e14919452ba77 100644 --- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java +++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java @@ -101,8 +101,7 @@ public class WifiManagerTest { private static final String[] TEST_MAC_ADDRESSES = {"da:a1:19:0:0:0"}; @Mock Context mContext; - @Mock - android.net.wifi.IWifiManager mWifiService; + @Mock android.net.wifi.IWifiManager mWifiService; @Mock ApplicationInfo mApplicationInfo; @Mock WifiConfiguration mApConfig; @Mock IBinder mAppBinder; @@ -118,7 +117,8 @@ public class WifiManagerTest { private Messenger mWifiServiceMessenger; final ArgumentCaptor mMessengerCaptor = ArgumentCaptor.forClass(Messenger.class); - @Before public void setUp() throws Exception { + @Before + public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mLooper = new TestLooper(); mHandler = spy(new Handler(mLooper.getLooper())); @@ -214,7 +214,7 @@ public class WifiManagerTest { @Test public void testCreationOfLocalOnlyHotspotSubscription() throws Exception { try (WifiManager.LocalOnlyHotspotSubscription sub = - mWifiManager.new LocalOnlyHotspotSubscription()) { + mWifiManager.new LocalOnlyHotspotSubscription()) { sub.close(); } } @@ -757,17 +757,17 @@ public class WifiManagerTest { * Verify client-provided callback is being called through callback proxy */ @Test - public void softApCallbackProxyCallsOnNumClientsChanged() throws Exception { + public void softApCallbackProxyCallsOnConnectedClientsChanged() throws Exception { ArgumentCaptor callbackCaptor = ArgumentCaptor.forClass(ISoftApCallback.Stub.class); mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler); verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(), anyInt()); - final int testNumClients = 3; - callbackCaptor.getValue().onNumClientsChanged(testNumClients); + final List testClients = new ArrayList(); + callbackCaptor.getValue().onConnectedClientsChanged(testClients); mLooper.dispatchAll(); - verify(mSoftApCallback).onNumClientsChanged(testNumClients); + verify(mSoftApCallback).onConnectedClientsChanged(testClients); } /* @@ -781,14 +781,14 @@ public class WifiManagerTest { verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(), anyInt()); - final int testNumClients = 5; + final List testClients = new ArrayList(); callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_ENABLING, 0); - callbackCaptor.getValue().onNumClientsChanged(testNumClients); + callbackCaptor.getValue().onConnectedClientsChanged(testClients); callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL); mLooper.dispatchAll(); verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLING, 0); - verify(mSoftApCallback).onNumClientsChanged(testNumClients); + verify(mSoftApCallback).onConnectedClientsChanged(testClients); verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL); } @@ -1047,8 +1047,8 @@ public class WifiManagerTest { verifyNoMoreInteractions(mWifiService); } - /** -i * Verify that a call to cancel WPS immediately returns a failure. + /** + * Verify that a call to cancel WPS immediately returns a failure. */ @Test public void testCancelWpsImmediatelyFailsWithCallback() { @@ -1343,7 +1343,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Verify getting the factory MAC address. - * @throws Exception */ @Test public void testGetFactoryMacAddress() throws Exception { @@ -1390,7 +1389,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of isEnhancedOpenSupported - * @throws Exception */ @Test public void testIsEnhancedOpenSupported() throws Exception { @@ -1404,7 +1402,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of isWpa3SaeSupported - * @throws Exception */ @Test public void testIsWpa3SaeSupported() throws Exception { @@ -1418,7 +1415,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of isWpa3SuiteBSupported - * @throws Exception */ @Test public void testIsWpa3SuiteBSupported() throws Exception { @@ -1432,7 +1428,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of isEasyConnectSupported - * @throws Exception */ @Test public void testIsEasyConnectSupported() throws Exception { @@ -1446,7 +1441,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#addNetwork(WifiConfiguration)} - * @throws Exception */ @Test public void testAddNetwork() throws Exception { @@ -1463,7 +1457,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#addNetwork(WifiConfiguration)} - * @throws Exception */ @Test public void testUpdateNetwork() throws Exception { @@ -1485,7 +1478,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#enableNetwork(int, boolean)} - * @throws Exception */ @Test public void testEnableNetwork() throws Exception { @@ -1497,7 +1489,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#disableNetwork(int)} - * @throws Exception */ @Test public void testDisableNetwork() throws Exception { @@ -1509,7 +1500,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#disconnect()} - * @throws Exception */ @Test public void testDisconnect() throws Exception { @@ -1520,7 +1510,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#reconnect()} - * @throws Exception */ @Test public void testReconnect() throws Exception { @@ -1531,7 +1520,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#reassociate()} - * @throws Exception */ @Test public void testReassociate() throws Exception { @@ -1542,7 +1530,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#getSupportedFeatures()} - * @throws Exception */ @Test public void testGetSupportedFeatures() throws Exception { @@ -1569,7 +1556,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#getControllerActivityEnergyInfo()} - * @throws Exception */ @Test public void testGetControllerActivityEnergyInfo() throws Exception { @@ -1582,7 +1568,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#getConnectionInfo()} - * @throws Exception */ @Test public void testGetConnectionInfo() throws Exception { @@ -1594,7 +1579,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#isDualModeSupported()} ()} - * @throws Exception */ @Test public void testIsDualModeSupported() throws Exception { @@ -1605,7 +1589,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#isDualBandSupported()} - * @throws Exception */ @Test public void testIsDualBandSupported() throws Exception { @@ -1616,7 +1599,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#getDhcpInfo()} - * @throws Exception */ @Test public void testGetDhcpInfo() throws Exception { @@ -1629,7 +1611,6 @@ i * Verify that a call to cancel WPS immediately returns a failure. /** * Test behavior of {@link WifiManager#setWifiEnabled(boolean)} - * @throws Exception */ @Test public void testSetWifiEnabled() throws Exception {