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:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user