Merge "Wifi usability: Add @SystemApi to send Wifi usability stats"
diff --git a/Android.bp b/Android.bp
index 8a2089f..644cf0e 100644
--- a/Android.bp
+++ b/Android.bp
@@ -637,6 +637,7 @@
"wifi/java/android/net/wifi/ISoftApCallback.aidl",
"wifi/java/android/net/wifi/ITrafficStateCallback.aidl",
"wifi/java/android/net/wifi/IWifiManager.aidl",
+ "wifi/java/android/net/wifi/IWifiUsabilityStatsListener.aidl",
"wifi/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl",
"wifi/java/android/net/wifi/aware/IWifiAwareEventCallback.aidl",
"wifi/java/android/net/wifi/aware/IWifiAwareMacAddressProvider.aidl",
diff --git a/api/system-current.txt b/api/system-current.txt
index 730cac6..2e8f69f 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4610,6 +4610,7 @@
}
public class WifiManager {
+ method @RequiresPermission("android.permission.WIFI_UPDATE_USABILITY_STATS_SCORE") public void addWifiUsabilityStatsListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.WifiUsabilityStatsListener);
method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void connect(android.net.wifi.WifiConfiguration, android.net.wifi.WifiManager.ActionListener);
method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void connect(int, android.net.wifi.WifiManager.ActionListener);
method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void disable(int, android.net.wifi.WifiManager.ActionListener);
@@ -4625,6 +4626,7 @@
method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public boolean isWifiApEnabled();
method public boolean isWifiScannerSupported();
method @RequiresPermission("android.permission.NETWORK_SETTINGS") public void registerNetworkRequestMatchCallback(@NonNull android.net.wifi.WifiManager.NetworkRequestMatchCallback, @Nullable android.os.Handler);
+ method @RequiresPermission("android.permission.WIFI_UPDATE_USABILITY_STATS_SCORE") public void removeWifiUsabilityStatsListener(@NonNull android.net.wifi.WifiManager.WifiUsabilityStatsListener);
method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void save(android.net.wifi.WifiConfiguration, android.net.wifi.WifiManager.ActionListener);
method @RequiresPermission("android.permission.WIFI_SET_DEVICE_MOBILITY_STATE") public void setDeviceMobilityState(int);
method @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration);
@@ -4682,6 +4684,10 @@
method public void select(@NonNull android.net.wifi.WifiConfiguration);
}
+ public static interface WifiManager.WifiUsabilityStatsListener {
+ method public void onStatsUpdated(int, boolean, android.net.wifi.WifiUsabilityStatsEntry);
+ }
+
public class WifiNetworkConnectionStatistics implements android.os.Parcelable {
ctor public WifiNetworkConnectionStatistics(int, int);
ctor public WifiNetworkConnectionStatistics();
@@ -4811,6 +4817,31 @@
field @Deprecated public int unchangedSampleSize;
}
+ public final class WifiUsabilityStatsEntry implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.WifiUsabilityStatsEntry> CREATOR;
+ field public final int linkSpeedMbps;
+ field public final int rssi;
+ field public final long timeStampMs;
+ field public final long totalBackgroundScanTimeMs;
+ field public final long totalBeaconRx;
+ field public final long totalCcaBusyFreqTimeMs;
+ field public final long totalHotspot2ScanTimeMs;
+ field public final long totalNanScanTimeMs;
+ field public final long totalPnoScanTimeMs;
+ field public final long totalRadioOnFreqTimeMs;
+ field public final long totalRadioOnTimeMs;
+ field public final long totalRadioRxTimeMs;
+ field public final long totalRadioTxTimeMs;
+ field public final long totalRoamScanTimeMs;
+ field public final long totalRxSuccess;
+ field public final long totalScanTimeMs;
+ field public final long totalTxBad;
+ field public final long totalTxRetries;
+ field public final long totalTxSuccess;
+ }
+
}
package android.net.wifi.aware {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index c7cba62..f92df6a 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1654,6 +1654,11 @@
<permission android:name="android.permission.WIFI_SET_DEVICE_MOBILITY_STATE"
android:protectionLevel="signature|privileged" />
+ <!-- #SystemApi @hide Allows privileged system APK to update Wifi usability stats and score.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.WIFI_UPDATE_USABILITY_STATS_SCORE"
+ android:protectionLevel="signature|privileged" />
+
<!-- ======================================= -->
<!-- Permissions for short range, peripheral networks -->
<!-- ======================================= -->
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index 79b63bc..6656919 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -1800,6 +1800,17 @@
// Sequence number from external system app to framework
optional int32 seq_num_to_framework = 19;
+
+ // The total time CCA is on busy status on the current frequency in ms
+ // counted from the last radio chip reset
+ optional int64 total_cca_busy_freq_time_ms = 20;
+
+ // The total radio on time of the current frequency from the last radio
+ // chip reset
+ optional int64 total_radio_on_freq_time_ms = 21;
+
+ // The total number of beacons received from the last radio chip reset
+ optional int64 total_beacon_rx = 22;
}
message WifiUsabilityStats {
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 46c4191..a0ce9dd 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -28,6 +28,7 @@
import android.net.wifi.INetworkRequestMatchCallback;
import android.net.wifi.ISoftApCallback;
import android.net.wifi.ITrafficStateCallback;
+import android.net.wifi.IWifiUsabilityStatsListener;
import android.net.wifi.PasspointManagementObjectDefinition;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiActivityEnergyInfo;
@@ -186,6 +187,10 @@
void unregisterSoftApCallback(int callbackIdentifier);
+ void addWifiUsabilityStatsListener(in IBinder binder, in IWifiUsabilityStatsListener listener, int listenerIdentifier);
+
+ void removeWifiUsabilityStatsListener(int listenerIdentifier);
+
void registerTrafficStateCallback(in IBinder binder, in ITrafficStateCallback callback, int callbackIdentifier);
void unregisterTrafficStateCallback(int callbackIdentifier);
@@ -210,4 +215,3 @@
void stopDppSession();
}
-
diff --git a/wifi/java/android/net/wifi/IWifiUsabilityStatsListener.aidl b/wifi/java/android/net/wifi/IWifiUsabilityStatsListener.aidl
new file mode 100644
index 0000000..284ffaa
--- /dev/null
+++ b/wifi/java/android/net/wifi/IWifiUsabilityStatsListener.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.net.wifi.WifiUsabilityStatsEntry;
+
+/**
+ * Interface for Wi-Fi usability stats listener.
+ *
+ * @hide
+ */
+oneway interface IWifiUsabilityStatsListener
+{
+ /**
+ * Service to manager callback providing current Wi-Fi usability stats.
+ *
+ * @param seqNum The sequence number of stats, used to derive the timing of updated Wi-Fi
+ * usability statistics, set by framework and shall be incremented by one
+ * after each update.
+ * @param isSameBssidAndFreq The flag to indicate whether the BSSID and the frequency of
+ * network stays the same or not relative to the last update of
+ * Wi-Fi usability stats.
+ * @param stats The updated Wi-Fi usability statistics.
+ */
+ void onStatsUpdated(int seqNum, boolean isSameBssidAndFreq,
+ in WifiUsabilityStatsEntry stats);
+}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 1fd45e7..084bd09 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -4777,4 +4777,92 @@
});
}
}
+
+ /**
+ * Interface for Wi-Fi usability statistics listener. Should be implemented by applications and
+ * set when calling {@link WifiManager#addWifiUsabilityStatsListener(Executor,
+ * WifiUsabilityStatsListener)}.
+ *
+ * @hide
+ */
+ @SystemApi
+ public interface WifiUsabilityStatsListener {
+ /**
+ * Called when Wi-Fi usability statistics is updated.
+ *
+ * @param seqNum The sequence number of statistics, used to derive the timing of updated
+ * Wi-Fi usability statistics, set by framework and incremented by one after
+ * each update.
+ * @param isSameBssidAndFreq The flag to indicate whether the BSSID and the frequency of
+ * network stays the same or not relative to the last update of
+ * Wi-Fi usability stats.
+ * @param stats The updated Wi-Fi usability statistics.
+ */
+ void onStatsUpdated(int seqNum, boolean isSameBssidAndFreq,
+ WifiUsabilityStatsEntry stats);
+ }
+
+ /**
+ * Adds a listener for Wi-Fi usability statistics. See {@link WifiUsabilityStatsListener}.
+ * Multiple listeners can be added. Callers will be invoked periodically by framework to
+ * inform clients about the current Wi-Fi usability statistics. Callers can remove a previously
+ * added listener using {@link removeWifiUsabilityStatsListener}.
+ *
+ * @param executor The executor on which callback will be invoked.
+ * @param listener Listener for Wifi usability statistics.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE)
+ public void addWifiUsabilityStatsListener(@NonNull @CallbackExecutor Executor executor,
+ @NonNull WifiUsabilityStatsListener listener) {
+ if (executor == null) throw new IllegalArgumentException("executor cannot be null");
+ if (listener == null) throw new IllegalArgumentException("listener cannot be null");
+ if (mVerboseLoggingEnabled) {
+ Log.v(TAG, "addWifiUsabilityStatsListener: listener=" + listener);
+ }
+ try {
+ mService.addWifiUsabilityStatsListener(new Binder(),
+ new IWifiUsabilityStatsListener.Stub() {
+ @Override
+ public void onStatsUpdated(int seqNum, boolean isSameBssidAndFreq,
+ WifiUsabilityStatsEntry stats) {
+ if (mVerboseLoggingEnabled) {
+ Log.v(TAG, "WifiUsabilityStatsListener: onStatsUpdated: seqNum="
+ + seqNum);
+ }
+ Binder.withCleanCallingIdentity(() ->
+ executor.execute(() -> listener.onStatsUpdated(seqNum,
+ isSameBssidAndFreq, stats)));
+ }
+ },
+ listener.hashCode()
+ );
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Allow callers to remove a previously registered listener. After calling this method,
+ * applications will no longer receive Wi-Fi usability statistics.
+ *
+ * @param listener Listener to remove the Wi-Fi usability statistics.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE)
+ public void removeWifiUsabilityStatsListener(@NonNull WifiUsabilityStatsListener listener) {
+ if (listener == null) throw new IllegalArgumentException("listener cannot be null");
+ if (mVerboseLoggingEnabled) {
+ Log.v(TAG, "removeWifiUsabilityStatsListener: listener=" + listener);
+ }
+ try {
+ mService.removeWifiUsabilityStatsListener(listener.hashCode());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/wifi/java/android/net/wifi/WifiUsabilityStatsEntry.aidl b/wifi/java/android/net/wifi/WifiUsabilityStatsEntry.aidl
new file mode 100644
index 0000000..839af54
--- /dev/null
+++ b/wifi/java/android/net/wifi/WifiUsabilityStatsEntry.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;
+
+parcelable WifiUsabilityStatsEntry;
diff --git a/wifi/java/android/net/wifi/WifiUsabilityStatsEntry.java b/wifi/java/android/net/wifi/WifiUsabilityStatsEntry.java
new file mode 100644
index 0000000..c796e29
--- /dev/null
+++ b/wifi/java/android/net/wifi/WifiUsabilityStatsEntry.java
@@ -0,0 +1,148 @@
+/*
+ * 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.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This class makes a subset of
+ * com.android.server.wifi.nano.WifiMetricsProto.WifiUsabilityStatsEntry parcelable.
+ *
+ * @hide
+ */
+@SystemApi
+public final class WifiUsabilityStatsEntry implements Parcelable {
+ /** Absolute milliseconds from device boot when these stats were sampled */
+ public final long timeStampMs;
+ /** The RSSI (in dBm) at the sample time */
+ public final int rssi;
+ /** Link speed at the sample time in Mbps */
+ public final int linkSpeedMbps;
+ /** The total number of tx success counted from the last radio chip reset */
+ public final long totalTxSuccess;
+ /** The total number of MPDU data packet retries counted from the last radio chip reset */
+ public final long totalTxRetries;
+ /** The total number of tx bad counted from the last radio chip reset */
+ public final long totalTxBad;
+ /** The total number of rx success counted from the last radio chip reset */
+ public final long totalRxSuccess;
+ /** The total time the wifi radio is on in ms counted from the last radio chip reset */
+ public final long totalRadioOnTimeMs;
+ /** The total time the wifi radio is doing tx in ms counted from the last radio chip reset */
+ public final long totalRadioTxTimeMs;
+ /** The total time the wifi radio is doing rx in ms counted from the last radio chip reset */
+ public final long totalRadioRxTimeMs;
+ /** The total time spent on all types of scans in ms counted from the last radio chip reset */
+ public final long totalScanTimeMs;
+ /** The total time spent on nan scans in ms counted from the last radio chip reset */
+ public final long totalNanScanTimeMs;
+ /** The total time spent on background scans in ms counted from the last radio chip reset */
+ public final long totalBackgroundScanTimeMs;
+ /** The total time spent on roam scans in ms counted from the last radio chip reset */
+ public final long totalRoamScanTimeMs;
+ /** The total time spent on pno scans in ms counted from the last radio chip reset */
+ public final long totalPnoScanTimeMs;
+ /** The total time spent on hotspot2.0 scans and GAS exchange in ms counted from the last radio
+ * chip reset */
+ public final long totalHotspot2ScanTimeMs;
+ /** The total time CCA is on busy status on the current frequency in ms counted from the last
+ * radio chip reset */
+ public final long totalCcaBusyFreqTimeMs;
+ /** The total radio on time of the current frequency from the last radio chip reset */
+ public final long totalRadioOnFreqTimeMs;
+ /** The total number of beacons received from the last radio chip reset */
+ public final long totalBeaconRx;
+
+ /** Constructor function {@hide} */
+ public WifiUsabilityStatsEntry(long timeStampMs, int rssi,
+ int linkSpeedMbps, long totalTxSuccess, long totalTxRetries,
+ long totalTxBad, long totalRxSuccess, long totalRadioOnTimeMs,
+ long totalRadioTxTimeMs, long totalRadioRxTimeMs, long totalScanTimeMs,
+ long totalNanScanTimeMs, long totalBackgroundScanTimeMs, long totalRoamScanTimeMs,
+ long totalPnoScanTimeMs, long totalHotspot2ScanTimeMs, long totalCcaBusyFreqTimeMs,
+ long totalRadioOnFreqTimeMs, long totalBeaconRx) {
+ this.timeStampMs = timeStampMs;
+ this.rssi = rssi;
+ this.linkSpeedMbps = linkSpeedMbps;
+ this.totalTxSuccess = totalTxSuccess;
+ this.totalTxRetries = totalTxRetries;
+ this.totalTxBad = totalTxBad;
+ this.totalRxSuccess = totalRxSuccess;
+ this.totalRadioOnTimeMs = totalRadioOnTimeMs;
+ this.totalRadioTxTimeMs = totalRadioTxTimeMs;
+ this.totalRadioRxTimeMs = totalRadioRxTimeMs;
+ this.totalScanTimeMs = totalScanTimeMs;
+ this.totalNanScanTimeMs = totalNanScanTimeMs;
+ this.totalBackgroundScanTimeMs = totalBackgroundScanTimeMs;
+ this.totalRoamScanTimeMs = totalRoamScanTimeMs;
+ this.totalPnoScanTimeMs = totalPnoScanTimeMs;
+ this.totalHotspot2ScanTimeMs = totalHotspot2ScanTimeMs;
+ this.totalCcaBusyFreqTimeMs = totalCcaBusyFreqTimeMs;
+ this.totalRadioOnFreqTimeMs = totalRadioOnFreqTimeMs;
+ this.totalBeaconRx = totalBeaconRx;
+ }
+
+ /** Implement the Parcelable interface */
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface */
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(timeStampMs);
+ dest.writeInt(rssi);
+ dest.writeInt(linkSpeedMbps);
+ dest.writeLong(totalTxSuccess);
+ dest.writeLong(totalTxRetries);
+ dest.writeLong(totalTxBad);
+ dest.writeLong(totalRxSuccess);
+ dest.writeLong(totalRadioOnTimeMs);
+ dest.writeLong(totalRadioTxTimeMs);
+ dest.writeLong(totalRadioRxTimeMs);
+ dest.writeLong(totalScanTimeMs);
+ dest.writeLong(totalNanScanTimeMs);
+ dest.writeLong(totalBackgroundScanTimeMs);
+ dest.writeLong(totalRoamScanTimeMs);
+ dest.writeLong(totalPnoScanTimeMs);
+ dest.writeLong(totalHotspot2ScanTimeMs);
+ dest.writeLong(totalCcaBusyFreqTimeMs);
+ dest.writeLong(totalRadioOnFreqTimeMs);
+ dest.writeLong(totalBeaconRx);
+ }
+
+ /** Implement the Parcelable interface */
+ public static final Creator<WifiUsabilityStatsEntry> CREATOR =
+ new Creator<WifiUsabilityStatsEntry>() {
+ public WifiUsabilityStatsEntry createFromParcel(Parcel in) {
+ return new WifiUsabilityStatsEntry(
+ in.readLong(), in.readInt(),
+ in.readInt(), in.readLong(), in.readLong(),
+ in.readLong(), in.readLong(), in.readLong(),
+ in.readLong(), in.readLong(), in.readLong(),
+ in.readLong(), in.readLong(), in.readLong(),
+ in.readLong(), in.readLong(), in.readLong(),
+ in.readLong(), in.readLong()
+ );
+ }
+
+ public WifiUsabilityStatsEntry[] newArray(int size) {
+ return new WifiUsabilityStatsEntry[size];
+ }
+ };
+}
diff --git a/wifi/java/com/android/server/wifi/BaseWifiService.java b/wifi/java/com/android/server/wifi/BaseWifiService.java
index b3ac9f1..226c7c48 100644
--- a/wifi/java/com/android/server/wifi/BaseWifiService.java
+++ b/wifi/java/com/android/server/wifi/BaseWifiService.java
@@ -26,6 +26,7 @@
import android.net.wifi.ISoftApCallback;
import android.net.wifi.ITrafficStateCallback;
import android.net.wifi.IWifiManager;
+import android.net.wifi.IWifiUsabilityStatsListener;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiActivityEnergyInfo;
import android.net.wifi.WifiConfiguration;
@@ -464,4 +465,15 @@
public void stopDppSession() throws RemoteException {
throw new UnsupportedOperationException();
}
+
+ @Override
+ public void addWifiUsabilityStatsListener(
+ IBinder binder, IWifiUsabilityStatsListener listener, int listenerIdentifier) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void removeWifiUsabilityStatsListener(int listenerIdentifier) {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index 4fbef5a..5c2f626 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -61,6 +61,7 @@
import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback;
import android.net.wifi.WifiManager.SoftApCallback;
import android.net.wifi.WifiManager.TrafficStateCallback;
+import android.net.wifi.WifiManager.WifiUsabilityStatsListener;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
@@ -80,6 +81,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.Executor;
/**
* Unit tests for {@link android.net.wifi.WifiManager}.
@@ -103,7 +105,9 @@
@Mock SoftApCallback mSoftApCallback;
@Mock TrafficStateCallback mTrafficStateCallback;
@Mock NetworkRequestMatchCallback mNetworkRequestMatchCallback;
+ @Mock WifiUsabilityStatsListener mWifiUsabilityStatsListener;
+ private Executor mExecutor;
private Handler mHandler;
private TestLooper mLooper;
private WifiManager mWifiManager;
@@ -1342,4 +1346,40 @@
assertArrayEquals(TEST_MAC_ADDRESSES, mWifiManager.getFactoryMacAddresses());
verify(mWifiService).getFactoryMacAddresses();
}
+
+ /**
+ * Verify the call to addWifiUsabilityStatsListener goes to WifiServiceImpl.
+ */
+ @Test
+ public void addWifiUsabilityStatsListeneroesToWifiServiceImpl() throws Exception {
+ mExecutor = new SynchronousExecutor();
+ mWifiManager.addWifiUsabilityStatsListener(mExecutor, mWifiUsabilityStatsListener);
+ verify(mWifiService).addWifiUsabilityStatsListener(any(IBinder.class),
+ any(IWifiUsabilityStatsListener.Stub.class), anyInt());
+ }
+
+ /**
+ * Verify the call to removeWifiUsabilityStatsListener goes to WifiServiceImpl.
+ */
+ @Test
+ public void removeWifiUsabilityListenerGoesToWifiServiceImpl() throws Exception {
+ ArgumentCaptor<Integer> listenerIdentifier = ArgumentCaptor.forClass(Integer.class);
+ mExecutor = new SynchronousExecutor();
+ mWifiManager.addWifiUsabilityStatsListener(mExecutor, mWifiUsabilityStatsListener);
+ verify(mWifiService).addWifiUsabilityStatsListener(any(IBinder.class),
+ any(IWifiUsabilityStatsListener.Stub.class), listenerIdentifier.capture());
+
+ mWifiManager.removeWifiUsabilityStatsListener(mWifiUsabilityStatsListener);
+ verify(mWifiService).removeWifiUsabilityStatsListener(
+ eq((int) listenerIdentifier.getValue()));
+ }
+
+ /**
+ * Defined for testing purpose.
+ */
+ class SynchronousExecutor implements Executor {
+ public void execute(Runnable r) {
+ r.run();
+ }
+ }
}
diff --git a/wifi/tests/src/android/net/wifi/WifiUsabilityStatsEntryTest.java b/wifi/tests/src/android/net/wifi/WifiUsabilityStatsEntryTest.java
new file mode 100644
index 0000000..a947b55
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/WifiUsabilityStatsEntryTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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 org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.validateMockitoUsage;
+
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.MockitoAnnotations;
+
+
+/**
+ * Unit tests for {@link android.net.wifi.WifiUsabilityStatsEntry}.
+ */
+@SmallTest
+public class WifiUsabilityStatsEntryTest {
+
+ /**
+ * Setup before tests.
+ */
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ /**
+ * Clean up after tests.
+ */
+ @After
+ public void cleanup() {
+ validateMockitoUsage();
+ }
+
+ /**
+ * Verify parcel read/write for Wifi usability stats result.
+ */
+ @Test
+ public void verifyStatsResultWriteAndThenRead() throws Exception {
+ WifiUsabilityStatsEntry writeResult = createResult();
+ WifiUsabilityStatsEntry readResult = parcelWriteRead(writeResult);
+ assertWifiUsabilityStatsEntryEquals(writeResult, readResult);
+ }
+
+ /**
+ * Write the provided {@link WifiUsabilityStatsEntry} to a parcel and deserialize it.
+ */
+ private static WifiUsabilityStatsEntry parcelWriteRead(
+ WifiUsabilityStatsEntry writeResult) throws Exception {
+ Parcel parcel = Parcel.obtain();
+ writeResult.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0); // Rewind data position back to the beginning for read.
+ return WifiUsabilityStatsEntry.CREATOR.createFromParcel(parcel);
+ }
+
+ private static WifiUsabilityStatsEntry createResult() {
+ return new WifiUsabilityStatsEntry(
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18
+ );
+ }
+
+ private static void assertWifiUsabilityStatsEntryEquals(
+ WifiUsabilityStatsEntry expected,
+ WifiUsabilityStatsEntry actual) {
+ assertEquals(expected.timeStampMs, actual.timeStampMs);
+ assertEquals(expected.rssi, actual.rssi);
+ assertEquals(expected.linkSpeedMbps, actual.linkSpeedMbps);
+ assertEquals(expected.totalTxSuccess, actual.totalTxSuccess);
+ assertEquals(expected.totalTxRetries, actual.totalTxRetries);
+ assertEquals(expected.totalTxBad, actual.totalTxBad);
+ assertEquals(expected.totalRxSuccess, actual.totalRxSuccess);
+ assertEquals(expected.totalRadioOnTimeMs, actual.totalRadioOnTimeMs);
+ assertEquals(expected.totalRadioTxTimeMs, actual.totalRadioTxTimeMs);
+ assertEquals(expected.totalRadioRxTimeMs, actual.totalRadioRxTimeMs);
+ assertEquals(expected.totalScanTimeMs, actual.totalScanTimeMs);
+ assertEquals(expected.totalNanScanTimeMs, actual.totalNanScanTimeMs);
+ assertEquals(expected.totalBackgroundScanTimeMs, actual.totalBackgroundScanTimeMs);
+ assertEquals(expected.totalRoamScanTimeMs, actual.totalRoamScanTimeMs);
+ assertEquals(expected.totalPnoScanTimeMs, actual.totalPnoScanTimeMs);
+ assertEquals(expected.totalHotspot2ScanTimeMs, actual.totalHotspot2ScanTimeMs);
+ assertEquals(expected.totalCcaBusyFreqTimeMs, actual.totalCcaBusyFreqTimeMs);
+ assertEquals(expected.totalRadioOnFreqTimeMs, actual.totalRadioOnFreqTimeMs);
+ assertEquals(expected.totalBeaconRx, actual.totalBeaconRx);
+ }
+}