wifi: Add instance identifier in SoftApInfo/WifiClient and infoList callback

1. The framework need to know the instance of the client connected to
know which instance is idled.

2. The framework need to know the instance of the soft AP info.

3. Add infoList callback support for dual APs mode.

AP+AP Part 5 includes:
1. Support forceClientDisconnect in dual AP mode.
2. Support dual SoftApInfo callback
   a. New callback onInfoListChanged
   b. Add instanceIdentifier in SoftApInfo but it is used only in
   framework.
   c. Add instanceIdentifier in WifiClient but it is used only in
   framework.

Bug: 162686273
Test: FrameworksWifiApiTests
Change-Id: I207831ff15a3044316556d61a72542ff35c94e74
This commit is contained in:
lesl
2020-12-03 19:52:18 +08:00
parent 62d862082b
commit d3d17acd9c
8 changed files with 171 additions and 24 deletions

View File

@@ -632,6 +632,7 @@ package android.net.wifi {
method public default void onCapabilityChanged(@NonNull android.net.wifi.SoftApCapability);
method public default void onConnectedClientsChanged(@NonNull java.util.List<android.net.wifi.WifiClient>);
method public default void onInfoChanged(@NonNull android.net.wifi.SoftApInfo);
method public default void onInfoListChanged(@NonNull java.util.List<android.net.wifi.SoftApInfo>);
method public default void onStateChanged(int, int);
}

View File

@@ -53,6 +53,12 @@ oneway interface ISoftApCallback
*/
void onInfoChanged(in SoftApInfo softApInfo);
/**
* Service to manager callback providing informations of softap.
*
* @param softApInfoList is the list of the softap informations. {@link SoftApInfo}
*/
void onInfoListChanged(in List<SoftApInfo> softApInfoList);
/**
* Service to manager callback providing capability of softap.

View File

@@ -96,6 +96,10 @@ public final class SoftApInfo implements Parcelable {
@Nullable
private MacAddress mBssid;
/** The identifier of the AP instance which AP resides on with current info. */
@Nullable
private String mApInstanceIdentifier;
/**
* The operational mode of the AP.
*/
@@ -195,6 +199,28 @@ public final class SoftApInfo implements Parcelable {
return mWifiStandard;
}
/**
* Set the AP instance identifier.
* @hide
*/
public void setApInstanceIdentifier(@NonNull String apInstanceIdentifier) {
mApInstanceIdentifier = apInstanceIdentifier;
}
/**
* Get the AP instance identifier.
*
* The AP instance identifier is a unique identity which can be used to
* associate the {@link SoftApInfo} to a specific {@link WifiClient}
* - see {@link WifiClient#getApInstanceIdentifier()}
*
* @hide
*/
@Nullable
public String getApInstanceIdentifier() {
return mApInstanceIdentifier;
}
/**
* @hide
*/
@@ -204,6 +230,7 @@ public final class SoftApInfo implements Parcelable {
mBandwidth = source.mBandwidth;
mBssid = source.mBssid;
mWifiStandard = source.mWifiStandard;
mApInstanceIdentifier = source.mApInstanceIdentifier;
}
}
@@ -226,6 +253,7 @@ public final class SoftApInfo implements Parcelable {
dest.writeInt(mBandwidth);
dest.writeParcelable(mBssid, flags);
dest.writeInt(mWifiStandard);
dest.writeString(mApInstanceIdentifier);
}
@NonNull
@@ -237,6 +265,7 @@ public final class SoftApInfo implements Parcelable {
info.mBandwidth = in.readInt();
info.mBssid = in.readParcelable(MacAddress.class.getClassLoader());
info.mWifiStandard = in.readInt();
info.mApInstanceIdentifier = in.readString();
return info;
}
@@ -254,6 +283,7 @@ public final class SoftApInfo implements Parcelable {
sbuf.append(", frequency= ").append(mFrequency);
if (mBssid != null) sbuf.append(",bssid=").append(mBssid.toString());
sbuf.append(", wifiStandard= ").append(mWifiStandard);
sbuf.append(", mApInstanceIdentifier= ").append(mApInstanceIdentifier);
sbuf.append("}");
return sbuf.toString();
}
@@ -266,11 +296,12 @@ public final class SoftApInfo implements Parcelable {
return mFrequency == softApInfo.mFrequency
&& mBandwidth == softApInfo.mBandwidth
&& Objects.equals(mBssid, softApInfo.mBssid)
&& mWifiStandard == softApInfo.mWifiStandard;
&& mWifiStandard == softApInfo.mWifiStandard
&& Objects.equals(mApInstanceIdentifier, softApInfo.mApInstanceIdentifier);
}
@Override
public int hashCode() {
return Objects.hash(mFrequency, mBandwidth, mBssid, mWifiStandard);
return Objects.hash(mFrequency, mBandwidth, mBssid, mWifiStandard, mApInstanceIdentifier);
}
}

View File

@@ -30,6 +30,9 @@ public final class WifiClient implements Parcelable {
private final MacAddress mMacAddress;
/** The identifier of the AP instance which the client connected. */
private final String mApInstanceIdentifier;
/**
* The mac address of this client.
*/
@@ -38,15 +41,30 @@ public final class WifiClient implements Parcelable {
return mMacAddress;
}
/**
* Get AP instance identifier.
*
* The AP instance identifier is a unique identity which can be used to
* associate the {@link SoftApInfo} to a specific {@link WifiClient}
* - see {@link SoftApInfo#getApInstanceIdentifier()}
* @hide
*/
@NonNull
public String getApInstanceIdentifier() {
return mApInstanceIdentifier;
}
private WifiClient(Parcel in) {
mMacAddress = in.readParcelable(null);
mApInstanceIdentifier = in.readString();
}
/** @hide */
public WifiClient(@NonNull MacAddress macAddress) {
public WifiClient(@NonNull MacAddress macAddress, @NonNull String apInstanceIdentifier) {
Objects.requireNonNull(macAddress, "mMacAddress must not be null.");
this.mMacAddress = macAddress;
this.mApInstanceIdentifier = apInstanceIdentifier;
}
@Override
@@ -57,6 +75,7 @@ public final class WifiClient implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeParcelable(mMacAddress, flags);
dest.writeString(mApInstanceIdentifier);
}
@NonNull
@@ -75,6 +94,7 @@ public final class WifiClient implements Parcelable {
public String toString() {
return "WifiClient{"
+ "mMacAddress=" + mMacAddress
+ "mApInstanceIdentifier=" + mApInstanceIdentifier
+ '}';
}
@@ -83,13 +103,12 @@ public final class WifiClient implements Parcelable {
if (this == o) return true;
if (!(o instanceof WifiClient)) return false;
WifiClient client = (WifiClient) o;
return mMacAddress.equals(client.mMacAddress);
return Objects.equals(mMacAddress, client.mMacAddress)
&& mApInstanceIdentifier.equals(client.mApInstanceIdentifier);
}
@Override
public int hashCode() {
return Objects.hash(mMacAddress);
return Objects.hash(mMacAddress, mApInstanceIdentifier);
}
}

View File

@@ -3985,12 +3985,35 @@ public class WifiManager {
/**
* Called when information of softap changes.
*
* Note: this API is only valid when the Soft AP is configured as a single AP
* - not as a bridged AP (2 Soft APs). When the Soft AP is configured as bridged AP
* this callback will not be triggered - use the
* {@link #onInfoListChanged(List<SoftApInfo>)} callback in bridged AP mode.
*
* @param softApInfo is the softap information. {@link SoftApInfo}
*/
default void onInfoChanged(@NonNull SoftApInfo softApInfo) {
// Do nothing: can be updated to add SoftApInfo details (e.g. channel) to the UI.
}
/**
* Called when information of softap changes.
*
* The number of the information elements in the list depends on Soft AP configuration
* and state.
* For instance, an empty list will be returned when the Soft AP is disabled.
* One information element will be returned in the list when the Soft AP is configured
* as a single AP, and two information elements will be returned in the list
* when the Soft AP is configured in bridged mode.
*
* See {@link #isBridgedApConcurrencySupported()} for the detail of the bridged AP.
*
* @param softApInfoList is the list of the softap information elements. {@link SoftApInfo}
*/
default void onInfoListChanged(@NonNull List<SoftApInfo> softApInfoList) {
// Do nothing: can be updated to add SoftApInfo details (e.g. channel) to the UI.
}
/**
* Called when capability of softap changes.
*
@@ -4070,6 +4093,19 @@ public class WifiManager {
});
}
@Override
public void onInfoListChanged(List<SoftApInfo> softApInfoList) {
if (mVerboseLoggingEnabled) {
Log.v(TAG, "SoftApCallbackProxy: onInfoListChange: softApInfoList="
+ softApInfoList);
}
Binder.clearCallingIdentity();
mExecutor.execute(() -> {
mCallback.onInfoListChanged(softApInfoList);
});
}
@Override
public void onCapabilityChanged(SoftApCapability capability) {
if (mVerboseLoggingEnabled) {

View File

@@ -32,17 +32,22 @@ import org.junit.Test;
*/
@SmallTest
public class SoftApInfoTest {
private static final String TEST_AP_INSTANCE = "wlan1";
private static final int TEST_FREQUENCY = 2412;
private static final int TEST_BANDWIDTH = SoftApInfo.CHANNEL_WIDTH_20MHZ;
private static final int TEST_WIFI_STANDARD = ScanResult.WIFI_STANDARD_LEGACY;
private static final MacAddress TEST_AP_MAC = MacAddress.fromString("aa:bb:cc:dd:ee:ff");
/**
* Verifies copy constructor.
*/
@Test
public void testCopyOperator() throws Exception {
SoftApInfo info = new SoftApInfo();
info.setFrequency(2412);
info.setBandwidth(SoftApInfo.CHANNEL_WIDTH_20MHZ);
info.setBssid(MacAddress.fromString("aa:bb:cc:dd:ee:ff"));
info.setWifiStandard(ScanResult.WIFI_STANDARD_LEGACY);
info.setFrequency(TEST_FREQUENCY);
info.setBandwidth(TEST_BANDWIDTH);
info.setBssid(TEST_AP_MAC);
info.setWifiStandard(TEST_WIFI_STANDARD);
info.setApInstanceIdentifier(TEST_AP_INSTANCE);
SoftApInfo copiedInfo = new SoftApInfo(info);
@@ -57,10 +62,11 @@ public class SoftApInfoTest {
@Test
public void testParcelOperation() throws Exception {
SoftApInfo info = new SoftApInfo();
info.setFrequency(2412);
info.setBandwidth(SoftApInfo.CHANNEL_WIDTH_20MHZ);
info.setBssid(MacAddress.fromString("aa:bb:cc:dd:ee:ff"));
info.setWifiStandard(ScanResult.WIFI_STANDARD_LEGACY);
info.setFrequency(TEST_FREQUENCY);
info.setBandwidth(TEST_BANDWIDTH);
info.setBssid(TEST_AP_MAC);
info.setWifiStandard(TEST_WIFI_STANDARD);
info.setApInstanceIdentifier(TEST_AP_INSTANCE);
Parcel parcelW = Parcel.obtain();
info.writeToParcel(parcelW, 0);
@@ -88,6 +94,27 @@ public class SoftApInfoTest {
if (SdkLevel.isAtLeastS()) {
assertEquals(info.getBssid(), null);
assertEquals(info.getWifiStandard(), ScanResult.WIFI_STANDARD_UNKNOWN);
assertEquals(info.getApInstanceIdentifier(), null);
}
}
/**
* Verifies the set/get method same as expected.
*/
@Test
public void testGetXXXAlignedWithSetXXX() throws Exception {
SoftApInfo info = new SoftApInfo();
info.setFrequency(TEST_FREQUENCY);
info.setBandwidth(TEST_BANDWIDTH);
info.setBssid(TEST_AP_MAC);
info.setWifiStandard(TEST_WIFI_STANDARD);
info.setApInstanceIdentifier(TEST_AP_INSTANCE);
assertEquals(info.getFrequency(), TEST_FREQUENCY);
assertEquals(info.getBandwidth(), TEST_BANDWIDTH);
if (SdkLevel.isAtLeastS()) {
assertEquals(info.getBssid(), TEST_AP_MAC);
assertEquals(info.getWifiStandard(), TEST_WIFI_STANDARD);
assertEquals(info.getApInstanceIdentifier(), TEST_AP_INSTANCE);
}
}

View File

@@ -42,9 +42,9 @@ public class WifiClientTest {
*/
@Test
public void testWifiClientParcelWriteRead() throws Exception {
WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS);
WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME);
assertParcelSane(writeWifiClient, 1);
assertParcelSane(writeWifiClient, 2);
}
/**
@@ -52,12 +52,12 @@ public class WifiClientTest {
*/
@Test
public void testWifiClientEquals() throws Exception {
WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS);
WifiClient writeWifiClientEquals = new WifiClient(MAC_ADDRESS);
WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME);
WifiClient writeWifiClientEquals = new WifiClient(MAC_ADDRESS, INTERFACE_NAME);
assertEquals(writeWifiClient, writeWifiClientEquals);
assertEquals(writeWifiClient.hashCode(), writeWifiClientEquals.hashCode());
assertFieldCountEquals(1, WifiClient.class);
assertFieldCountEquals(2, WifiClient.class);
}
/**
@@ -66,8 +66,8 @@ public class WifiClientTest {
@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);
WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME);
WifiClient writeWifiClientNotEquals = new WifiClient(macAddressNotEquals, INTERFACE_NAME);
assertNotEquals(writeWifiClient, writeWifiClientNotEquals);
assertNotEquals(writeWifiClient.hashCode(), writeWifiClientNotEquals.hashCode());

View File

@@ -137,6 +137,7 @@ public class WifiManagerTest {
private static final int TEST_AP_FREQUENCY = 2412;
private static final int TEST_AP_BANDWIDTH = SoftApInfo.CHANNEL_WIDTH_20MHZ;
private static final int TEST_SUB_ID = 3;
private static final String TEST_AP_INSTANCE = "wlan1";
@Mock Context mContext;
@Mock android.net.wifi.IWifiManager mWifiService;
@@ -1111,6 +1112,27 @@ public class WifiManagerTest {
verify(mSoftApCallback).onInfoChanged(testSoftApInfo);
}
/*
* Verify client-provided callback is being called through callback proxy
*/
@Test
public void softApCallbackProxyCallsOnSoftApInfoListChanged() throws Exception {
SoftApInfo testSoftApInfo = new SoftApInfo();
testSoftApInfo.setFrequency(TEST_AP_FREQUENCY);
testSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH);
List<SoftApInfo> infoList = new ArrayList<>();
infoList.add(testSoftApInfo);
ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
anyInt());
callbackCaptor.getValue().onInfoListChanged(infoList);
mLooper.dispatchAll();
verify(mSoftApCallback).onInfoListChanged(infoList);
}
/*
* Verify client-provided callback is being called through callback proxy
@@ -1135,7 +1157,8 @@ public class WifiManagerTest {
*/
@Test
public void softApCallbackProxyCallsOnBlockedClientConnecting() throws Exception {
WifiClient testWifiClient = new WifiClient(MacAddress.fromString("22:33:44:55:66:77"));
WifiClient testWifiClient = new WifiClient(MacAddress.fromString("22:33:44:55:66:77"),
TEST_AP_INSTANCE);
ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
@@ -1157,6 +1180,8 @@ public class WifiManagerTest {
SoftApInfo testSoftApInfo = new SoftApInfo();
testSoftApInfo.setFrequency(TEST_AP_FREQUENCY);
testSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH);
List<SoftApInfo> infoList = new ArrayList<>();
infoList.add(testSoftApInfo);
SoftApCapability testSoftApCapability = new SoftApCapability(0);
testSoftApCapability.setMaxSupportedClients(10);
ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
@@ -1169,6 +1194,7 @@ public class WifiManagerTest {
callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_ENABLING, 0);
callbackCaptor.getValue().onConnectedClientsChanged(testClients);
callbackCaptor.getValue().onInfoChanged(testSoftApInfo);
callbackCaptor.getValue().onInfoListChanged(infoList);
callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL);
callbackCaptor.getValue().onCapabilityChanged(testSoftApCapability);
@@ -1177,6 +1203,7 @@ public class WifiManagerTest {
verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLING, 0);
verify(mSoftApCallback).onConnectedClientsChanged(testClients);
verify(mSoftApCallback).onInfoChanged(testSoftApInfo);
verify(mSoftApCallback).onInfoListChanged(infoList);
verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL);
verify(mSoftApCallback).onCapabilityChanged(testSoftApCapability);
}