Merge "[AWARE] Check dynamic location permission"
diff --git a/service/java/com/android/server/wifi/HalDeviceManager.java b/service/java/com/android/server/wifi/HalDeviceManager.java
index 51ff312..facb065 100644
--- a/service/java/com/android/server/wifi/HalDeviceManager.java
+++ b/service/java/com/android/server/wifi/HalDeviceManager.java
@@ -41,6 +41,7 @@
import android.util.LongSparseArray;
import android.util.MutableBoolean;
import android.util.MutableInt;
+import android.util.Pair;
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
@@ -78,10 +79,10 @@
public HalDeviceManager(Clock clock) {
mClock = clock;
- mInterfaceAvailableForRequestListeners.put(IfaceType.STA, new HashSet<>());
- mInterfaceAvailableForRequestListeners.put(IfaceType.AP, new HashSet<>());
- mInterfaceAvailableForRequestListeners.put(IfaceType.P2P, new HashSet<>());
- mInterfaceAvailableForRequestListeners.put(IfaceType.NAN, new HashSet<>());
+ mInterfaceAvailableForRequestListeners.put(IfaceType.STA, new HashMap<>());
+ mInterfaceAvailableForRequestListeners.put(IfaceType.AP, new HashMap<>());
+ mInterfaceAvailableForRequestListeners.put(IfaceType.P2P, new HashMap<>());
+ mInterfaceAvailableForRequestListeners.put(IfaceType.NAN, new HashMap<>());
}
/* package */ void enableVerboseLogging(int verbose) {
@@ -265,10 +266,11 @@
*/
public IWifiChip getChip(IWifiIface iface) {
String name = getName(iface);
+ int type = getType(iface);
if (VDBG) Log.d(TAG, "getChip: iface(name)=" + name);
synchronized (mLock) {
- InterfaceCacheEntry cacheEntry = mInterfaceInfoCache.get(name);
+ InterfaceCacheEntry cacheEntry = mInterfaceInfoCache.get(Pair.create(name, type));
if (cacheEntry == null) {
Log.e(TAG, "getChip: no entry for iface(name)=" + name);
return null;
@@ -294,10 +296,11 @@
@NonNull InterfaceDestroyedListener destroyedListener,
@Nullable Handler handler) {
String name = getName(iface);
+ int type = getType(iface);
if (VDBG) Log.d(TAG, "registerDestroyedListener: iface(name)=" + name);
synchronized (mLock) {
- InterfaceCacheEntry cacheEntry = mInterfaceInfoCache.get(name);
+ InterfaceCacheEntry cacheEntry = mInterfaceInfoCache.get(Pair.create(name, type));
if (cacheEntry == null) {
Log.e(TAG, "registerDestroyedListener: no entry for iface(name)=" + name);
return false;
@@ -330,12 +333,22 @@
public void registerInterfaceAvailableForRequestListener(int ifaceType,
@NonNull InterfaceAvailableForRequestListener listener, @Nullable Handler handler) {
if (VDBG) {
- Log.d(TAG, "registerInterfaceAvailableForRequestListener: ifaceType=" + ifaceType);
+ Log.d(TAG, "registerInterfaceAvailableForRequestListener: ifaceType=" + ifaceType
+ + ", listener=" + listener + ", handler=" + handler);
}
synchronized (mLock) {
- mInterfaceAvailableForRequestListeners.get(ifaceType).add(
- new InterfaceAvailableForRequestListenerProxy(listener, handler));
+ InterfaceAvailableForRequestListenerProxy proxy =
+ new InterfaceAvailableForRequestListenerProxy(listener, handler);
+ if (mInterfaceAvailableForRequestListeners.get(ifaceType).containsKey(proxy)) {
+ if (VDBG) {
+ Log.d(TAG,
+ "registerInterfaceAvailableForRequestListener: dup listener skipped: "
+ + listener);
+ }
+ return;
+ }
+ mInterfaceAvailableForRequestListeners.get(ifaceType).put(proxy, null);
}
WifiChipInfo[] chipInfos = getAllChipInfo();
@@ -359,14 +372,8 @@
}
synchronized (mLock) {
- Iterator<InterfaceAvailableForRequestListenerProxy> it =
- mInterfaceAvailableForRequestListeners.get(ifaceType).iterator();
- while (it.hasNext()) {
- if (it.next().mListener == listener) {
- it.remove();
- return;
- }
- }
+ mInterfaceAvailableForRequestListeners.get(ifaceType).remove(
+ new InterfaceAvailableForRequestListenerProxy(listener, null));
}
}
@@ -412,15 +419,15 @@
}
/**
- * Called when an interface type is possibly available for creation.
+ * Called when an interface type availability for creation is changed.
*/
public interface InterfaceAvailableForRequestListener {
/**
- * Registered when an interface type could be requested. Registered with
+ * Called when an interface type availability for creation is updated. Registered with
* registerInterfaceAvailableForRequestListener() and unregistered with
* unregisterInterfaceAvailableForRequestListener().
*/
- void onAvailableForRequest();
+ void onAvailabilityChanged(boolean isAvailable);
}
/**
@@ -485,7 +492,7 @@
private IWifi mWifi;
private final WifiEventCallback mWifiEventCallback = new WifiEventCallback();
private final Set<ManagerStatusListenerProxy> mManagerStatusListeners = new HashSet<>();
- private final SparseArray<Set<InterfaceAvailableForRequestListenerProxy>>
+ private final SparseArray<Map<InterfaceAvailableForRequestListenerProxy, Boolean>>
mInterfaceAvailableForRequestListeners = new SparseArray<>();
private final SparseArray<IWifiChipEventCallback.Stub> mDebugCallbacks = new SparseArray<>();
@@ -494,7 +501,8 @@
* we need to keep a list of registered destroyed listeners. Will be validated regularly
* in getAllChipInfoAndValidateCache().
*/
- private final Map<String, InterfaceCacheEntry> mInterfaceInfoCache = new HashMap<>();
+ private final Map<Pair<String, Integer>, InterfaceCacheEntry> mInterfaceInfoCache =
+ new HashMap<>();
private class InterfaceCacheEntry {
public IWifiChip chip;
@@ -1376,7 +1384,8 @@
cacheEntry.creationTime = mClock.getUptimeSinceBootMillis();
if (mDbg) Log.d(TAG, "createIfaceIfPossible: added cacheEntry=" + cacheEntry);
- mInterfaceInfoCache.put(cacheEntry.name, cacheEntry);
+ mInterfaceInfoCache.put(
+ Pair.create(cacheEntry.name, cacheEntry.type), cacheEntry);
return iface;
}
}
@@ -1668,7 +1677,8 @@
boolean lookupError = false;
LongSparseArray<WifiIfaceInfo> orderedList = new LongSparseArray(interfaces.length);
for (WifiIfaceInfo info : interfaces) {
- InterfaceCacheEntry cacheEntry = mInterfaceInfoCache.get(info.name);
+ InterfaceCacheEntry cacheEntry = mInterfaceInfoCache.get(
+ Pair.create(info.name, getType(info.iface)));
if (cacheEntry == null) {
Log.e(TAG,
"selectInterfacesToDelete: can't find cache entry with name=" + info.name);
@@ -1836,7 +1846,7 @@
}
// dispatch listeners no matter what status
- dispatchDestroyedListeners(name);
+ dispatchDestroyedListeners(name, type);
if (status != null && status.code == WifiStatusCode.SUCCESS) {
return true;
@@ -1876,31 +1886,40 @@
WifiChipInfo[] chipInfos) {
if (VDBG) Log.d(TAG, "dispatchAvailableForRequestListenersForType: ifaceType=" + ifaceType);
- Set<InterfaceAvailableForRequestListenerProxy> listeners =
- mInterfaceAvailableForRequestListeners.get(ifaceType);
+ synchronized (mLock) {
+ Map<InterfaceAvailableForRequestListenerProxy, Boolean> listeners =
+ mInterfaceAvailableForRequestListeners.get(ifaceType);
- if (listeners.size() == 0) {
- return;
- }
+ if (listeners.size() == 0) {
+ return;
+ }
- if (!isItPossibleToCreateIface(chipInfos, ifaceType)) {
- if (VDBG) Log.d(TAG, "Creating interface type isn't possible: ifaceType=" + ifaceType);
- return;
- }
+ boolean isAvailable = isItPossibleToCreateIface(chipInfos, ifaceType);
- if (VDBG) Log.d(TAG, "It is possible to create the interface type: ifaceType=" + ifaceType);
- for (InterfaceAvailableForRequestListenerProxy listener : listeners) {
- listener.trigger();
+ if (VDBG) {
+ Log.d(TAG, "Interface available for: ifaceType=" + ifaceType + " = " + isAvailable);
+ }
+ for (Map.Entry<InterfaceAvailableForRequestListenerProxy, Boolean> listenerEntry :
+ listeners.entrySet()) {
+ if (listenerEntry.getValue() == null || listenerEntry.getValue() != isAvailable) {
+ if (VDBG) {
+ Log.d(TAG, "Interface available listener dispatched: ifaceType=" + ifaceType
+ + ", listener=" + listenerEntry.getKey());
+ }
+ listenerEntry.getKey().triggerWithArg(isAvailable);
+ }
+ listenerEntry.setValue(isAvailable);
+ }
}
}
// dispatch all destroyed listeners registered for the specified interface AND remove the
// cache entry
- private void dispatchDestroyedListeners(String name) {
+ private void dispatchDestroyedListeners(String name, int type) {
if (VDBG) Log.d(TAG, "dispatchDestroyedListeners: iface(name)=" + name);
synchronized (mLock) {
- InterfaceCacheEntry entry = mInterfaceInfoCache.get(name);
+ InterfaceCacheEntry entry = mInterfaceInfoCache.get(Pair.create(name, type));
if (entry == null) {
Log.e(TAG, "dispatchDestroyedListeners: no cache entry for iface(name)=" + name);
return;
@@ -1910,7 +1929,7 @@
listener.trigger();
}
entry.destroyedListeners.clear(); // for insurance (though cache entry is removed)
- mInterfaceInfoCache.remove(name);
+ mInterfaceInfoCache.remove(Pair.create(name, type));
}
}
@@ -1919,7 +1938,7 @@
if (VDBG) Log.d(TAG, "dispatchAllDestroyedListeners");
synchronized (mLock) {
- Iterator<Map.Entry<String, InterfaceCacheEntry>> it =
+ Iterator<Map.Entry<Pair<String, Integer>, InterfaceCacheEntry>> it =
mInterfaceInfoCache.entrySet().iterator();
while (it.hasNext()) {
InterfaceCacheEntry entry = it.next().getValue();
@@ -1958,7 +1977,18 @@
}
}
- protected abstract void action();
+ void triggerWithArg(boolean arg) {
+ if (mHandler != null) {
+ mHandler.post(() -> {
+ actionWithArg(arg);
+ });
+ } else {
+ actionWithArg(arg);
+ }
+ }
+
+ protected void action() {}
+ protected void actionWithArg(boolean arg) {}
ListenerProxy(LISTENER listener, Handler handler, String tag) {
mListener = listener;
@@ -1990,8 +2020,8 @@
}
@Override
- protected void action() {
- mListener.onAvailableForRequest();
+ protected void actionWithArg(boolean isAvailable) {
+ mListener.onAvailabilityChanged(isAvailable);
}
}
diff --git a/service/java/com/android/server/wifi/WakeupController.java b/service/java/com/android/server/wifi/WakeupController.java
index 8787bfd..4e84c4a 100644
--- a/service/java/com/android/server/wifi/WakeupController.java
+++ b/service/java/com/android/server/wifi/WakeupController.java
@@ -18,14 +18,22 @@
import android.content.Context;
import android.database.ContentObserver;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiScanner;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
+import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
/**
* WakeupController is responsible managing Auto Wifi.
@@ -34,6 +42,8 @@
*/
public class WakeupController {
+ private static final String TAG = "WakeupController";
+
// TODO(b/69624403) propagate this to Settings
private static final boolean USE_PLATFORM_WIFI_WAKE = false;
@@ -43,6 +53,34 @@
private final ContentObserver mContentObserver;
private final WakeupLock mWakeupLock;
private final WifiConfigManager mWifiConfigManager;
+ private final WifiInjector mWifiInjector;
+
+ private final WifiScanner.ScanListener mScanListener = new WifiScanner.ScanListener() {
+ @Override
+ public void onPeriodChanged(int periodInMs) {
+ // no-op
+ }
+
+ @Override
+ public void onResults(WifiScanner.ScanData[] results) {
+ // TODO(easchwar) handle scan results
+ }
+
+ @Override
+ public void onFullResult(ScanResult fullScanResult) {
+ // no-op
+ }
+
+ @Override
+ public void onSuccess() {
+ // no-op
+ }
+
+ @Override
+ public void onFailure(int reason, String description) {
+ Log.e(TAG, "ScanListener onFailure: " + reason + ": " + description);
+ }
+ };
/** Whether this feature is enabled in Settings. */
private boolean mWifiWakeupEnabled;
@@ -56,12 +94,14 @@
WakeupLock wakeupLock,
WifiConfigManager wifiConfigManager,
WifiConfigStore wifiConfigStore,
+ WifiInjector wifiInjector,
FrameworkFacade frameworkFacade) {
mContext = context;
mHandler = new Handler(looper);
mWakeupLock = wakeupLock;
mWifiConfigManager = wifiConfigManager;
mFrameworkFacade = frameworkFacade;
+ mWifiInjector = wifiInjector;
mContentObserver = new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
@@ -88,6 +128,80 @@
}
/**
+ * Starts listening for incoming scans.
+ *
+ * <p>Should only be called upon entering ScanMode. WakeupController registers its listener with
+ * the WifiScanner. If the WakeupController is already active, then it returns early. Otherwise
+ * it performs its initialization steps and sets {@link #mIsActive} to true.
+ */
+ public void start() {
+ mWifiInjector.getWifiScanner().registerScanListener(mScanListener);
+
+ // If already active, we don't want to re-initialize the lock, so return early.
+ if (mIsActive) {
+ return;
+ }
+ setActive(true);
+
+ if (mWifiWakeupEnabled) {
+ mWakeupLock.initialize(getMostRecentSavedScanResults());
+ }
+ }
+
+ /**
+ * Stops listening for scans.
+ *
+ * <p>Should only be called upon leaving ScanMode. It deregisters the listener from
+ * WifiScanner.
+ */
+ public void stop() {
+ mWifiInjector.getWifiScanner().deregisterScanListener(mScanListener);
+ }
+
+ /** Resets the WakeupController, setting {@link #mIsActive} to false. */
+ public void reset() {
+ setActive(false);
+ }
+
+ /** Returns a list of saved networks from the last full scan. */
+ private Set<ScanResultMatchInfo> getMostRecentSavedScanResults() {
+ Set<ScanResultMatchInfo> goodSavedNetworks = getGoodSavedNetworks();
+
+ List<ScanResult> scanResults = mWifiInjector.getWifiScanner().getSingleScanResults();
+ Set<ScanResultMatchInfo> lastSeenNetworks = new HashSet<>(scanResults.size());
+ for (ScanResult scanResult : scanResults) {
+ lastSeenNetworks.add(ScanResultMatchInfo.fromScanResult(scanResult));
+ }
+
+ lastSeenNetworks.retainAll(goodSavedNetworks);
+ return lastSeenNetworks;
+ }
+
+ /** Returns a filtered list of saved networks from WifiConfigManager. */
+ private Set<ScanResultMatchInfo> getGoodSavedNetworks() {
+ List<WifiConfiguration> savedNetworks = mWifiConfigManager.getSavedNetworks();
+
+ Set<ScanResultMatchInfo> goodSavedNetworks = new HashSet<>(savedNetworks.size());
+ for (WifiConfiguration config : savedNetworks) {
+ if (isWideAreaNetwork(config)
+ || config.hasNoInternetAccess()
+ || config.noInternetAccessExpected
+ || !config.getNetworkSelectionStatus().getHasEverConnected()) {
+ continue;
+ }
+ goodSavedNetworks.add(ScanResultMatchInfo.fromWifiConfiguration(config));
+ }
+
+ Log.d(TAG, "getGoodSavedNetworks: " + goodSavedNetworks.size());
+ return goodSavedNetworks;
+ }
+
+ //TODO(b/69271702) implement WAN filtering
+ private boolean isWideAreaNetwork(WifiConfiguration wifiConfiguration) {
+ return false;
+ }
+
+ /**
* Whether the feature is enabled in settings.
*
* <p>Note: This method is only used to determine whether or not to actually enable wifi. All
diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java
index 8fb61c2..ebd18cd 100644
--- a/service/java/com/android/server/wifi/WifiConfigManager.java
+++ b/service/java/com/android/server/wifi/WifiConfigManager.java
@@ -2349,8 +2349,7 @@
Iterator<WifiConfiguration> iter = networks.iterator();
while (iter.hasNext()) {
WifiConfiguration config = iter.next();
- if (!config.hiddenSSID ||
- config.getNetworkSelectionStatus().isNetworkPermanentlyDisabled()) {
+ if (!config.hiddenSSID) {
iter.remove();
}
}
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index 7312998..c2806d8 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -122,6 +122,7 @@
private final Runtime mJavaRuntime;
private final SelfRecovery mSelfRecovery;
private final WakeupController mWakeupController;
+ private final INetworkManagementService mNwManagementService;
private final boolean mUseRealLogger;
@@ -169,8 +170,10 @@
mSupplicantStaIfaceHal = new SupplicantStaIfaceHal(mContext, mWifiMonitor);
mWificondControl = new WificondControl(this, mWifiMonitor,
new CarrierNetworkConfig(mContext));
+ mNwManagementService = INetworkManagementService.Stub.asInterface(
+ ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
mWifiNative = new WifiNative(SystemProperties.get("wifi.interface", "wlan0"),
- mWifiVendorHal, mSupplicantStaIfaceHal, mWificondControl);
+ mWifiVendorHal, mSupplicantStaIfaceHal, mWificondControl, mNwManagementService);
mWifiP2pMonitor = new WifiP2pMonitor(this);
mSupplicantP2pIfaceHal = new SupplicantP2pIfaceHal(mWifiP2pMonitor);
mWifiP2pNative = new WifiP2pNative(SystemProperties.get("wifi.direct.interface", "p2p0"),
@@ -236,7 +239,7 @@
new ConnectToNetworkNotificationBuilder(mContext, mFrameworkFacade));
mWakeupController = new WakeupController(mContext,
mWifiStateMachineHandlerThread.getLooper(), new WakeupLock(mWifiConfigManager),
- mWifiConfigManager, mWifiConfigStore, mFrameworkFacade);
+ mWifiConfigManager, mWifiConfigStore, this, mFrameworkFacade);
mLockManager = new WifiLockManager(mContext, BatteryStatsService.getService());
mWifiController = new WifiController(mContext, mWifiStateMachine, mSettingsStore,
mLockManager, mWifiServiceHandlerThread.getLooper(), mFrameworkFacade,
diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java
index 3118761..63dc797 100644
--- a/service/java/com/android/server/wifi/WifiNative.java
+++ b/service/java/com/android/server/wifi/WifiNative.java
@@ -16,8 +16,10 @@
package com.android.server.wifi;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.net.InterfaceConfiguration;
import android.net.apf.ApfCapabilities;
import android.net.wifi.IApInterface;
import android.net.wifi.IClientInterface;
@@ -27,7 +29,10 @@
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiScanner;
import android.net.wifi.WifiWakeReasonAndCounts;
+import android.os.INetworkManagementService;
+import android.os.RemoteException;
import android.os.SystemClock;
+import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
@@ -35,10 +40,13 @@
import com.android.internal.annotations.Immutable;
import com.android.internal.util.HexDump;
import com.android.server.connectivity.KeepalivePacketData;
+import com.android.server.net.BaseNetworkObserver;
import com.android.server.wifi.util.FrameParser;
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
@@ -47,12 +55,14 @@
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TimeZone;
-
/**
* Native calls for bring up/shut down of the supplicant daemon and for
* sending requests to the supplicant daemon
@@ -65,14 +75,19 @@
private final SupplicantStaIfaceHal mSupplicantStaIfaceHal;
private final WifiVendorHal mWifiVendorHal;
private final WificondControl mWificondControl;
+ private final INetworkManagementService mNwManagementService;
+ // TODO(b/69426063): Remove interfaceName from constructor once WifiStateMachine switches over
+ // to the new interface management methods.
public WifiNative(String interfaceName, WifiVendorHal vendorHal,
- SupplicantStaIfaceHal staIfaceHal, WificondControl condControl) {
+ SupplicantStaIfaceHal staIfaceHal, WificondControl condControl,
+ INetworkManagementService nwService) {
mTAG = "WifiNative-" + interfaceName;
mInterfaceName = interfaceName;
mWifiVendorHal = vendorHal;
mSupplicantStaIfaceHal = staIfaceHal;
mWificondControl = condControl;
+ mNwManagementService = nwService;
}
public String getInterfaceName() {
@@ -158,12 +173,362 @@
* some duplication to ease transition.
*/
/**
+ * Meta-info about every iface that is active.
+ */
+ private static class Iface {
+ /** Type of ifaces possible */
+ public static final int IFACE_TYPE_AP = 0;
+ public static final int IFACE_TYPE_STA = 1;
+
+ @IntDef({IFACE_TYPE_AP, IFACE_TYPE_STA})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface IfaceType{}
+
+ /** Identifier allocated for the interface */
+ public final int id;
+ /** Type of the iface: STA or AP */
+ public final @IfaceType int type;
+ /** Name of the interface */
+ public String name;
+ /** External iface destroyed listener for the iface */
+ public InterfaceCallback externalListener;
+ /** Network observer registered for this interface */
+ public NetworkObserverInternal networkObserver;
+
+ Iface(int id, @Iface.IfaceType int type) {
+ this.id = id;
+ this.type = type;
+ }
+ }
+
+ /**
+ * Iface Management entity. This class maintains list of all the active ifaces.
+ */
+ private static class IfaceManager {
+ /** Integer to allocate for the next iface being created */
+ private int mNextId;
+ /** Map of the id to the iface structure */
+ private HashMap<Integer, Iface> mIfaces = new HashMap<>();
+
+ /** Allocate a new iface for the given type */
+ private Iface allocateIface(@Iface.IfaceType int type) {
+ Iface iface = new Iface(mNextId, type);
+ mIfaces.put(mNextId, iface);
+ mNextId++;
+ return iface;
+ }
+
+ /** Remove the iface using the provided id */
+ private Iface removeIface(int id) {
+ return mIfaces.remove(id);
+ }
+
+ /** Lookup the iface using the provided id */
+ private Iface getIface(int id) {
+ return mIfaces.get(id);
+ }
+
+ /** Lookup the iface using the provided name */
+ private Iface getIface(@NonNull String ifaceName) {
+ for (Iface iface : mIfaces.values()) {
+ if (TextUtils.equals(iface.name, ifaceName)) {
+ return iface;
+ }
+ }
+ return null;
+ }
+
+ /** Iterator to use for deleting all the ifaces while performing teardown on each of them */
+ private Iterator<Integer> getIfaceIdIter() {
+ return mIfaces.keySet().iterator();
+ }
+
+ /** Checks if there are any iface active. */
+ private boolean hasAnyIface() {
+ return !mIfaces.isEmpty();
+ }
+
+ /** Checks if there are any iface of the given type active. */
+ private boolean hasAnyIfaceOfType(@Iface.IfaceType int type) {
+ for (Iface iface : mIfaces.values()) {
+ if (iface.type == type) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /** Checks if there are any STA iface active. */
+ private boolean hasAnyStaIface() {
+ return hasAnyIfaceOfType(Iface.IFACE_TYPE_STA);
+ }
+
+ /** Checks if there are any AP iface active. */
+ private boolean hasAnyApIface() {
+ return hasAnyIfaceOfType(Iface.IFACE_TYPE_AP);
+ }
+ }
+
+ private Object mLock = new Object();
+ private final IfaceManager mIfaceMgr = new IfaceManager();
+ private HashSet<StatusListener> mStatusListeners = new HashSet<>();
+
+ /** Helper method invoked to start supplicant if there were no ifaces */
+ private boolean startHal() {
+ synchronized (mLock) {
+ if (!mIfaceMgr.hasAnyIface()) {
+ if (!mWifiVendorHal.startVendorHal()) {
+ Log.e(mTAG, "Failed to start vendor HAL");
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ /** Helper method invoked to stop HAL if there are no more ifaces */
+ private void stopHalAndWificondIfNecessary() {
+ synchronized (mLock) {
+ if (!mIfaceMgr.hasAnyIface()) {
+ if (!mWificondControl.tearDownInterfaces()) {
+ Log.e(mTAG, "Failed to teardown ifaces from wificond");
+ }
+ mWifiVendorHal.stopVendorHal();
+ }
+ }
+ }
+
+ private static final int CONNECT_TO_SUPPLICANT_RETRY_INTERVAL_MS = 100;
+ private static final int CONNECT_TO_SUPPLICANT_RETRY_TIMES = 50;
+ /**
+ * This method is called to wait for establishing connection to wpa_supplicant.
+ *
+ * @return true if connection is established, false otherwise.
+ */
+ private boolean waitForSupplicantConnection() {
+ // Start initialization if not already started.
+ if (!mSupplicantStaIfaceHal.isInitializationStarted()
+ && !mSupplicantStaIfaceHal.initialize()) {
+ return false;
+ }
+ boolean connected = false;
+ int connectTries = 0;
+ while (!connected && connectTries++ < CONNECT_TO_SUPPLICANT_RETRY_TIMES) {
+ // Check if the initialization is complete.
+ connected = mSupplicantStaIfaceHal.isInitializationComplete();
+ if (connected) {
+ break;
+ }
+ try {
+ Thread.sleep(CONNECT_TO_SUPPLICANT_RETRY_INTERVAL_MS);
+ } catch (InterruptedException ignore) {
+ }
+ }
+ return connected;
+ }
+
+ /** Helper method invoked to start supplicant if there were no STA ifaces */
+ private boolean startSupplicant() {
+ synchronized (mLock) {
+ if (!mIfaceMgr.hasAnyStaIface()) {
+ if (!mWificondControl.enableSupplicant()) {
+ Log.e(mTAG, "Failed to enable supplicant");
+ return false;
+ }
+ if (!waitForSupplicantConnection()) {
+ Log.e(mTAG, "Failed to connect to supplicant");
+ return false;
+ }
+ if (!mSupplicantStaIfaceHal.registerDeathHandler(new DeathHandlerInternal())) {
+ Log.e(mTAG, "Failed to register supplicant death handler");
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ /** Helper method invoked to stop supplicant if there are no more STA ifaces */
+ private void stopSupplicantIfNecessary() {
+ synchronized (mLock) {
+ if (!mIfaceMgr.hasAnyStaIface()) {
+ if (!mSupplicantStaIfaceHal.deregisterDeathHandler()) {
+ Log.e(mTAG, "Failed to deregister supplicant death handler");
+ }
+ if (!mWificondControl.disableSupplicant()) {
+ Log.e(mTAG, "Failed to disable supplicant");
+ }
+ }
+ }
+ }
+
+ /** Helper method to register a network observer and return it */
+ private boolean registerNetworkObserver(@NonNull NetworkObserverInternal observer) {
+ try {
+ mNwManagementService.registerObserver(observer);
+ } catch (RemoteException e) {
+ return false;
+ }
+ return true;
+ }
+
+ /** Helper method to register a network observer and return it */
+ private boolean unregisterNetworkObserver(@NonNull NetworkObserverInternal observer) {
+ try {
+ mNwManagementService.unregisterObserver(observer);
+ } catch (RemoteException e) {
+ return false;
+ }
+ return true;
+ }
+
+ /** Helper method invoked to teardown client iface and perform necessary cleanup */
+ private void onClientInterfaceDestroyed(@NonNull Iface iface) {
+ synchronized (mLock) {
+ if (!unregisterNetworkObserver(iface.networkObserver)) {
+ Log.e(mTAG, "Failed to unregister network observer for iface=" + iface.name);
+ }
+ if (!mSupplicantStaIfaceHal.teardownIface(iface.name)) {
+ Log.e(mTAG, "Failed to teardown iface in supplicant=" + iface.name);
+ }
+ if (!mWificondControl.tearDownClientInterface(iface.name)) {
+ Log.e(mTAG, "Failed to teardown iface in wificond=" + iface.name);
+ }
+ stopSupplicantIfNecessary();
+ stopHalAndWificondIfNecessary();
+ }
+ }
+
+ /** Helper method invoked to teardown softAp iface and perform necessary cleanup */
+ private void onSoftApInterfaceDestroyed(@NonNull Iface iface) {
+ synchronized (mLock) {
+ if (!unregisterNetworkObserver(iface.networkObserver)) {
+ Log.e(mTAG, "Failed to unregister network observer for iface=" + iface.name);
+ }
+ if (!mWificondControl.stopSoftAp(iface.name)) {
+ Log.e(mTAG, "Failed to stop softap on iface=" + iface.name);
+ }
+ if (!mWificondControl.tearDownSoftApInterface(iface.name)) {
+ Log.e(mTAG, "Failed to teardown iface in wificond=" + iface.name);
+ }
+ stopHalAndWificondIfNecessary();
+ }
+ }
+
+ /** Helper method invoked to teardown iface and perform necessary cleanup */
+ private void onInterfaceDestroyed(@NonNull Iface iface) {
+ synchronized (mLock) {
+ if (iface.type == Iface.IFACE_TYPE_STA) {
+ onClientInterfaceDestroyed(iface);
+ } else if (iface.type == Iface.IFACE_TYPE_AP) {
+ onSoftApInterfaceDestroyed(iface);
+ }
+ // Invoke the external callback.
+ iface.externalListener.onDestroyed(iface.name);
+ }
+ }
+
+ /**
+ * Callback to be invoked by HalDeviceManager when an interface is destroyed.
+ */
+ private class InterfaceDestoyedListenerInternal
+ implements HalDeviceManager.InterfaceDestroyedListener {
+ /** Identifier allocated for the interface */
+ private final int mInterfaceId;
+
+ InterfaceDestoyedListenerInternal(int ifaceId) {
+ mInterfaceId = ifaceId;
+ }
+
+ @Override
+ public void onDestroyed(@NonNull String ifaceName) {
+ synchronized (mLock) {
+ final Iface iface = mIfaceMgr.removeIface(mInterfaceId);
+ if (iface == null) {
+ Log.e(mTAG, "Received iface destroyed notification on an invalid iface="
+ + ifaceName);
+ return;
+ }
+ onInterfaceDestroyed(iface);
+ Log.i(mTAG, "Successfully torn down iface=" + ifaceName);
+ }
+ }
+ }
+
+ /**
+ * Common death handler for any of the lower layer daemons.
+ */
+ private class DeathHandlerInternal implements VendorHalDeathEventHandler,
+ SupplicantDeathEventHandler, WificondDeathEventHandler {
+ @Override
+ public void onDeath() {
+ synchronized (mLock) {
+ Log.i(mTAG, "One of the daemons died. Tearing down everything");
+ Iterator<Integer> ifaceIdIter = mIfaceMgr.getIfaceIdIter();
+ while (ifaceIdIter.hasNext()) {
+ Iface iface = mIfaceMgr.getIface(ifaceIdIter.next());
+ ifaceIdIter.remove();
+ onInterfaceDestroyed(iface);
+ Log.i(mTAG, "Successfully torn down iface=" + iface.name);
+ }
+ for (StatusListener listener : mStatusListeners) {
+ listener.onStatusChanged(false);
+ }
+ // TODO(70572148): Do we need to wait to mark the system ready again?
+ for (StatusListener listener : mStatusListeners) {
+ listener.onStatusChanged(true);
+ }
+ }
+ }
+ }
+
+ /**
+ * Network observer to use for all interface up/down notifications.
+ */
+ private class NetworkObserverInternal extends BaseNetworkObserver {
+ /** Identifier allocated for the interface */
+ private final int mInterfaceId;
+
+ NetworkObserverInternal(int id) {
+ mInterfaceId = id;
+ }
+
+ @Override
+ public void interfaceLinkStateChanged(String ifaceName, boolean isUp) {
+ synchronized (mLock) {
+ Log.i(mTAG, "Interface link state changed=" + ifaceName + ", isUp=" + isUp);
+ final Iface iface = mIfaceMgr.getIface(mInterfaceId);
+ if (iface == null) {
+ Log.e(mTAG, "Received iface up/down notification on an invalid iface="
+ + ifaceName);
+ return;
+ }
+ if (isUp) {
+ iface.externalListener.onUp(ifaceName);
+ } else {
+ iface.externalListener.onDown(ifaceName);
+ }
+ }
+ }
+ }
+
+ /**
* Initialize the native modules.
*
* @return true on success, false otherwise.
*/
public boolean initialize() {
- return false;
+ synchronized (mLock) {
+ if (!mWifiVendorHal.initialize(new DeathHandlerInternal())) {
+ Log.e(mTAG, "Failed to initialize vendor HAL");
+ return false;
+ }
+ if (!mWificondControl.registerDeathHandler(new DeathHandlerInternal())) {
+ Log.e(mTAG, "Failed to initialize wificond");
+ return false;
+ }
+ return true;
+ }
}
/**
@@ -186,6 +551,7 @@
* @param listener StatusListener listener object.
*/
public void registerStatusListener(@NonNull StatusListener listener) {
+ mStatusListeners.add(listener);
}
/**
@@ -224,7 +590,47 @@
* @return Returns the name of the allocated interface, will be null on failure.
*/
public String setupInterfaceForClientMode(@NonNull InterfaceCallback interfaceCallback) {
- return null;
+ synchronized (mLock) {
+ if (!startHal()) {
+ Log.e(mTAG, "Failed to start Hal");
+ return null;
+ }
+ if (!startSupplicant()) {
+ Log.e(mTAG, "Failed to start supplicant");
+ return null;
+ }
+ Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_STA);
+ if (iface == null) {
+ Log.e(mTAG, "Failed to allocate new STA iface");
+ return null;
+ }
+ iface.externalListener = interfaceCallback;
+ iface.name =
+ mWifiVendorHal.createStaIface(new InterfaceDestoyedListenerInternal(iface.id));
+ if (TextUtils.isEmpty(iface.name)) {
+ Log.e(mTAG, "Failed to create iface in vendor HAL");
+ mIfaceMgr.removeIface(iface.id);
+ return null;
+ }
+ if (mWificondControl.setupInterfaceForClientMode(iface.name) == null) {
+ Log.e(mTAG, "Failed to setup iface in wificond=" + iface.name);
+ teardownInterface(iface.name);
+ return null;
+ }
+ if (!mSupplicantStaIfaceHal.setupIface(iface.name)) {
+ Log.e(mTAG, "Failed to setup iface in supplicant=" + iface.name);
+ teardownInterface(iface.name);
+ return null;
+ }
+ iface.networkObserver = new NetworkObserverInternal(iface.id);
+ if (!registerNetworkObserver(iface.networkObserver)) {
+ Log.e(mTAG, "Failed to register network observer for iface=" + iface.name);
+ teardownInterface(iface.name);
+ return null;
+ }
+ Log.i(mTAG, "Successfully setup iface=" + iface.name);
+ return iface.name;
+ }
}
/**
@@ -237,7 +643,63 @@
* @return Returns the name of the allocated interface, will be null on failure.
*/
public String setupInterfaceForSoftApMode(@NonNull InterfaceCallback interfaceCallback) {
- return null;
+ synchronized (mLock) {
+ if (!startHal()) {
+ Log.e(mTAG, "Failed to start Hal");
+ return null;
+ }
+ Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_AP);
+ if (iface == null) {
+ Log.e(mTAG, "Failed to allocate new AP iface");
+ return null;
+ }
+ iface.externalListener = interfaceCallback;
+ iface.name =
+ mWifiVendorHal.createApIface(new InterfaceDestoyedListenerInternal(iface.id));
+ if (TextUtils.isEmpty(iface.name)) {
+ Log.e(mTAG, "Failed to create iface in vendor HAL");
+ mIfaceMgr.removeIface(iface.id);
+ return null;
+ }
+ if (mWificondControl.setupInterfaceForSoftApMode(iface.name) == null) {
+ Log.e(mTAG, "Failed to setup iface in wificond=" + iface.name);
+ teardownInterface(iface.name);
+ return null;
+ }
+ iface.networkObserver = new NetworkObserverInternal(iface.id);
+ if (!registerNetworkObserver(iface.networkObserver)) {
+ Log.e(mTAG, "Failed to register network observer for iface=" + iface.name);
+ teardownInterface(iface.name);
+ return null;
+ }
+ Log.i(mTAG, "Successfully setup iface=" + iface.name);
+ return iface.name;
+ }
+ }
+
+ /**
+ * Check if the interface is up or down.
+ *
+ * @param ifaceName Name of the interface.
+ * @return true if iface is up, false if it's down or on error.
+ */
+ public boolean isInterfaceUp(@NonNull String ifaceName) {
+ synchronized (mLock) {
+ final Iface iface = mIfaceMgr.getIface(ifaceName);
+ if (iface == null) {
+ Log.e(mTAG, "Trying to get iface state on invalid iface=" + ifaceName);
+ return false;
+ }
+ InterfaceConfiguration config = null;
+ try {
+ config = mNwManagementService.getInterfaceConfig(ifaceName);
+ } catch (RemoteException e) {
+ }
+ if (config == null) {
+ return false;
+ }
+ return config.isUp();
+ }
}
/**
@@ -249,6 +711,28 @@
* @param ifaceName Name of the interface.
*/
public void teardownInterface(@NonNull String ifaceName) {
+ synchronized (mLock) {
+ final Iface iface = mIfaceMgr.getIface(ifaceName);
+ if (iface == null) {
+ Log.e(mTAG, "Trying to teardown an invalid iface=" + ifaceName);
+ return;
+ }
+ // Trigger the iface removal from HAL. The rest of the cleanup will be triggered
+ // from the interface destroyed callback.
+ // TODO(b/70521011): Figure out what to do for devices with no HAL.
+ if (iface.type == Iface.IFACE_TYPE_STA) {
+ if (!mWifiVendorHal.removeStaIface(ifaceName)) {
+ Log.e(mTAG, "Failed to remove iface in vendor HAL=" + ifaceName);
+ return;
+ }
+ } else if (iface.type == Iface.IFACE_TYPE_AP) {
+ if (!mWifiVendorHal.removeApIface(ifaceName)) {
+ Log.e(mTAG, "Failed to remove iface in vendor HAL=" + ifaceName);
+ return;
+ }
+ }
+ Log.i(mTAG, "Successfully initiated teardown for iface=" + ifaceName);
+ }
}
/********************************************************
diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java
index 505a09b..4090c36 100644
--- a/service/java/com/android/server/wifi/WifiStateMachine.java
+++ b/service/java/com/android/server/wifi/WifiStateMachine.java
@@ -4657,7 +4657,14 @@
public void enter() {
mLastOperationMode = mOperationalMode;
mWifiStateTracker.updateState(WifiStateTracker.SCAN_MODE);
+ mWifiInjector.getWakeupController().start();
}
+
+ @Override
+ public void exit() {
+ mWifiInjector.getWakeupController().stop();
+ }
+
@Override
public boolean processMessage(Message message) {
logStateAndMessage(message, this);
@@ -4885,6 +4892,8 @@
// Let the system know that wifi is available in client mode.
setWifiState(WIFI_STATE_ENABLED);
+ mWifiInjector.getWakeupController().reset();
+
mNetworkInfo.setIsAvailable(true);
if (mNetworkAgent != null) mNetworkAgent.sendNetworkInfo(mNetworkInfo);
diff --git a/service/java/com/android/server/wifi/WifiVendorHal.java b/service/java/com/android/server/wifi/WifiVendorHal.java
index f1d2add..d6b568d 100644
--- a/service/java/com/android/server/wifi/WifiVendorHal.java
+++ b/service/java/com/android/server/wifi/WifiVendorHal.java
@@ -347,6 +347,24 @@
}
}
+ private class StaInterfaceDestroyedListenerInternal implements InterfaceDestroyedListener {
+ private final InterfaceDestroyedListener mExternalListener;
+
+ StaInterfaceDestroyedListenerInternal(InterfaceDestroyedListener externalListener) {
+ mExternalListener = externalListener;
+ }
+
+ @Override
+ public void onDestroyed(@NonNull String ifaceName) {
+ synchronized (sLock) {
+ mIWifiStaIfaces.remove(ifaceName);
+ }
+ if (mExternalListener != null) {
+ mExternalListener.onDestroyed(ifaceName);
+ }
+ }
+ }
+
/**
* Create a STA iface using {@link HalDeviceManager}.
*
@@ -355,8 +373,8 @@
*/
public String createStaIface(InterfaceDestroyedListener destroyedListener) {
synchronized (sLock) {
- IWifiStaIface iface;
- iface = mHalDeviceManager.createStaIface(destroyedListener, null);
+ IWifiStaIface iface = mHalDeviceManager.createStaIface(
+ new StaInterfaceDestroyedListenerInternal(destroyedListener), null);
if (iface == null) {
mLog.err("Failed to create STA iface");
return stringResult(null);
@@ -416,6 +434,25 @@
}
}
+ private class ApInterfaceDestroyedListenerInternal implements InterfaceDestroyedListener {
+ private final InterfaceDestroyedListener mExternalListener;
+
+ ApInterfaceDestroyedListenerInternal(InterfaceDestroyedListener externalListener) {
+ mExternalListener = externalListener;
+ }
+
+ @Override
+ public void onDestroyed(@NonNull String ifaceName) {
+ synchronized (sLock) {
+ mIWifiApIfaces.remove(ifaceName);
+ }
+ if (mExternalListener != null) {
+ mExternalListener.onDestroyed(ifaceName);
+ }
+ }
+ }
+
+
/**
* Create a AP iface using {@link HalDeviceManager}.
*
@@ -424,8 +461,8 @@
*/
public String createApIface(InterfaceDestroyedListener destroyedListener) {
synchronized (sLock) {
- IWifiApIface iface;
- iface = mHalDeviceManager.createApIface(destroyedListener, null);
+ IWifiApIface iface = mHalDeviceManager.createApIface(
+ new ApInterfaceDestroyedListenerInternal(destroyedListener), null);
if (iface == null) {
mLog.err("Failed to create AP iface");
return stringResult(null);
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java b/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java
index f8deb05..b263597 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java
@@ -203,6 +203,7 @@
String name = AWARE_INTERFACE_PREFIX + i;
mMgr.deleteDataPathInterface(name);
}
+ mMgr.releaseAwareInterface();
}
/**
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareNativeManager.java b/service/java/com/android/server/wifi/aware/WifiAwareNativeManager.java
index dd19d7b..b9dd680 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareNativeManager.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareNativeManager.java
@@ -47,10 +47,10 @@
private Handler mHandler;
private WifiAwareNativeCallback mWifiAwareNativeCallback;
private IWifiNanIface mWifiNanIface = null;
- private InterfaceDestroyedListener mInterfaceDestroyedListener =
- new InterfaceDestroyedListener();
+ private InterfaceDestroyedListener mInterfaceDestroyedListener;
private InterfaceAvailableForRequestListener mInterfaceAvailableForRequestListener =
new InterfaceAvailableForRequestListener();
+ private int mReferenceCount = 0;
WifiAwareNativeManager(WifiAwareStateManager awareStateManager,
HalDeviceManager halDeviceManager,
@@ -88,7 +88,6 @@
if (mHalDeviceManager.isStarted()) {
mHalDeviceManager.registerInterfaceAvailableForRequestListener(
IfaceType.NAN, mInterfaceAvailableForRequestListener, mHandler);
- tryToGetAware();
}
}
@@ -104,19 +103,31 @@
}
/**
- * Attempt to obtain the HAL NAN interface. If available then enables Aware usage.
+ * Attempt to obtain the HAL NAN interface.
*/
- private void tryToGetAware() {
+ public void tryToGetAware() {
synchronized (mLock) {
- if (mDbg) Log.v(TAG, "tryToGetAware: mWifiNanIface=" + mWifiNanIface);
+ if (mDbg) {
+ Log.d(TAG, "tryToGetAware: mWifiNanIface=" + mWifiNanIface + ", mReferenceCount="
+ + mReferenceCount);
+ }
if (mWifiNanIface != null) {
+ mReferenceCount++;
return;
}
+ if (mHalDeviceManager == null) {
+ Log.e(TAG, "tryToGetAware: mHalDeviceManager is null!?");
+ awareIsDown();
+ return;
+ }
+
+ mInterfaceDestroyedListener = new InterfaceDestroyedListener();
IWifiNanIface iface = mHalDeviceManager.createNanIface(mInterfaceDestroyedListener,
mHandler);
if (iface == null) {
- Log.e(TAG, "Was not able to obtain an IWifiNanIface");
+ Log.e(TAG, "Was not able to obtain an IWifiNanIface (even though enabled!?)");
+ awareIsDown();
} else {
if (mDbg) Log.v(TAG, "Obtained an IWifiNanIface");
@@ -126,44 +137,92 @@
Log.e(TAG, "IWifiNanIface.registerEventCallback error: " + statusString(
status));
mHalDeviceManager.removeIface(iface);
+ awareIsDown();
return;
}
} catch (RemoteException e) {
Log.e(TAG, "IWifiNanIface.registerEventCallback exception: " + e);
- mHalDeviceManager.removeIface(iface);
+ awareIsDown();
return;
}
mWifiNanIface = iface;
- mWifiAwareStateManager.enableUsage();
+ mReferenceCount = 1;
}
}
}
+ /**
+ * Release the HAL NAN interface.
+ */
+ public void releaseAware() {
+ if (mDbg) {
+ Log.d(TAG, "releaseAware: mWifiNanIface=" + mWifiNanIface + ", mReferenceCount="
+ + mReferenceCount);
+ }
+
+ if (mWifiNanIface == null) {
+ return;
+ }
+ if (mHalDeviceManager == null) {
+ Log.e(TAG, "releaseAware: mHalDeviceManager is null!?");
+ return;
+ }
+
+ synchronized (mLock) {
+ mReferenceCount--;
+ if (mReferenceCount != 0) {
+ return;
+ }
+ mInterfaceDestroyedListener.active = false;
+ mInterfaceDestroyedListener = null;
+ mHalDeviceManager.removeIface(mWifiNanIface);
+ mWifiNanIface = null;
+ }
+ }
+
private void awareIsDown() {
synchronized (mLock) {
- if (mDbg) Log.v(TAG, "awareIsDown: mWifiNanIface=" + mWifiNanIface);
- if (mWifiNanIface != null) {
- mWifiNanIface = null;
- mWifiAwareStateManager.disableUsage();
+ if (mDbg) {
+ Log.d(TAG, "awareIsDown: mWifiNanIface=" + mWifiNanIface + ", mReferenceCount ="
+ + mReferenceCount);
}
+ mWifiNanIface = null;
+ mReferenceCount = 0;
+ mWifiAwareStateManager.disableUsage();
}
}
private class InterfaceDestroyedListener implements
HalDeviceManager.InterfaceDestroyedListener {
+ public boolean active = true;
+
@Override
public void onDestroyed(@NonNull String ifaceName) {
- if (mDbg) Log.v(TAG, "Interface was destroyed");
- awareIsDown();
+ if (mDbg) {
+ Log.d(TAG, "Interface was destroyed: mWifiNanIface=" + mWifiNanIface + ", active="
+ + active);
+ }
+ if (active && mWifiNanIface != null) {
+ awareIsDown();
+ } // else: we released it locally so no need to disable usage
}
}
private class InterfaceAvailableForRequestListener implements
HalDeviceManager.InterfaceAvailableForRequestListener {
@Override
- public void onAvailableForRequest() {
- if (mDbg) Log.v(TAG, "Interface is possibly available");
- tryToGetAware();
+ public void onAvailabilityChanged(boolean isAvailable) {
+ if (mDbg) {
+ Log.d(TAG, "Interface availability = " + isAvailable + ", mWifiNanIface="
+ + mWifiNanIface);
+ }
+ synchronized (mLock) {
+ if (isAvailable) {
+ mWifiAwareStateManager.enableUsage();
+ } else if (mWifiNanIface == null) { // not available could mean already have NAN
+ mWifiAwareStateManager.disableUsage();
+ }
+ }
}
}
@@ -182,6 +241,7 @@
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("WifiAwareNativeManager:");
pw.println(" mWifiNanIface: " + mWifiNanIface);
+ pw.println(" mReferenceCount: " + mReferenceCount);
mWifiAwareNativeCallback.dump(fd, pw, args);
mHalDeviceManager.dump(fd, pw, args);
}
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java b/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java
index 1dd18ef..5ae6902 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java
@@ -119,6 +119,8 @@
private static final int COMMAND_TYPE_TRANSMIT_NEXT_MESSAGE = 119;
private static final int COMMAND_TYPE_RECONFIGURE = 120;
private static final int COMMAND_TYPE_DELAYED_INITIALIZATION = 121;
+ private static final int COMMAND_TYPE_GET_AWARE = 122;
+ private static final int COMMAND_TYPE_RELEASE_AWARE = 123;
private static final int RESPONSE_TYPE_ON_CONFIG_SUCCESS = 200;
private static final int RESPONSE_TYPE_ON_CONFIG_FAIL = 201;
@@ -470,6 +472,26 @@
}
/**
+ * Place a request to get the Wi-Fi Aware interface (before which no HAL command can be
+ * executed).
+ */
+ public void getAwareInterface() {
+ Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
+ msg.arg1 = COMMAND_TYPE_GET_AWARE;
+ mSm.sendMessage(msg);
+ }
+
+ /**
+ * Place a request to release the Wi-Fi Aware interface (after which no HAL command can be
+ * executed).
+ */
+ public void releaseAwareInterface() {
+ Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
+ msg.arg1 = COMMAND_TYPE_RELEASE_AWARE;
+ mSm.sendMessage(msg);
+ }
+
+ /**
* Place a request for a new client connection on the state machine queue.
*/
public void connect(int clientId, int uid, int pid, String callingPackage,
@@ -1634,6 +1656,14 @@
mWifiAwareNativeManager.start(getHandler());
waitForResponse = false;
break;
+ case COMMAND_TYPE_GET_AWARE:
+ mWifiAwareNativeManager.tryToGetAware();
+ waitForResponse = false;
+ break;
+ case COMMAND_TYPE_RELEASE_AWARE:
+ mWifiAwareNativeManager.releaseAware();
+ waitForResponse = false;
+ break;
default:
waitForResponse = false;
Log.wtf(TAG, "processCommand: this isn't a COMMAND -- msg=" + msg);
@@ -1884,6 +1914,14 @@
"processTimeout: COMMAND_TYPE_DELAYED_INITIALIZATION - shouldn't be "
+ "waiting!");
break;
+ case COMMAND_TYPE_GET_AWARE:
+ Log.wtf(TAG,
+ "processTimeout: COMMAND_TYPE_GET_AWARE - shouldn't be waiting!");
+ break;
+ case COMMAND_TYPE_RELEASE_AWARE:
+ Log.wtf(TAG,
+ "processTimeout: COMMAND_TYPE_RELEASE_AWARE - shouldn't be waiting!");
+ break;
default:
Log.wtf(TAG, "processTimeout: this isn't a COMMAND -- msg=" + msg);
/* fall-through */
@@ -2060,6 +2098,10 @@
boolean notificationRequired =
doesAnyClientNeedIdentityChangeNotifications() || notifyIdentityChange;
+ if (mCurrentAwareConfiguration == null) {
+ mWifiAwareNativeManager.tryToGetAware();
+ }
+
boolean success = mWifiAwareNativeApi.enableAndConfigure(transactionId, merged,
notificationRequired, mCurrentAwareConfiguration == null,
mPowerManager.isInteractive(), mPowerManager.isDeviceIdleMode());
@@ -2290,12 +2332,16 @@
private void enableUsageLocal() {
if (VDBG) Log.v(TAG, "enableUsageLocal: mUsageEnabled=" + mUsageEnabled);
+ if (mCapabilities == null) {
+ getAwareInterface();
+ queryCapabilities();
+ releaseAwareInterface();
+ }
+
if (mUsageEnabled) {
return;
}
-
mUsageEnabled = true;
- queryCapabilities();
sendAwareStateChangedBroadcast(true);
mAwareMetrics.recordEnableUsage();
@@ -2863,7 +2909,10 @@
private void onAwareDownLocal() {
if (VDBG) {
- Log.v(TAG, "onAwareDown");
+ Log.v(TAG, "onAwareDown: mCurrentAwareConfiguration=" + mCurrentAwareConfiguration);
+ }
+ if (mCurrentAwareConfiguration == null) {
+ return;
}
for (int i = 0; i < mClients.size(); ++i) {
diff --git a/tests/wifitests/Android.mk b/tests/wifitests/Android.mk
index b5c5844..19a5efb 100644
--- a/tests/wifitests/Android.mk
+++ b/tests/wifitests/Android.mk
@@ -59,7 +59,7 @@
# since neither is declared a static java library.
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-test \
- mockito-target-minus-junit4 \
+ mockito-target-inline-minus-junit4 \
frameworks-base-testutils \
services \
wifi-service \
@@ -110,6 +110,7 @@
libunwindstack \
libutils \
libvndksupport \
+ libdexmakerjvmtiagent \
ifdef WPA_SUPPLICANT_VERSION
LOCAL_JNI_SHARED_LIBRARIES += libwpa_client
diff --git a/tests/wifitests/AndroidManifest.xml b/tests/wifitests/AndroidManifest.xml
index dcb61c7..aad2041 100644
--- a/tests/wifitests/AndroidManifest.xml
+++ b/tests/wifitests/AndroidManifest.xml
@@ -19,7 +19,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.server.wifi.test">
- <application>
+ <application
+ android:debuggable="true">
<uses-library android:name="android.test.runner" />
<activity android:label="WifiTestDummyLabel"
android:name="WifiTestDummyName">
diff --git a/tests/wifitests/src/com/android/server/wifi/HalDeviceManagerTest.java b/tests/wifitests/src/com/android/server/wifi/HalDeviceManagerTest.java
index 4290ada..3e3ce42 100644
--- a/tests/wifitests/src/com/android/server/wifi/HalDeviceManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/HalDeviceManagerTest.java
@@ -313,42 +313,51 @@
HalDeviceManager.InterfaceAvailableForRequestListener nanAvailListener = mock(
HalDeviceManager.InterfaceAvailableForRequestListener.class);
+ InOrder availInOrder = inOrder(staAvailListener, nanAvailListener);
+
// Request STA
IWifiIface staIface = validateInterfaceSequence(chipMock,
false, // chipModeValid
-1000, // chipModeId (only used if chipModeValid is true)
IfaceType.STA, // ifaceTypeToCreate
- "sta0", // ifaceName
+ "wlan0", // ifaceName
TestChipV1.STA_CHIP_MODE_ID, // finalChipMode
null, // tearDownList
staDestroyedListener, // destroyedListener
staAvailListener // availableListener
);
+ availInOrder.verify(staAvailListener).onAvailabilityChanged(false);
// Request NAN
IWifiIface nanIface = validateInterfaceSequence(chipMock,
true, // chipModeValid
TestChipV1.STA_CHIP_MODE_ID, // chipModeId
IfaceType.NAN, // ifaceTypeToCreate
- "nan0", // ifaceName
+ "wlan0", // ifaceName
TestChipV1.STA_CHIP_MODE_ID, // finalChipMode
null, // tearDownList
nanDestroyedListener, // destroyedListener
nanAvailListener // availableListener
);
+ availInOrder.verify(nanAvailListener).onAvailabilityChanged(false);
// fiddle with the "chip" by removing the STA
- chipMock.interfaceNames.get(IfaceType.STA).remove("sta0");
+ chipMock.interfaceNames.get(IfaceType.STA).remove("wlan0");
// now try to request another NAN
IWifiIface nanIface2 = mDut.createNanIface(nanDestroyedListener, mHandler);
+ collector.checkThat("NAN can't be created", nanIface2, IsNull.nullValue());
+
mDut.registerInterfaceAvailableForRequestListener(IfaceType.NAN, nanAvailListener,
mHandler);
- collector.checkThat("NAN can't be created", nanIface2, IsNull.nullValue());
+ mTestLooper.dispatchAll();
+
+ // extra (apparently duplicate) call since everything was cleaned-up once a cache mismatch
+ // was detected - so this is a call on a new registration
+ availInOrder.verify(nanAvailListener).onAvailabilityChanged(false);
// verify that Wi-Fi is shut-down: should also get all onDestroyed messages that are
// registered (even if they seem out-of-sync to chip)
- mTestLooper.dispatchAll();
verify(mWifiMock, times(2)).stop();
verify(mManagerStatusListenerMock, times(2)).onStatusChanged();
verify(staDestroyedListener).onDestroyed(getName(staIface));
@@ -384,7 +393,7 @@
false, // chipModeValid
-1000, // chipModeId (only used if chipModeValid is true)
IfaceType.STA, // ifaceTypeToCreate
- "sta0", // ifaceName
+ "wlan0", // ifaceName
TestChipV1.STA_CHIP_MODE_ID, // finalChipMode
null, // tearDownList
null, // destroyedListener
@@ -399,12 +408,14 @@
mHandler);
mTestLooper.dispatchAll();
+ verify(staAvailListener).onAvailabilityChanged(false);
+
// remove STA interface -> should trigger callbacks
mDut.removeIface(staIface);
mTestLooper.dispatchAll();
// verify: only a single trigger
- verify(staAvailListener).onAvailableForRequest();
+ verify(staAvailListener).onAvailabilityChanged(true);
verifyNoMoreInteractions(staAvailListener);
}
@@ -515,8 +526,8 @@
*/
@Test
public void testCreateStaInterfaceNoInitModeTestChipV1() throws Exception {
- runCreateSingleXxxInterfaceNoInitMode(new TestChipV1(), IfaceType.STA, "sta0",
- TestChipV1.STA_CHIP_MODE_ID, 1);
+ runCreateSingleXxxInterfaceNoInitMode(new TestChipV1(), IfaceType.STA, "wlan0",
+ TestChipV1.STA_CHIP_MODE_ID, false);
}
/**
@@ -524,8 +535,8 @@
*/
@Test
public void testCreateApInterfaceNoInitModeTestChipV1() throws Exception {
- runCreateSingleXxxInterfaceNoInitMode(new TestChipV1(), IfaceType.AP, "ap0",
- TestChipV1.AP_CHIP_MODE_ID, 1);
+ runCreateSingleXxxInterfaceNoInitMode(new TestChipV1(), IfaceType.AP, "wlan0",
+ TestChipV1.AP_CHIP_MODE_ID, false);
}
/**
@@ -534,7 +545,7 @@
@Test
public void testCreateP2pInterfaceNoInitModeTestChipV1() throws Exception {
runCreateSingleXxxInterfaceNoInitMode(new TestChipV1(), IfaceType.P2P, "p2p0",
- TestChipV1.STA_CHIP_MODE_ID, 1);
+ TestChipV1.STA_CHIP_MODE_ID, false);
}
/**
@@ -542,8 +553,8 @@
*/
@Test
public void testCreateNanInterfaceNoInitModeTestChipV1() throws Exception {
- runCreateSingleXxxInterfaceNoInitMode(new TestChipV1(), IfaceType.NAN, "nan0",
- TestChipV1.STA_CHIP_MODE_ID, 1);
+ runCreateSingleXxxInterfaceNoInitMode(new TestChipV1(), IfaceType.NAN, "wlan0",
+ TestChipV1.STA_CHIP_MODE_ID, false);
}
// TestChipV2
@@ -557,8 +568,8 @@
// we get callback 1 after creating the first STA (since we can create another STA),
// and we get callback 2 after destroying the first STA (since we can create another STA -
// as expected).
- runCreateSingleXxxInterfaceNoInitMode(new TestChipV2(), IfaceType.STA, "sta0",
- TestChipV2.CHIP_MODE_ID, 2);
+ runCreateSingleXxxInterfaceNoInitMode(new TestChipV2(), IfaceType.STA, "wlan0",
+ TestChipV2.CHIP_MODE_ID, true);
}
/**
@@ -566,8 +577,8 @@
*/
@Test
public void testCreateApInterfaceNoInitModeTestChipV2() throws Exception {
- runCreateSingleXxxInterfaceNoInitMode(new TestChipV2(), IfaceType.AP, "ap0",
- TestChipV2.CHIP_MODE_ID, 1);
+ runCreateSingleXxxInterfaceNoInitMode(new TestChipV2(), IfaceType.AP, "wlan0",
+ TestChipV2.CHIP_MODE_ID, false);
}
/**
@@ -576,7 +587,7 @@
@Test
public void testCreateP2pInterfaceNoInitModeTestChipV2() throws Exception {
runCreateSingleXxxInterfaceNoInitMode(new TestChipV2(), IfaceType.P2P, "p2p0",
- TestChipV2.CHIP_MODE_ID, 1);
+ TestChipV2.CHIP_MODE_ID, false);
}
/**
@@ -584,8 +595,8 @@
*/
@Test
public void testCreateNanInterfaceNoInitModeTestChipV2() throws Exception {
- runCreateSingleXxxInterfaceNoInitMode(new TestChipV2(), IfaceType.NAN, "nan0",
- TestChipV2.CHIP_MODE_ID, 1);
+ runCreateSingleXxxInterfaceNoInitMode(new TestChipV2(), IfaceType.NAN, "wlan0",
+ TestChipV2.CHIP_MODE_ID, false);
}
// TestChipV3
@@ -599,8 +610,8 @@
// we get callback 1 after creating the first STA (since we can create another STA),
// and we get callback 2 after destroying the first STA (since we can create another STA -
// as expected).
- runCreateSingleXxxInterfaceNoInitMode(new TestChipV3(), IfaceType.STA, "sta0",
- TestChipV3.CHIP_MODE_ID, 2);
+ runCreateSingleXxxInterfaceNoInitMode(new TestChipV3(), IfaceType.STA, "wlan0",
+ TestChipV3.CHIP_MODE_ID, true);
}
/**
@@ -608,8 +619,8 @@
*/
@Test
public void testCreateApInterfaceNoInitModeTestChipV3() throws Exception {
- runCreateSingleXxxInterfaceNoInitMode(new TestChipV3(), IfaceType.AP, "ap0",
- TestChipV3.CHIP_MODE_ID, 1);
+ runCreateSingleXxxInterfaceNoInitMode(new TestChipV3(), IfaceType.AP, "wlan0",
+ TestChipV3.CHIP_MODE_ID, false);
}
/**
@@ -618,7 +629,7 @@
@Test
public void testCreateP2pInterfaceNoInitModeTestChipV3() throws Exception {
runCreateSingleXxxInterfaceNoInitMode(new TestChipV3(), IfaceType.P2P, "p2p0",
- TestChipV3.CHIP_MODE_ID, 1);
+ TestChipV3.CHIP_MODE_ID, false);
}
/**
@@ -626,8 +637,8 @@
*/
@Test
public void testCreateNanInterfaceNoInitModeTestChipV3() throws Exception {
- runCreateSingleXxxInterfaceNoInitMode(new TestChipV3(), IfaceType.NAN, "nan0",
- TestChipV3.CHIP_MODE_ID, 1);
+ runCreateSingleXxxInterfaceNoInitMode(new TestChipV3(), IfaceType.NAN, "wlan0",
+ TestChipV3.CHIP_MODE_ID, false);
}
//////////////////////////////////////////////////////////////////////////////////////
@@ -640,7 +651,7 @@
*/
@Test
public void testCreateApWithStaModeUpTestChipV1() throws Exception {
- final String name = "ap0";
+ final String name = "wlan0";
TestChipV1 chipMock = new TestChipV1();
chipMock.initialize();
@@ -666,6 +677,8 @@
);
collector.checkThat("allocated interface", iface, IsNull.notNullValue());
+ verify(iafrl).onAvailabilityChanged(false);
+
// act: stop Wi-Fi
mDut.stop();
mTestLooper.dispatchAll();
@@ -707,8 +720,8 @@
mDut.registerInterfaceAvailableForRequestListener(IfaceType.STA, staIafrl, null);
mDut.registerInterfaceAvailableForRequestListener(IfaceType.AP, apIafrl, null);
- mInOrder.verify(staIafrl).onAvailableForRequest();
- mInOrder.verify(apIafrl).onAvailableForRequest();
+ mInOrder.verify(staIafrl).onAvailabilityChanged(true);
+ mInOrder.verify(apIafrl).onAvailabilityChanged(true);
// Create STA Iface first.
IWifiStaIface staIface = mock(IWifiStaIface.class);
@@ -721,7 +734,7 @@
assertEquals(staIface, mDut.createStaIface(staIdl, null));
mInOrder.verify(chipMock.chip).configureChip(TestChipV1.STA_CHIP_MODE_ID);
- mInOrder.verify(apIafrl).onAvailableForRequest();
+ mInOrder.verify(staIafrl).onAvailabilityChanged(false);
// Now Create AP Iface.
IWifiApIface apIface = mock(IWifiApIface.class);
@@ -736,7 +749,8 @@
mInOrder.verify(chipMock.chip).removeStaIface(getName(staIface));
mInOrder.verify(staIdl).onDestroyed(getName(staIface));
mInOrder.verify(chipMock.chip).configureChip(TestChipV1.AP_CHIP_MODE_ID);
- mInOrder.verify(staIafrl).onAvailableForRequest();
+ mInOrder.verify(apIafrl).onAvailabilityChanged(false);
+ mInOrder.verify(staIafrl).onAvailabilityChanged(true);
// Stop Wi-Fi
mDut.stop();
@@ -754,7 +768,7 @@
*/
@Test
public void testCreateApWithApModeUpTestChipV1() throws Exception {
- final String name = "ap0";
+ final String name = "wlan0";
TestChipV1 chipMock = new TestChipV1();
chipMock.initialize();
@@ -780,6 +794,8 @@
);
collector.checkThat("allocated interface", iface, IsNull.notNullValue());
+ verify(iafrl).onAvailabilityChanged(false);
+
// act: stop Wi-Fi
mDut.stop();
mTestLooper.dispatchAll();
@@ -844,10 +860,8 @@
HalDeviceManager.InterfaceAvailableForRequestListener nanAvailListener = mock(
HalDeviceManager.InterfaceAvailableForRequestListener.class);
- InOrder inOrderStaAvail = inOrder(staAvailListener);
- InOrder inOrderApAvail = inOrder(apAvailListener);
- InOrder inOrderP2pAvail = inOrder(p2pAvailListener);
- InOrder inOrderNanAvail = inOrder(nanAvailListener);
+ InOrder inOrderAvail = inOrder(staAvailListener, apAvailListener, p2pAvailListener,
+ nanAvailListener);
// register listeners for interface availability
mDut.registerInterfaceAvailableForRequestListener(IfaceType.STA, staAvailListener,
@@ -859,17 +873,17 @@
mHandler);
mTestLooper.dispatchAll();
- inOrderStaAvail.verify(staAvailListener).onAvailableForRequest();
- inOrderApAvail.verify(apAvailListener).onAvailableForRequest();
- inOrderP2pAvail.verify(p2pAvailListener).onAvailableForRequest();
- inOrderNanAvail.verify(nanAvailListener).onAvailableForRequest();
+ inOrderAvail.verify(staAvailListener).onAvailabilityChanged(true);
+ inOrderAvail.verify(apAvailListener).onAvailabilityChanged(true);
+ inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(true);
+ inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(true);
// Request STA
IWifiIface staIface = validateInterfaceSequence(chipMock,
false, // chipModeValid
-1000, // chipModeId (only used if chipModeValid is true)
IfaceType.STA, // ifaceTypeToCreate
- "sta0", // ifaceName
+ "wlan0", // ifaceName
TestChipV1.STA_CHIP_MODE_ID, // finalChipMode
null, // tearDownList
staDestroyedListener, // destroyedListener
@@ -877,9 +891,7 @@
);
collector.checkThat("allocated STA interface", staIface, IsNull.notNullValue());
- inOrderApAvail.verify(apAvailListener).onAvailableForRequest();
- inOrderP2pAvail.verify(p2pAvailListener).onAvailableForRequest();
- inOrderNanAvail.verify(nanAvailListener).onAvailableForRequest();
+ inOrderAvail.verify(staAvailListener).onAvailabilityChanged(false);
// request STA2: should fail
IWifiIface staIface2 = mDut.createStaIface(null, null);
@@ -903,14 +915,15 @@
);
collector.checkThat("allocated P2P interface", p2pIface, IsNull.notNullValue());
- inOrderApAvail.verify(apAvailListener).onAvailableForRequest();
+ inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(false);
+ inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(false);
// Request AP
IWifiIface apIface = validateInterfaceSequence(chipMock,
true, // chipModeValid
TestChipV1.STA_CHIP_MODE_ID, // chipModeId
IfaceType.AP, // ifaceTypeToCreate
- "ap0", // ifaceName
+ "wlan0", // ifaceName
TestChipV1.AP_CHIP_MODE_ID, // finalChipMode
new IWifiIface[]{staIface, p2pIface}, // tearDownList
apDestroyedListener, // destroyedListener
@@ -925,7 +938,8 @@
);
collector.checkThat("allocated AP interface", apIface, IsNull.notNullValue());
- inOrderStaAvail.verify(staAvailListener).onAvailableForRequest();
+ inOrderAvail.verify(apAvailListener).onAvailabilityChanged(false);
+ inOrderAvail.verify(staAvailListener).onAvailabilityChanged(true);
// request AP2: should fail
IWifiIface apIface2 = mDut.createApIface(null, null);
@@ -940,7 +954,7 @@
true, // chipModeValid
TestChipV1.AP_CHIP_MODE_ID, // chipModeId
IfaceType.STA, // ifaceTypeToCreate
- "sta0", // ifaceName
+ "wlan0", // ifaceName
TestChipV1.STA_CHIP_MODE_ID, // finalChipMode
null, // tearDownList
staDestroyedListener, // destroyedListener
@@ -951,9 +965,10 @@
);
collector.checkThat("allocated STA interface", staIface, IsNull.notNullValue());
- inOrderApAvail.verify(apAvailListener).onAvailableForRequest();
- inOrderP2pAvail.verify(p2pAvailListener).onAvailableForRequest();
- inOrderNanAvail.verify(nanAvailListener).onAvailableForRequest();
+ inOrderAvail.verify(apAvailListener).onAvailabilityChanged(true);
+ inOrderAvail.verify(staAvailListener).onAvailabilityChanged(false);
+ inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(true);
+ inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(true);
mTestLooper.dispatchAll();
verify(apDestroyedListener).onDestroyed(getName(apIface));
@@ -970,7 +985,8 @@
null // availableListener
);
- inOrderApAvail.verify(apAvailListener).onAvailableForRequest();
+ inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(false);
+ inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(false);
// Request NAN: should fail
IWifiIface nanIface = mDut.createNanIface(nanDestroyedListener, mHandler);
@@ -982,9 +998,8 @@
mDut.removeIface(p2pIface);
mTestLooper.dispatchAll();
- inOrderApAvail.verify(apAvailListener).onAvailableForRequest();
- inOrderP2pAvail.verify(p2pAvailListener).onAvailableForRequest();
- inOrderNanAvail.verify(nanAvailListener).onAvailableForRequest();
+ inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(true);
+ inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(true);
verify(chipMock.chip, times(2)).removeP2pIface("p2p0");
verify(p2pDestroyedListener2).onDestroyed(getName(p2pIface));
@@ -993,7 +1008,7 @@
true, // chipModeValid
TestChipV1.STA_CHIP_MODE_ID, // chipModeId
IfaceType.NAN, // ifaceTypeToCreate
- "nan0", // ifaceName
+ "wlan0", // ifaceName
TestChipV1.STA_CHIP_MODE_ID, // finalChipMode
null, // tearDownList
nanDestroyedListener, // destroyedListener
@@ -1001,8 +1016,7 @@
);
collector.checkThat("allocated NAN interface", nanIface, IsNull.notNullValue());
- inOrderApAvail.verify(apAvailListener).onAvailableForRequest();
- inOrderP2pAvail.verify(p2pAvailListener).onAvailableForRequest();
+ inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(false);
verifyNoMoreInteractions(mManagerStatusListenerMock, staDestroyedListener, staAvailListener,
staDestroyedListener2, apDestroyedListener, apAvailListener, p2pDestroyedListener,
@@ -1023,9 +1037,7 @@
*/
@Test
public void testP2pAndNanInteractionsTestChipV1() throws Exception {
- // staAvailCallbacks=0: there is no second STA so will never get available callback after
- // first is created.
- runP2pAndNanExclusiveInteractionsTestChip(new TestChipV1(), 0, TestChipV1.STA_CHIP_MODE_ID);
+ runP2pAndNanExclusiveInteractionsTestChip(new TestChipV1(), TestChipV1.STA_CHIP_MODE_ID);
}
/**
@@ -1054,7 +1066,7 @@
false, // chipModeValid
-1000, // chipModeId (only used if chipModeValid is true)
IfaceType.STA, // ifaceTypeToCreate
- "sta0", // ifaceName
+ "wlan0", // ifaceName
TestChipV1.STA_CHIP_MODE_ID, // finalChipMode
null, // tearDownList
staDestroyedListener1, // destroyedListener
@@ -1062,6 +1074,8 @@
);
collector.checkThat("STA created", staIface1, IsNull.notNullValue());
+ verify(staAvailListener1).onAvailabilityChanged(false);
+
// get STA interface again
IWifiIface staIface2 = mDut.createStaIface(staDestroyedListener2, mHandler);
collector.checkThat("STA created", staIface2, IsNull.nullValue());
@@ -1170,10 +1184,8 @@
HalDeviceManager.InterfaceAvailableForRequestListener nanAvailListener = mock(
HalDeviceManager.InterfaceAvailableForRequestListener.class);
- InOrder inOrderStaAvail = inOrder(staAvailListener);
- InOrder inOrderApAvail = inOrder(apAvailListener);
- InOrder inOrderP2pAvail = inOrder(p2pAvailListener);
- InOrder inOrderNanAvail = inOrder(nanAvailListener);
+ InOrder inOrderAvail = inOrder(staAvailListener, apAvailListener, p2pAvailListener,
+ nanAvailListener);
// register listeners for interface availability
mDut.registerInterfaceAvailableForRequestListener(IfaceType.STA, staAvailListener,
@@ -1185,10 +1197,10 @@
mHandler);
mTestLooper.dispatchAll();
- inOrderStaAvail.verify(staAvailListener).onAvailableForRequest();
- inOrderApAvail.verify(apAvailListener).onAvailableForRequest();
- inOrderP2pAvail.verify(p2pAvailListener).onAvailableForRequest();
- inOrderNanAvail.verify(nanAvailListener).onAvailableForRequest();
+ inOrderAvail.verify(staAvailListener).onAvailabilityChanged(true);
+ inOrderAvail.verify(apAvailListener).onAvailabilityChanged(true);
+ inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(true);
+ inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(true);
// create STA
when(mClock.getUptimeSinceBootMillis()).thenReturn(15L);
@@ -1196,7 +1208,7 @@
false, // chipModeValid
-1000, // chipModeId (only used if chipModeValid is true)
IfaceType.STA, // ifaceTypeToCreate
- "sta0", // ifaceName
+ "wlan0", // ifaceName
TestChipV2.CHIP_MODE_ID, // finalChipMode
null, // tearDownList
staDestroyedListener, // destroyedListener
@@ -1204,11 +1216,6 @@
);
collector.checkThat("STA interface wasn't created", staIface, IsNull.notNullValue());
- inOrderStaAvail.verify(staAvailListener).onAvailableForRequest();
- inOrderApAvail.verify(apAvailListener).onAvailableForRequest();
- inOrderP2pAvail.verify(p2pAvailListener).onAvailableForRequest();
- inOrderNanAvail.verify(nanAvailListener).onAvailableForRequest();
-
// create P2P
IWifiIface p2pIface = validateInterfaceSequence(chipMock,
true, // chipModeValid
@@ -1222,8 +1229,8 @@
);
collector.checkThat("P2P interface wasn't created", p2pIface, IsNull.notNullValue());
- inOrderStaAvail.verify(staAvailListener).onAvailableForRequest();
- inOrderApAvail.verify(apAvailListener).onAvailableForRequest();
+ inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(false);
+ inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(false);
// request NAN: should fail
IWifiIface nanIface = mDut.createNanIface(null, null);
@@ -1234,7 +1241,7 @@
true, // chipModeValid
TestChipV2.CHIP_MODE_ID, // chipModeId
IfaceType.AP, // ifaceTypeToCreate
- "ap0", // ifaceName
+ "wlan1", // ifaceName
TestChipV2.CHIP_MODE_ID, // finalChipMode
null, // tearDownList
apDestroyedListener, // destroyedListener
@@ -1242,6 +1249,9 @@
);
collector.checkThat("AP interface wasn't created", apIface, IsNull.notNullValue());
+ inOrderAvail.verify(apAvailListener).onAvailabilityChanged(false);
+ inOrderAvail.verify(staAvailListener).onAvailabilityChanged(false);
+
// request STA2: should fail
IWifiIface staIface2 = mDut.createStaIface(null, null);
collector.checkThat("STA2 should not be created", staIface2, IsNull.nullValue());
@@ -1254,9 +1264,9 @@
mDut.removeIface(apIface);
mTestLooper.dispatchAll();
- inOrderStaAvail.verify(staAvailListener).onAvailableForRequest();
- inOrderApAvail.verify(apAvailListener).onAvailableForRequest();
- verify(chipMock.chip).removeApIface("ap0");
+ inOrderAvail.verify(apAvailListener).onAvailabilityChanged(true);
+ inOrderAvail.verify(staAvailListener).onAvailabilityChanged(true);
+ verify(chipMock.chip).removeApIface("wlan1");
verify(apDestroyedListener).onDestroyed(getName(apIface));
// create STA2: using a later clock
@@ -1265,7 +1275,7 @@
true, // chipModeValid
TestChipV2.CHIP_MODE_ID, // chipModeId
IfaceType.STA, // ifaceTypeToCreate
- "sta1", // ifaceName
+ "wlan1", // ifaceName
TestChipV2.CHIP_MODE_ID, // finalChipMode
null, // tearDownList
staDestroyedListener2, // destroyedListener
@@ -1273,7 +1283,7 @@
);
collector.checkThat("STA 2 interface wasn't created", staIface2, IsNull.notNullValue());
- inOrderApAvail.verify(apAvailListener).onAvailableForRequest();
+ inOrderAvail.verify(staAvailListener).onAvailabilityChanged(false);
// request STA3: should fail
IWifiIface staIface3 = mDut.createStaIface(null, null);
@@ -1284,7 +1294,7 @@
true, // chipModeValid
TestChipV2.CHIP_MODE_ID, // chipModeId
IfaceType.AP, // ifaceTypeToCreate
- "ap0", // ifaceName
+ "wlan1", // ifaceName
TestChipV2.CHIP_MODE_ID, // finalChipMode
null, // tearDownList
apDestroyedListener, // destroyedListener
@@ -1295,12 +1305,14 @@
);
collector.checkThat("AP interface wasn't created", apIface, IsNull.notNullValue());
+ inOrderAvail.verify(apAvailListener).onAvailabilityChanged(false);
+
// tear down P2P
mDut.removeIface(p2pIface);
mTestLooper.dispatchAll();
- inOrderP2pAvail.verify(p2pAvailListener).onAvailableForRequest();
- inOrderNanAvail.verify(nanAvailListener).onAvailableForRequest();
+ inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(true);
+ inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(true);
verify(chipMock.chip).removeP2pIface("p2p0");
verify(p2pDestroyedListener).onDestroyed(getName(p2pIface));
@@ -1309,7 +1321,7 @@
true, // chipModeValid
TestChipV2.CHIP_MODE_ID, // chipModeId
IfaceType.NAN, // ifaceTypeToCreate
- "nan0", // ifaceName
+ "wlan0", // ifaceName
TestChipV2.CHIP_MODE_ID, // finalChipMode
null, // tearDownList
nanDestroyedListener, // destroyedListener
@@ -1317,7 +1329,7 @@
);
collector.checkThat("NAN interface wasn't created", nanIface, IsNull.notNullValue());
- inOrderP2pAvail.verify(p2pAvailListener).onAvailableForRequest();
+ inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(false);
verifyNoMoreInteractions(mManagerStatusListenerMock, staDestroyedListener,
staDestroyedListener2, apDestroyedListener, p2pDestroyedListener,
@@ -1340,9 +1352,7 @@
*/
@Test
public void testP2pAndNanInteractionsTestChipV2() throws Exception {
- // staAvailCallbacks=5: after every substantial change will get a callback since second
- // STA is always available.
- runP2pAndNanExclusiveInteractionsTestChip(new TestChipV2(), 5, TestChipV2.CHIP_MODE_ID);
+ runP2pAndNanExclusiveInteractionsTestChip(new TestChipV2(), TestChipV2.CHIP_MODE_ID);
}
/**
@@ -1445,10 +1455,8 @@
HalDeviceManager.InterfaceAvailableForRequestListener nanAvailListener = mock(
HalDeviceManager.InterfaceAvailableForRequestListener.class);
- InOrder inOrderStaAvail = inOrder(staAvailListener);
- InOrder inOrderApAvail = inOrder(apAvailListener);
- InOrder inOrderP2pAvail = inOrder(p2pAvailListener);
- InOrder inOrderNanAvail = inOrder(nanAvailListener);
+ InOrder inOrderAvail = inOrder(staAvailListener, apAvailListener, p2pAvailListener,
+ nanAvailListener);
// register listeners for interface availability
mDut.registerInterfaceAvailableForRequestListener(IfaceType.STA, staAvailListener,
@@ -1460,10 +1468,10 @@
mHandler);
mTestLooper.dispatchAll();
- inOrderStaAvail.verify(staAvailListener).onAvailableForRequest();
- inOrderApAvail.verify(apAvailListener).onAvailableForRequest();
- inOrderP2pAvail.verify(p2pAvailListener).onAvailableForRequest();
- inOrderNanAvail.verify(nanAvailListener).onAvailableForRequest();
+ inOrderAvail.verify(staAvailListener).onAvailabilityChanged(true);
+ inOrderAvail.verify(apAvailListener).onAvailabilityChanged(true);
+ inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(true);
+ inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(true);
// create STA
when(mClock.getUptimeSinceBootMillis()).thenReturn(15L);
@@ -1471,7 +1479,7 @@
false, // chipModeValid
-1000, // chipModeId (only used if chipModeValid is true)
IfaceType.STA, // ifaceTypeToCreate
- "sta0", // ifaceName
+ "wlan0", // ifaceName
TestChipV3.CHIP_MODE_ID, // finalChipMode
null, // tearDownList
staDestroyedListener, // destroyedListener
@@ -1479,11 +1487,6 @@
);
collector.checkThat("STA interface wasn't created", staIface, IsNull.notNullValue());
- inOrderStaAvail.verify(staAvailListener).onAvailableForRequest();
- inOrderApAvail.verify(apAvailListener).onAvailableForRequest();
- inOrderP2pAvail.verify(p2pAvailListener).onAvailableForRequest();
- inOrderNanAvail.verify(nanAvailListener).onAvailableForRequest();
-
// create P2P
IWifiIface p2pIface = validateInterfaceSequence(chipMock,
true, // chipModeValid
@@ -1497,7 +1500,9 @@
);
collector.checkThat("P2P interface wasn't created", p2pIface, IsNull.notNullValue());
- inOrderApAvail.verify(apAvailListener).onAvailableForRequest();
+ inOrderAvail.verify(staAvailListener).onAvailabilityChanged(false);
+ inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(false);
+ inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(false);
// request NAN: should fail
IWifiIface nanIface = mDut.createNanIface(null, null);
@@ -1508,7 +1513,7 @@
true, // chipModeValid
TestChipV3.CHIP_MODE_ID, // chipModeId
IfaceType.AP, // ifaceTypeToCreate
- "ap0", // ifaceName
+ "wlan1", // ifaceName
TestChipV3.CHIP_MODE_ID, // finalChipMode
null, // tearDownList
apDestroyedListener, // destroyedListener
@@ -1518,6 +1523,8 @@
collector.checkThat("AP interface wasn't created", apIface, IsNull.notNullValue());
verify(chipMock.chip).removeP2pIface("p2p0");
+ inOrderAvail.verify(apAvailListener).onAvailabilityChanged(false);
+
// request STA2: should fail
IWifiIface staIface2 = mDut.createStaIface(null, null);
collector.checkThat("STA2 should not be created", staIface2, IsNull.nullValue());
@@ -1534,11 +1541,11 @@
mDut.removeIface(apIface);
mTestLooper.dispatchAll();
- inOrderStaAvail.verify(staAvailListener).onAvailableForRequest();
- inOrderApAvail.verify(apAvailListener).onAvailableForRequest();
- inOrderP2pAvail.verify(p2pAvailListener).onAvailableForRequest();
- inOrderNanAvail.verify(nanAvailListener).onAvailableForRequest();
- verify(chipMock.chip).removeApIface("ap0");
+ inOrderAvail.verify(apAvailListener).onAvailabilityChanged(true);
+ inOrderAvail.verify(staAvailListener).onAvailabilityChanged(true);
+ inOrderAvail.verify(p2pAvailListener).onAvailabilityChanged(true);
+ inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(true);
+ verify(chipMock.chip).removeApIface("wlan1");
verify(apDestroyedListener).onDestroyed(getName(apIface));
// create STA2: using a later clock
@@ -1547,7 +1554,7 @@
true, // chipModeValid
TestChipV3.CHIP_MODE_ID, // chipModeId
IfaceType.STA, // ifaceTypeToCreate
- "sta1", // ifaceName
+ "wlan1", // ifaceName
TestChipV3.CHIP_MODE_ID, // finalChipMode
null, // tearDownList
staDestroyedListener2, // destroyedListener
@@ -1555,9 +1562,7 @@
);
collector.checkThat("STA 2 interface wasn't created", staIface2, IsNull.notNullValue());
- inOrderApAvail.verify(apAvailListener).onAvailableForRequest();
- inOrderP2pAvail.verify(p2pAvailListener).onAvailableForRequest();
- inOrderNanAvail.verify(nanAvailListener).onAvailableForRequest();
+ inOrderAvail.verify(staAvailListener).onAvailabilityChanged(false);
// request STA3: should fail
IWifiIface staIface3 = mDut.createStaIface(null, null);
@@ -1568,7 +1573,7 @@
true, // chipModeValid
TestChipV3.CHIP_MODE_ID, // chipModeId
IfaceType.NAN, // ifaceTypeToCreate
- "nan0", // ifaceName
+ "wlan0", // ifaceName
TestChipV3.CHIP_MODE_ID, // finalChipMode
null, // tearDownList
nanDestroyedListener, // destroyedListener
@@ -1578,9 +1583,8 @@
);
collector.checkThat("NAN interface wasn't created", nanIface, IsNull.notNullValue());
- inOrderApAvail.verify(apAvailListener).onAvailableForRequest();
- inOrderP2pAvail.verify(p2pAvailListener).onAvailableForRequest();
- verify(chipMock.chip).removeStaIface("sta1");
+ inOrderAvail.verify(nanAvailListener).onAvailabilityChanged(false);
+ verify(chipMock.chip).removeStaIface("wlan1");
verify(staDestroyedListener2).onDestroyed(getName(staIface2));
// request STA2: should fail
@@ -1608,8 +1612,7 @@
*/
@Test
public void testP2pAndNanInteractionsTestChipV3() throws Exception {
- // staAvailCallbacks=2: only get callback (for second STA) when P2P or NAN are down.
- runP2pAndNanExclusiveInteractionsTestChip(new TestChipV3(), 2, TestChipV3.CHIP_MODE_ID);
+ runP2pAndNanExclusiveInteractionsTestChip(new TestChipV3(), TestChipV3.CHIP_MODE_ID);
}
/**
@@ -1725,7 +1728,7 @@
}
private void runCreateSingleXxxInterfaceNoInitMode(ChipMockBase chipMock, int ifaceTypeToCreate,
- String ifaceName, int finalChipMode, int expectedAvailableCalls) throws Exception {
+ String ifaceName, int finalChipMode, boolean multipleIfaceSupport) throws Exception {
chipMock.initialize();
mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip,
mManagerStatusListenerMock);
@@ -1737,6 +1740,8 @@
HalDeviceManager.InterfaceAvailableForRequestListener iafrl = mock(
HalDeviceManager.InterfaceAvailableForRequestListener.class);
+ InOrder availInOrder = inOrder(iafrl);
+
IWifiIface iface = validateInterfaceSequence(chipMock,
false, // chipModeValid
-1000, // chipModeId (only used if chipModeValid is true)
@@ -1748,6 +1753,7 @@
iafrl // availableListener
);
collector.checkThat("allocated interface", iface, IsNull.notNullValue());
+ availInOrder.verify(iafrl).onAvailabilityChanged(multipleIfaceSupport);
// act: remove interface
mDut.removeIface(iface);
@@ -1770,7 +1776,9 @@
}
verify(idl).onDestroyed(ifaceName);
- verify(iafrl, times(expectedAvailableCalls)).onAvailableForRequest();
+ if (!multipleIfaceSupport) {
+ availInOrder.verify(iafrl).onAvailabilityChanged(true);
+ }
verifyNoMoreInteractions(mManagerStatusListenerMock, idl, iafrl);
}
@@ -1791,7 +1799,7 @@
* line of NAN and P2P being exclusive).
*/
public void runP2pAndNanExclusiveInteractionsTestChip(ChipMockBase chipMock,
- int staAvailCallbacks, int onlyChipMode) throws Exception {
+ int onlyChipMode) throws Exception {
chipMock.initialize();
mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip,
mManagerStatusListenerMock);
@@ -1810,31 +1818,38 @@
InterfaceDestroyedListener p2pDestroyedListener = mock(
InterfaceDestroyedListener.class);
- HalDeviceManager.InterfaceAvailableForRequestListener p2pAvailListener = null;
+
+ InOrder availInOrder = inOrder(staAvailListener, nanAvailListener);
// Request STA
IWifiIface staIface = validateInterfaceSequence(chipMock,
false, // chipModeValid
-1000, // chipModeId (only used if chipModeValid is true)
IfaceType.STA, // ifaceTypeToCreate
- "sta0", // ifaceName
+ "wlan0", // ifaceName
onlyChipMode, // finalChipMode
null, // tearDownList
staDestroyedListener, // destroyedListener
staAvailListener // availableListener
);
+ availInOrder.verify(staAvailListener).onAvailabilityChanged(
+ chipMock.chipMockId == CHIP_MOCK_V2 || chipMock.chipMockId == CHIP_MOCK_V3);
// Request NAN
IWifiIface nanIface = validateInterfaceSequence(chipMock,
true, // chipModeValid
onlyChipMode, // chipModeId
IfaceType.NAN, // ifaceTypeToCreate
- "nan0", // ifaceName
+ "wlan0", // ifaceName
onlyChipMode, // finalChipMode
null, // tearDownList
nanDestroyedListener, // destroyedListener
nanAvailListener // availableListener
);
+ if (chipMock.chipMockId == CHIP_MOCK_V3) {
+ availInOrder.verify(staAvailListener).onAvailabilityChanged(false);
+ }
+ availInOrder.verify(nanAvailListener).onAvailabilityChanged(false);
// Request P2P
IWifiIface p2pIface = validateInterfaceSequence(chipMock,
@@ -1845,7 +1860,7 @@
onlyChipMode, // finalChipMode
new IWifiIface[]{nanIface}, // tearDownList
p2pDestroyedListener, // destroyedListener
- p2pAvailListener, // availableListener
+ null, // availableListener
// destroyedInterfacesDestroyedListeners...
new InterfaceDestroyedListenerWithIfaceName(
getName(nanIface), nanDestroyedListener)
@@ -1864,24 +1879,26 @@
mTestLooper.dispatchAll();
verify(p2pDestroyedListener).onDestroyed(getName(p2pIface));
- verify(nanAvailListener).onAvailableForRequest();
+ if (chipMock.chipMockId == CHIP_MOCK_V3) {
+ availInOrder.verify(staAvailListener).onAvailabilityChanged(true);
+ }
+ availInOrder.verify(nanAvailListener).onAvailabilityChanged(true);
// Request NAN: expect success now
nanIface = validateInterfaceSequence(chipMock,
true, // chipModeValid
onlyChipMode, // chipModeId
IfaceType.NAN, // ifaceTypeToCreate
- "nan0", // ifaceName
+ "wlan0", // ifaceName
onlyChipMode, // finalChipMode
null, // tearDownList
nanDestroyedListener, // destroyedListener
nanAvailListener // availableListener
);
-
- if (staAvailCallbacks != 0) {
- // if there are duplicate STAs then expect an available callback for each step above
- verify(staAvailListener, times(staAvailCallbacks)).onAvailableForRequest();
+ if (chipMock.chipMockId == CHIP_MOCK_V3) {
+ availInOrder.verify(staAvailListener).onAvailabilityChanged(false);
}
+ availInOrder.verify(nanAvailListener).onAvailabilityChanged(false);
verifyNoMoreInteractions(mManagerStatusListenerMock, staDestroyedListener, staAvailListener,
nanDestroyedListener, nanAvailListener, p2pDestroyedListener);
@@ -2285,7 +2302,13 @@
// chip configuration
+ private static final int CHIP_MOCK_V1 = 0;
+ private static final int CHIP_MOCK_V2 = 1;
+ private static final int CHIP_MOCK_V3 = 2;
+
private class ChipMockBase {
+ public int chipMockId;
+
public IWifiChip chip;
public int chipId;
public boolean chipModeValid = false;
@@ -2353,6 +2376,8 @@
void initialize() throws Exception {
super.initialize();
+ chipMockId = CHIP_MOCK_V1;
+
// chip Id configuration
ArrayList<Integer> chipIds;
chipId = 10;
@@ -2414,6 +2439,8 @@
void initialize() throws Exception {
super.initialize();
+ chipMockId = CHIP_MOCK_V2;
+
// chip Id configuration
ArrayList<Integer> chipIds;
chipId = 12;
@@ -2472,6 +2499,8 @@
void initialize() throws Exception {
super.initialize();
+ chipMockId = CHIP_MOCK_V3;
+
// chip Id configuration
ArrayList<Integer> chipIds;
chipId = 15;
diff --git a/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java b/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java
index 5e45570..afbd87a 100644
--- a/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java
@@ -19,20 +19,32 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiScanner;
import android.os.test.TestLooper;
import android.provider.Settings;
+import com.android.server.wifi.util.ScanResultUtil;
+
import org.junit.Before;
import org.junit.Test;
+import org.mockito.InOrder;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
/**
* Unit tests for {@link WakeupController}.
@@ -41,8 +53,10 @@
@Mock private Context mContext;
@Mock private WakeupLock mWakeupLock;
- @Mock private WifiConfigManager mWifiConfigManager;
@Mock private WifiConfigStore mWifiConfigStore;
+ @Mock private WifiInjector mWifiInjector;
+ @Mock private WifiScanner mWifiScanner;
+ @Mock private WifiConfigManager mWifiConfigManager;
@Mock private FrameworkFacade mFrameworkFacade;
private TestLooper mLooper;
@@ -52,12 +66,30 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
+
+ when(mWifiInjector.getWifiScanner()).thenReturn(mWifiScanner);
mLooper = new TestLooper();
}
- private WakeupController newWakeupController() {
- return new WakeupController(mContext, mLooper.getLooper(), mWakeupLock, mWifiConfigManager,
- mWifiConfigStore, mFrameworkFacade);
+ /** Initializes the wakeupcontroller in the given `enabled` state. */
+ private void initializeWakeupController(boolean enabled) {
+ int settingsValue = enabled ? 1 : 0;
+ when(mFrameworkFacade.getIntegerSetting(mContext,
+ Settings.Global.WIFI_WAKEUP_ENABLED, 0)).thenReturn(settingsValue);
+ mWakeupController = new WakeupController(mContext,
+ mLooper.getLooper(),
+ mWakeupLock,
+ mWifiConfigManager,
+ mWifiConfigStore,
+ mWifiInjector,
+ mFrameworkFacade);
+ }
+
+ private ScanResult createOpenScanResult(String ssid) {
+ ScanResult scanResult = new ScanResult();
+ scanResult.SSID = ssid;
+ scanResult.capabilities = "";
+ return scanResult;
}
/**
@@ -65,9 +97,7 @@
*/
@Test
public void verifyEnabledWhenToggledOn() {
- when(mFrameworkFacade.getIntegerSetting(mContext,
- Settings.Global.WIFI_WAKEUP_ENABLED, 0)).thenReturn(1);
- mWakeupController = newWakeupController();
+ initializeWakeupController(true /* enabled */);
assertTrue(mWakeupController.isEnabled());
}
@@ -77,9 +107,7 @@
*/
@Test
public void verifyDisabledWhenToggledOff() {
- when(mFrameworkFacade.getIntegerSetting(mContext,
- Settings.Global.WIFI_WAKEUP_ENABLED, 0)).thenReturn(0);
- mWakeupController = newWakeupController();
+ initializeWakeupController(false /* enabled */);
assertFalse(mWakeupController.isEnabled());
}
@@ -89,7 +117,7 @@
*/
@Test
public void registersWakeupConfigStoreData() {
- mWakeupController = newWakeupController();
+ initializeWakeupController(true /* enabled */);
verify(mWifiConfigStore).registerStoreData(any(WakeupConfigStoreData.class));
}
@@ -98,11 +126,121 @@
*/
@Test
public void dumpIncludesWakeupLock() {
- mWakeupController = newWakeupController();
+ initializeWakeupController(true /* enabled */);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
PrintWriter writer = new PrintWriter(stream);
mWakeupController.dump(null, writer, null);
verify(mWakeupLock).dump(null, writer, null);
}
+
+ /**
+ * Verify that start initializes the wakeup lock.
+ */
+ @Test
+ public void startInitializesWakeupLock() {
+ initializeWakeupController(true /* enabled */);
+ mWakeupController.start();
+ verify(mWakeupLock).initialize(any());
+ }
+
+ /**
+ * Verify that start does not initialize the wakeup lock when feature is disabled.
+ */
+ @Test
+ public void startDoesNotInitializeWakeupLockWhenDisabled() {
+ initializeWakeupController(false /* enabled */);
+ mWakeupController.start();
+ verify(mWakeupLock, never()).initialize(any());
+ }
+
+ /**
+ * Verify that start does not re-initialize the wakeup lock if the controller is already active.
+ */
+ @Test
+ public void startDoesNotInitializeWakeupLockIfAlreadyActive() {
+ initializeWakeupController(true /* enabled */);
+ InOrder inOrder = Mockito.inOrder(mWakeupLock);
+
+ mWakeupController.start();
+ inOrder.verify(mWakeupLock).initialize(any());
+
+ mWakeupController.stop();
+ mWakeupController.start();
+ inOrder.verify(mWakeupLock, never()).initialize(any());
+ }
+
+ /**
+ * Verify that start registers the scan listener on the wifi scanner.
+ */
+ @Test
+ public void startRegistersScanListener() {
+ initializeWakeupController(true /* enabled */);
+ mWakeupController.start();
+ verify(mWifiScanner).registerScanListener(any());
+ }
+
+ /**
+ * Verify that stop deregisters the scan listener from the wifi scanner.
+ */
+ @Test
+ public void stopDeresgistersScanListener() {
+ initializeWakeupController(true /* enabled */);
+ mWakeupController.start();
+ mWakeupController.stop();
+ verify(mWifiScanner).deregisterScanListener(any());
+ }
+
+ /**
+ * Verify that reset sets active to false.
+ *
+ * <p>This is accomplished by initiating another call to start and verifying that the wakeup
+ * lock is re-initialized.
+ */
+ @Test
+ public void resetSetsActiveToFalse() {
+ initializeWakeupController(true /* enabled */);
+ InOrder inOrder = Mockito.inOrder(mWakeupLock);
+
+ mWakeupController.start();
+ inOrder.verify(mWakeupLock).initialize(any());
+
+ mWakeupController.stop();
+ mWakeupController.reset();
+ mWakeupController.start();
+ inOrder.verify(mWakeupLock).initialize(any());
+ }
+
+ /**
+ * Verify that the wakeup lock is initialized with the intersection of ScanResults and saved
+ * networks.
+ */
+ @Test
+ public void startInitializesWakeupLockWithSavedScanResults() {
+ String ssid1 = "ssid 1";
+ String ssid2 = "ssid 2";
+ String quotedSsid = ScanResultUtil.createQuotedSSID(ssid1);
+
+ // saved configs
+ WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork(quotedSsid);
+ openNetwork.getNetworkSelectionStatus().setHasEverConnected(true);
+ WifiConfiguration wepNetwork = WifiConfigurationTestUtil.createWepNetwork();
+ wepNetwork.getNetworkSelectionStatus().setHasEverConnected(true);
+ when(mWifiConfigManager.getSavedNetworks())
+ .thenReturn(Arrays.asList(openNetwork, wepNetwork));
+
+ // scan results from most recent scan
+ ScanResult savedScanResult = createOpenScanResult(ssid1);
+ ScanResult unsavedScanResult = createOpenScanResult(ssid2);
+ when(mWifiScanner.getSingleScanResults())
+ .thenReturn(Arrays.asList(savedScanResult, unsavedScanResult));
+
+ // intersection of most recent scan + saved configs
+ Collection<ScanResultMatchInfo> expectedMatchInfos =
+ Collections.singleton(ScanResultMatchInfo.fromScanResult(savedScanResult));
+
+ initializeWakeupController(true /* enabled */);
+ mWakeupController.start();
+ verify(mWakeupLock).initialize(eq(expectedMatchInfos));
+ }
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
index a2c989a..5d6b14d 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
@@ -2880,11 +2880,6 @@
verifyAddNetworkToWifiConfigManager(network2);
verifyAddNetworkToWifiConfigManager(network3);
- // Enable all of them.
- assertTrue(mWifiConfigManager.enableNetwork(network1.networkId, false, TEST_CREATOR_UID));
- assertTrue(mWifiConfigManager.enableNetwork(network2.networkId, false, TEST_CREATOR_UID));
- assertTrue(mWifiConfigManager.enableNetwork(network3.networkId, false, TEST_CREATOR_UID));
-
// Now set scan results in 2 of them to set the corresponding
// {@link NetworkSelectionStatus#mSeenInLastQualifiedNetworkSelection} field.
assertTrue(mWifiConfigManager.setNetworkCandidateScanResult(
@@ -2903,15 +2898,6 @@
assertEquals(network3.SSID, hiddenNetworks.get(0).ssid);
assertEquals(network1.SSID, hiddenNetworks.get(1).ssid);
assertEquals(network2.SSID, hiddenNetworks.get(2).ssid);
-
- // Now permanently disable |network3|. This should remove network 3 from the list.
- assertTrue(mWifiConfigManager.disableNetwork(network3.networkId, TEST_CREATOR_UID));
-
- // Retrieve the hidden network list again & verify the order of the networks returned.
- hiddenNetworks = mWifiConfigManager.retrieveHiddenNetworkList();
- assertEquals(2, hiddenNetworks.size());
- assertEquals(network1.SSID, hiddenNetworks.get(0).ssid);
- assertEquals(network2.SSID, hiddenNetworks.get(1).ssid);
}
/**
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNativeInterfaceManagementTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNativeInterfaceManagementTest.java
new file mode 100644
index 0000000..fe08fe6
--- /dev/null
+++ b/tests/wifitests/src/com/android/server/wifi/WifiNativeInterfaceManagementTest.java
@@ -0,0 +1,759 @@
+/*
+ * Copyright (C) 2017 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 com.android.server.wifi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.*;
+
+import android.app.test.MockAnswerUtil;
+import android.net.InterfaceConfiguration;
+import android.net.wifi.IApInterface;
+import android.net.wifi.IClientInterface;
+import android.os.INetworkManagementService;
+import android.os.RemoteException;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.server.net.BaseNetworkObserver;
+import com.android.server.wifi.HalDeviceManager.InterfaceDestroyedListener;
+import com.android.server.wifi.WifiNative.SupplicantDeathEventHandler;
+import com.android.server.wifi.WifiNative.VendorHalDeathEventHandler;
+import com.android.server.wifi.WifiNative.WificondDeathEventHandler;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Unit tests for the interface management operations in
+ * {@link com.android.server.wifi.WifiNative}.
+ */
+@SmallTest
+public class WifiNativeInterfaceManagementTest {
+ private static final String IFACE_NAME_0 = "mockWlan0";
+ private static final String IFACE_NAME_1 = "mockWlan1";
+
+ @Mock private WifiVendorHal mWifiVendorHal;
+ @Mock private WificondControl mWificondControl;
+ @Mock private SupplicantStaIfaceHal mSupplicantStaIfaceHal;
+ @Mock private INetworkManagementService mNwManagementService;
+
+ @Mock private WifiNative.StatusListener mStatusListener;
+ @Mock private WifiNative.InterfaceCallback mIfaceCallback0;
+ @Mock private WifiNative.InterfaceCallback mIfaceCallback1;
+
+ private ArgumentCaptor<VendorHalDeathEventHandler> mWifiVendorHalDeathHandlerCaptor =
+ ArgumentCaptor.forClass(VendorHalDeathEventHandler.class);
+ private ArgumentCaptor<WificondDeathEventHandler> mWificondDeathHandlerCaptor =
+ ArgumentCaptor.forClass(WificondDeathEventHandler.class);
+ private ArgumentCaptor<SupplicantDeathEventHandler> mSupplicantDeathHandlerCaptor =
+ ArgumentCaptor.forClass(SupplicantDeathEventHandler.class);
+ private ArgumentCaptor<BaseNetworkObserver> mNetworkObserverCaptor0 =
+ ArgumentCaptor.forClass(BaseNetworkObserver.class);
+ private ArgumentCaptor<BaseNetworkObserver> mNetworkObserverCaptor1 =
+ ArgumentCaptor.forClass(BaseNetworkObserver.class);
+ private ArgumentCaptor<InterfaceDestroyedListener> mIfaceDestroyedListenerCaptor0 =
+ ArgumentCaptor.forClass(InterfaceDestroyedListener.class);
+ private ArgumentCaptor<InterfaceDestroyedListener> mIfaceDestroyedListenerCaptor1 =
+ ArgumentCaptor.forClass(InterfaceDestroyedListener.class);
+
+ private WifiNative mWifiNative;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ // Setup mocks for the positive single interface cases, individual tests can modify the
+ // mocks for negative or multi-interface tests.
+ when(mWifiVendorHal.initialize(mWifiVendorHalDeathHandlerCaptor.capture()))
+ .thenReturn(true);
+ when(mWifiVendorHal.startVendorHal()).thenReturn(true);
+ when(mWifiVendorHal.createStaIface(any())).thenReturn(IFACE_NAME_0);
+ when(mWifiVendorHal.createApIface(any())).thenReturn(IFACE_NAME_0);
+ when(mWifiVendorHal.removeStaIface(any())).thenReturn(true);
+ when(mWifiVendorHal.removeApIface(any())).thenReturn(true);
+
+ when(mWificondControl.registerDeathHandler(mWificondDeathHandlerCaptor.capture()))
+ .thenReturn(true);
+ when(mWificondControl.enableSupplicant()).thenReturn(true);
+ when(mWificondControl.disableSupplicant()).thenReturn(true);
+ when(mWificondControl.setupInterfaceForClientMode(any()))
+ .thenReturn(mock(IClientInterface.class));
+ when(mWificondControl.setupInterfaceForSoftApMode(any()))
+ .thenReturn(mock(IApInterface.class));
+ when(mWificondControl.tearDownClientInterface(any())).thenReturn(true);
+ when(mWificondControl.tearDownSoftApInterface(any())).thenReturn(true);
+ when(mWificondControl.tearDownInterfaces()).thenReturn(true);
+
+ when(mSupplicantStaIfaceHal.registerDeathHandler(mSupplicantDeathHandlerCaptor.capture()))
+ .thenReturn(true);
+ when(mSupplicantStaIfaceHal.deregisterDeathHandler()).thenReturn(true);
+ when(mSupplicantStaIfaceHal.initialize()).thenReturn(true);
+ when(mSupplicantStaIfaceHal.isInitializationStarted()).thenReturn(false);
+ when(mSupplicantStaIfaceHal.isInitializationComplete()).thenReturn(true);
+ when(mSupplicantStaIfaceHal.setupIface(any())).thenReturn(true);
+ when(mSupplicantStaIfaceHal.teardownIface(any())).thenReturn(true);
+
+ mWifiNative = new WifiNative(
+ IFACE_NAME_0, mWifiVendorHal, mSupplicantStaIfaceHal, mWificondControl,
+ mNwManagementService);
+ mWifiNative.initialize();
+ mWifiNative.registerStatusListener(mStatusListener);
+
+ verify(mWifiVendorHal).initialize(any());
+ verify(mWificondControl).registerDeathHandler(any());
+ }
+
+ /**
+ * Verifies the setup of a single client interface.
+ */
+ @Test
+ public void testSetupClientInterface() throws Exception {
+ executeAndValidateSetupClientInterface(
+ false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0,
+ mNetworkObserverCaptor0);
+ verifyNoMoreInteractions(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService, mIfaceCallback0, mIfaceCallback1);
+ }
+
+ /**
+ * Verifies the setup of a single softAp interface.
+ */
+ @Test
+ public void testSetupSoftApInterface() throws Exception {
+ executeAndValidateSetupSoftApInterface(
+ false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0,
+ mNetworkObserverCaptor0);
+ verifyNoMoreInteractions(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService, mIfaceCallback0, mIfaceCallback1);
+ }
+
+ /**
+ * Verifies the setup & teardown of a single client interface.
+ */
+ @Test
+ public void testSetupAndTeardownClientInterface() throws Exception {
+ executeAndValidateSetupClientInterface(
+ false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0,
+ mNetworkObserverCaptor0);
+ executeAndValidateTeardownClientInterface(false, false, IFACE_NAME_0, mIfaceCallback0,
+ mIfaceDestroyedListenerCaptor0.getValue(), mNetworkObserverCaptor0.getValue());
+ verifyNoMoreInteractions(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService, mIfaceCallback0, mIfaceCallback1);
+ }
+
+ /**
+ * Verifies the setup & teardown of a single client interface.
+ */
+ @Test
+ public void testSetupAndTeardownSoftApInterface() throws Exception {
+ executeAndValidateSetupSoftApInterface(
+ false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0,
+ mNetworkObserverCaptor0);
+ executeAndValidateTeardownSoftApInterface(false, false, IFACE_NAME_0, mIfaceCallback0,
+ mIfaceDestroyedListenerCaptor0.getValue(), mNetworkObserverCaptor0.getValue());
+ verifyNoMoreInteractions(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService, mIfaceCallback0, mIfaceCallback1);
+ }
+
+ /**
+ * Verifies the setup & teardown of a client & softAp interface.
+ */
+ @Test
+ public void testSetupAndTeardownClientAndSoftApInterface_Seq1() throws Exception {
+ executeAndValidateSetupClientInterface(
+ false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0,
+ mNetworkObserverCaptor0);
+ executeAndValidateSetupSoftApInterface(
+ true, false, IFACE_NAME_1, mIfaceCallback1, mIfaceDestroyedListenerCaptor1,
+ mNetworkObserverCaptor1);
+ executeAndValidateTeardownClientInterface(false, true, IFACE_NAME_0, mIfaceCallback0,
+ mIfaceDestroyedListenerCaptor0.getValue(), mNetworkObserverCaptor0.getValue());
+ executeAndValidateTeardownSoftApInterface(false, false, IFACE_NAME_1, mIfaceCallback1,
+ mIfaceDestroyedListenerCaptor1.getValue(), mNetworkObserverCaptor1.getValue());
+ verifyNoMoreInteractions(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService, mIfaceCallback0, mIfaceCallback1);
+ }
+
+ /**
+ * Verifies the setup & teardown of a client & softAp interface.
+ */
+ @Test
+ public void testSetupAndTeardownClientAndSoftApInterface_Seq2() throws Exception {
+ executeAndValidateSetupClientInterface(
+ false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0,
+ mNetworkObserverCaptor0);
+ executeAndValidateSetupSoftApInterface(
+ true, false, IFACE_NAME_1, mIfaceCallback1, mIfaceDestroyedListenerCaptor1,
+ mNetworkObserverCaptor1);
+ executeAndValidateTeardownSoftApInterface(true, false, IFACE_NAME_1, mIfaceCallback1,
+ mIfaceDestroyedListenerCaptor1.getValue(), mNetworkObserverCaptor1.getValue());
+ executeAndValidateTeardownClientInterface(false, false, IFACE_NAME_0, mIfaceCallback0,
+ mIfaceDestroyedListenerCaptor0.getValue(), mNetworkObserverCaptor0.getValue());
+ verifyNoMoreInteractions(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService, mIfaceCallback0, mIfaceCallback1);
+ }
+
+ /**
+ * Verifies the setup & teardown of a client & softAp interface.
+ */
+ @Test
+ public void testSetupAndTeardownClientAndSoftApInterface_Seq3() throws Exception {
+ executeAndValidateSetupSoftApInterface(
+ false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0,
+ mNetworkObserverCaptor0);
+ executeAndValidateSetupClientInterface(
+ false, true, IFACE_NAME_1, mIfaceCallback1, mIfaceDestroyedListenerCaptor1,
+ mNetworkObserverCaptor1);
+ executeAndValidateTeardownSoftApInterface(true, false, IFACE_NAME_0, mIfaceCallback0,
+ mIfaceDestroyedListenerCaptor0.getValue(), mNetworkObserverCaptor0.getValue());
+ executeAndValidateTeardownClientInterface(false, false, IFACE_NAME_1, mIfaceCallback1,
+ mIfaceDestroyedListenerCaptor1.getValue(), mNetworkObserverCaptor1.getValue());
+ verifyNoMoreInteractions(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService, mIfaceCallback0, mIfaceCallback1);
+ }
+
+ /**
+ * Verifies the setup & teardown of a client & softAp interface.
+ */
+ @Test
+ public void testSetupAndTeardownClientAndSoftApInterface_Seq4() throws Exception {
+ executeAndValidateSetupSoftApInterface(
+ false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0,
+ mNetworkObserverCaptor0);
+ executeAndValidateSetupClientInterface(
+ false, true, IFACE_NAME_1, mIfaceCallback1, mIfaceDestroyedListenerCaptor1,
+ mNetworkObserverCaptor1);
+ executeAndValidateTeardownClientInterface(false, true, IFACE_NAME_1, mIfaceCallback1,
+ mIfaceDestroyedListenerCaptor1.getValue(), mNetworkObserverCaptor1.getValue());
+ executeAndValidateTeardownSoftApInterface(false, false, IFACE_NAME_0, mIfaceCallback0,
+ mIfaceDestroyedListenerCaptor0.getValue(), mNetworkObserverCaptor0.getValue());
+ verifyNoMoreInteractions(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService, mIfaceCallback0, mIfaceCallback1);
+ }
+
+ /**
+ * Verifies the setup of a client interface and then a SoftAp interface which would
+ * destroy the Client interface. This is what would happen on older devices which do not
+ * support concurrent interfaces.
+ */
+ @Test
+ public void testSetupClientAndSoftApInterfaceCausesClientInterfaceTeardown() throws Exception {
+ executeAndValidateSetupClientInterface(
+ false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0,
+ mNetworkObserverCaptor0);
+
+ // Trigger the STA interface teardown when AP interface is created.
+ // The iface name will remain the same.
+ doAnswer(new MockAnswerUtil.AnswerWithArguments() {
+ public String answer(InterfaceDestroyedListener destroyedListener) {
+ mIfaceDestroyedListenerCaptor0.getValue().onDestroyed(IFACE_NAME_0);
+ return IFACE_NAME_0;
+ }
+ }).when(mWifiVendorHal).createApIface(any());
+
+ assertEquals(IFACE_NAME_0, mWifiNative.setupInterfaceForSoftApMode(mIfaceCallback1));
+
+ validateOnDestroyedClientInterface(
+ false, true, IFACE_NAME_0, mIfaceCallback0, mNetworkObserverCaptor0.getValue());
+ validateSetupSoftApInterface(
+ true, false, IFACE_NAME_0, mIfaceDestroyedListenerCaptor1,
+ mNetworkObserverCaptor1);
+
+ // Execute a teardown of the interface to ensure that the new iface removal works.
+ executeAndValidateTeardownSoftApInterface(false, false, IFACE_NAME_0, mIfaceCallback1,
+ mIfaceDestroyedListenerCaptor1.getValue(), mNetworkObserverCaptor1.getValue());
+
+ verifyNoMoreInteractions(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService, mIfaceCallback0, mIfaceCallback1);
+ }
+
+ /**
+ * Verifies the setup of a client interface and then a SoftAp interface which would
+ * destroy the Client interface. This is what would happen on older devices which do not
+ * support concurrent interfaces.
+ */
+ @Test
+ public void testSetupSoftApAndClientInterfaceCausesSoftApInterfaceTeardown() throws Exception {
+ executeAndValidateSetupSoftApInterface(
+ false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0,
+ mNetworkObserverCaptor0);
+
+ // Trigger the AP interface teardown when STA interface is created.
+ // The iface name will remain the same.
+ doAnswer(new MockAnswerUtil.AnswerWithArguments() {
+ public String answer(InterfaceDestroyedListener destroyedListener) {
+ mIfaceDestroyedListenerCaptor0.getValue().onDestroyed(IFACE_NAME_0);
+ return IFACE_NAME_0;
+ }
+ }).when(mWifiVendorHal).createStaIface(any());
+
+ assertEquals(IFACE_NAME_0, mWifiNative.setupInterfaceForClientMode(mIfaceCallback1));
+
+ validateOnDestroyedSoftApInterface(
+ true, false, IFACE_NAME_0, mIfaceCallback0, mNetworkObserverCaptor0.getValue());
+ validateSetupClientInterface(
+ false, true, IFACE_NAME_0, mIfaceDestroyedListenerCaptor1,
+ mNetworkObserverCaptor1);
+
+ // Execute a teardown of the interface to ensure that the new iface removal works.
+ executeAndValidateTeardownClientInterface(false, false, IFACE_NAME_0, mIfaceCallback1,
+ mIfaceDestroyedListenerCaptor1.getValue(), mNetworkObserverCaptor1.getValue());
+
+ verifyNoMoreInteractions(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService, mIfaceCallback0, mIfaceCallback1);
+ }
+
+ /**
+ * Verifies the setup of a client interface and trigger an interface down event.
+ */
+ @Test
+ public void testSetupClientInterfaceAndTriggerInterfaceDown() throws Exception {
+ executeAndValidateSetupSoftApInterface(
+ false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0,
+ mNetworkObserverCaptor0);
+
+ mNetworkObserverCaptor0.getValue().interfaceLinkStateChanged(IFACE_NAME_0, false);
+ verify(mIfaceCallback0).onDown(IFACE_NAME_0);
+
+ verifyNoMoreInteractions(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService, mIfaceCallback0, mIfaceCallback1);
+ }
+
+ /**
+ * Verifies the setup of a client interface and trigger an interface up event.
+ */
+ @Test
+ public void testSetupClientInterfaceAndTriggerInterfaceUp() throws Exception {
+ executeAndValidateSetupSoftApInterface(
+ false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0,
+ mNetworkObserverCaptor0);
+
+ mNetworkObserverCaptor0.getValue().interfaceLinkStateChanged(IFACE_NAME_0, true);
+ verify(mIfaceCallback0).onUp(IFACE_NAME_0);
+
+ verifyNoMoreInteractions(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService, mIfaceCallback0, mIfaceCallback1);
+ }
+
+ /**
+ * Verifies the setup of a client interface and wificond death handling.
+ */
+ @Test
+ public void testSetupClientInterfaceAndWicondDied() throws Exception {
+ executeAndValidateSetupClientInterface(
+ false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0,
+ mNetworkObserverCaptor0);
+ // Trigger wificond death
+ mWificondDeathHandlerCaptor.getValue().onDeath();
+
+ validateOnDestroyedClientInterface(false, false, IFACE_NAME_0, mIfaceCallback0,
+ mNetworkObserverCaptor0.getValue());
+
+ verify(mStatusListener).onStatusChanged(false);
+ verify(mStatusListener).onStatusChanged(true);
+ verifyNoMoreInteractions(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService, mIfaceCallback0, mIfaceCallback1);
+ }
+
+ /**
+ * Verifies the setup of a soft ap interface and vendor HAL death handling.
+ */
+ @Test
+ public void testSetupSoftApInterfaceAndVendorHalDied() throws Exception {
+ executeAndValidateSetupSoftApInterface(
+ false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0,
+ mNetworkObserverCaptor0);
+ // Trigger vendor HAL death
+ mWifiVendorHalDeathHandlerCaptor.getValue().onDeath();
+
+ validateOnDestroyedSoftApInterface(false, false, IFACE_NAME_0, mIfaceCallback0,
+ mNetworkObserverCaptor0.getValue());
+
+ verify(mStatusListener).onStatusChanged(false);
+ verify(mStatusListener).onStatusChanged(true);
+ verifyNoMoreInteractions(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService, mIfaceCallback0, mIfaceCallback1);
+ }
+
+ /**
+ * Verifies the setup of a client interface and supplicant HAL death handling.
+ */
+ @Test
+ public void testSetupClientInterfaceAndVendorHalDied() throws Exception {
+ executeAndValidateSetupClientInterface(
+ false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0,
+ mNetworkObserverCaptor0);
+ // Trigger wificond death
+ mSupplicantDeathHandlerCaptor.getValue().onDeath();
+
+ validateOnDestroyedClientInterface(false, false, IFACE_NAME_0, mIfaceCallback0,
+ mNetworkObserverCaptor0.getValue());
+
+ verify(mStatusListener).onStatusChanged(false);
+ verify(mStatusListener).onStatusChanged(true);
+ verifyNoMoreInteractions(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService, mIfaceCallback0, mIfaceCallback1);
+ }
+
+ /**
+ * Verifies failure handling in setup of a client interface.
+ */
+ @Test
+ public void testSetupClientInterfaceFailureInStartHal() throws Exception {
+ when(mWifiVendorHal.startVendorHal()).thenReturn(false);
+ assertNull(mWifiNative.setupInterfaceForClientMode(mIfaceCallback0));
+
+ InOrder inOrder = inOrder(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService);
+ inOrder.verify(mWifiVendorHal).startVendorHal();
+
+ // To test if the failure is handled cleanly, invoke teardown and ensure that
+ // none of the mocks are used because the iface does not exist in the internal
+ // database.
+ mWifiNative.teardownInterface(IFACE_NAME_0);
+
+ verifyNoMoreInteractions(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService, mIfaceCallback0, mIfaceCallback1);
+ }
+
+ /**
+ * Verifies failure handling in setup of a client interface.
+ */
+ @Test
+ public void testSetupClientInterfaceFailureInStartSupplicant() throws Exception {
+ when(mWificondControl.enableSupplicant()).thenReturn(false);
+ assertNull(mWifiNative.setupInterfaceForClientMode(mIfaceCallback0));
+
+ InOrder inOrder = inOrder(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService);
+ inOrder.verify(mWifiVendorHal).startVendorHal();
+ inOrder.verify(mWificondControl).enableSupplicant();
+
+ // To test if the failure is handled cleanly, invoke teardown and ensure that
+ // none of the mocks are used because the iface does not exist in the internal
+ // database.
+ mWifiNative.teardownInterface(IFACE_NAME_0);
+
+ verifyNoMoreInteractions(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService, mIfaceCallback0, mIfaceCallback1);
+ }
+
+ /**
+ * Verifies failure handling in setup of a client interface.
+ */
+ @Test
+ public void testSetupClientInterfaceFailureInHalCreateStaIface() throws Exception {
+ when(mWifiVendorHal.createStaIface(any())).thenReturn(null);
+ assertNull(mWifiNative.setupInterfaceForClientMode(mIfaceCallback0));
+
+ InOrder inOrder = inOrder(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService);
+ inOrder.verify(mWifiVendorHal).startVendorHal();
+ inOrder.verify(mWificondControl).enableSupplicant();
+ inOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted();
+ inOrder.verify(mSupplicantStaIfaceHal).initialize();
+ inOrder.verify(mSupplicantStaIfaceHal).isInitializationComplete();
+ inOrder.verify(mSupplicantStaIfaceHal).registerDeathHandler(any());
+ inOrder.verify(mWifiVendorHal).createStaIface(any());
+
+ // To test if the failure is handled cleanly, invoke teardown and ensure that
+ // none of the mocks are used because the iface does not exist in the internal
+ // database.
+ mWifiNative.teardownInterface(IFACE_NAME_0);
+
+ verifyNoMoreInteractions(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService, mIfaceCallback0, mIfaceCallback1);
+ }
+
+ /**
+ * Verifies failure handling in setup of a client interface.
+ */
+ @Test
+ public void testSetupClientInterfaceFailureInWificondSetupInterfaceForClientMode()
+ throws Exception {
+ when(mWificondControl.setupInterfaceForClientMode(any())).thenReturn(null);
+ assertNull(mWifiNative.setupInterfaceForClientMode(mIfaceCallback0));
+
+ InOrder inOrder = inOrder(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService);
+ inOrder.verify(mWifiVendorHal).startVendorHal();
+ inOrder.verify(mWificondControl).enableSupplicant();
+ inOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted();
+ inOrder.verify(mSupplicantStaIfaceHal).initialize();
+ inOrder.verify(mSupplicantStaIfaceHal).isInitializationComplete();
+ inOrder.verify(mSupplicantStaIfaceHal).registerDeathHandler(any());
+ inOrder.verify(mWifiVendorHal).createStaIface(mIfaceDestroyedListenerCaptor0.capture());
+ inOrder.verify(mWificondControl).setupInterfaceForClientMode(any());
+ inOrder.verify(mWifiVendorHal).removeStaIface(any());
+
+ // Trigger the HAL interface destroyed callback to verify the whole removal sequence.
+ mIfaceDestroyedListenerCaptor0.getValue().onDestroyed(IFACE_NAME_0);
+ validateOnDestroyedClientInterface(false, false, IFACE_NAME_0, mIfaceCallback0,
+ null);
+
+ // To test if the failure is handled cleanly, invoke teardown and ensure that
+ // none of the mocks are used because the iface does not exist in the internal
+ // database.
+ mWifiNative.teardownInterface(IFACE_NAME_0);
+
+ verifyNoMoreInteractions(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService, mIfaceCallback0, mIfaceCallback1);
+ }
+
+ /**
+ * Verifies failure handling in setup of a client interface.
+ */
+ @Test
+ public void testSetupClientInterfaceFailureInSupplicantSetupIface() throws Exception {
+ when(mSupplicantStaIfaceHal.setupIface(any())).thenReturn(false);
+ assertNull(mWifiNative.setupInterfaceForClientMode(mIfaceCallback0));
+
+ InOrder inOrder = inOrder(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService);
+ inOrder.verify(mWifiVendorHal).startVendorHal();
+ inOrder.verify(mWificondControl).enableSupplicant();
+ inOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted();
+ inOrder.verify(mSupplicantStaIfaceHal).initialize();
+ inOrder.verify(mSupplicantStaIfaceHal).isInitializationComplete();
+ inOrder.verify(mSupplicantStaIfaceHal).registerDeathHandler(any());
+ inOrder.verify(mWifiVendorHal).createStaIface(mIfaceDestroyedListenerCaptor0.capture());
+ inOrder.verify(mWificondControl).setupInterfaceForClientMode(any());
+ inOrder.verify(mSupplicantStaIfaceHal).setupIface(any());
+ inOrder.verify(mWifiVendorHal).removeStaIface(any());
+
+ // Trigger the HAL interface destroyed callback to verify the whole removal sequence.
+ mIfaceDestroyedListenerCaptor0.getValue().onDestroyed(IFACE_NAME_0);
+ validateOnDestroyedClientInterface(false, false, IFACE_NAME_0, mIfaceCallback0,
+ null);
+
+ // To test if the failure is handled cleanly, invoke teardown and ensure that
+ // none of the mocks are used because the iface does not exist in the internal
+ // database.
+ mWifiNative.teardownInterface(IFACE_NAME_0);
+
+ verifyNoMoreInteractions(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService, mIfaceCallback0, mIfaceCallback1);
+ }
+
+ /**
+ * Verifies failure handling in setup of a client interface.
+ */
+ @Test
+ public void testSetupClientInterfaceFailureInNetworkObserverRegister() throws Exception {
+ doThrow(new RemoteException()).when(mNwManagementService).registerObserver(any());
+ assertNull(mWifiNative.setupInterfaceForClientMode(mIfaceCallback0));
+
+ InOrder inOrder = inOrder(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService);
+ inOrder.verify(mWifiVendorHal).startVendorHal();
+ inOrder.verify(mWificondControl).enableSupplicant();
+ inOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted();
+ inOrder.verify(mSupplicantStaIfaceHal).initialize();
+ inOrder.verify(mSupplicantStaIfaceHal).isInitializationComplete();
+ inOrder.verify(mSupplicantStaIfaceHal).registerDeathHandler(any());
+ inOrder.verify(mWifiVendorHal).createStaIface(mIfaceDestroyedListenerCaptor0.capture());
+ inOrder.verify(mWificondControl).setupInterfaceForClientMode(any());
+ inOrder.verify(mSupplicantStaIfaceHal).setupIface(any());
+ inOrder.verify(mNwManagementService).registerObserver(mNetworkObserverCaptor0.capture());
+ inOrder.verify(mWifiVendorHal).removeStaIface(any());
+
+ // Trigger the HAL interface destroyed callback to verify the whole removal sequence.
+ mIfaceDestroyedListenerCaptor0.getValue().onDestroyed(IFACE_NAME_0);
+ validateOnDestroyedClientInterface(false, false, IFACE_NAME_0, mIfaceCallback0,
+ mNetworkObserverCaptor0.getValue());
+
+ // To test if the failure is handled cleanly, invoke teardown and ensure that
+ // none of the mocks are used because the iface does not exist in the internal
+ // database.
+ mWifiNative.teardownInterface(IFACE_NAME_0);
+
+ verifyNoMoreInteractions(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService, mIfaceCallback0, mIfaceCallback1);
+ }
+
+ /**
+ * Verifies the interface state query API.
+ */
+ @Test
+ public void testIsInterfaceUp() throws Exception {
+ executeAndValidateSetupClientInterface(
+ false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0,
+ mNetworkObserverCaptor0);
+
+ InterfaceConfiguration config = new InterfaceConfiguration();
+ when(mNwManagementService.getInterfaceConfig(IFACE_NAME_0)).thenReturn(config);
+
+ config.setInterfaceUp();
+ assertTrue(mWifiNative.isInterfaceUp(IFACE_NAME_0));
+
+ config.setInterfaceDown();
+ assertFalse(mWifiNative.isInterfaceUp(IFACE_NAME_0));
+
+ when(mNwManagementService.getInterfaceConfig(IFACE_NAME_0)).thenReturn(null);
+ assertFalse(mWifiNative.isInterfaceUp(IFACE_NAME_0));
+
+ verify(mNwManagementService, times(3)).getInterfaceConfig(IFACE_NAME_0);
+
+ verifyNoMoreInteractions(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService, mIfaceCallback0, mIfaceCallback1);
+ }
+
+ private void executeAndValidateSetupClientInterface(
+ boolean existingStaIface, boolean existingApIface,
+ String ifaceName, @Mock WifiNative.InterfaceCallback callback,
+ ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor,
+ ArgumentCaptor<BaseNetworkObserver> networkObserverCaptor) throws Exception {
+ when(mWifiVendorHal.createStaIface(any())).thenReturn(ifaceName);
+ assertEquals(ifaceName, mWifiNative.setupInterfaceForClientMode(callback));
+
+ validateSetupClientInterface(
+ existingStaIface, existingApIface, ifaceName, destroyedListenerCaptor,
+ networkObserverCaptor);
+ }
+
+ private void validateSetupClientInterface(
+ boolean existingStaIface, boolean existingApIface,
+ String ifaceName, ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor,
+ ArgumentCaptor<BaseNetworkObserver> networkObserverCaptor) throws Exception {
+ InOrder inOrder = inOrder(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService);
+
+ if (!existingStaIface && !existingApIface) {
+ inOrder.verify(mWifiVendorHal).startVendorHal();
+ }
+ if (!existingStaIface) {
+ inOrder.verify(mWificondControl).enableSupplicant();
+ inOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted();
+ inOrder.verify(mSupplicantStaIfaceHal).initialize();
+ inOrder.verify(mSupplicantStaIfaceHal).isInitializationComplete();
+ inOrder.verify(mSupplicantStaIfaceHal).registerDeathHandler(any());
+ }
+ inOrder.verify(mWifiVendorHal).createStaIface(destroyedListenerCaptor.capture());
+ inOrder.verify(mWificondControl).setupInterfaceForClientMode(ifaceName);
+ inOrder.verify(mSupplicantStaIfaceHal).setupIface(ifaceName);
+ inOrder.verify(mNwManagementService).registerObserver(networkObserverCaptor.capture());
+ }
+
+ private void executeAndValidateTeardownClientInterface(
+ boolean anyOtherStaIface, boolean anyOtherApIface,
+ String ifaceName, @Mock WifiNative.InterfaceCallback callback,
+ InterfaceDestroyedListener destroyedListener,
+ BaseNetworkObserver networkObserver) throws Exception {
+ InOrder inOrder = inOrder(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService, callback);
+
+ mWifiNative.teardownInterface(ifaceName);
+
+ inOrder.verify(mWifiVendorHal).removeStaIface(ifaceName);
+
+ // Now trigger the HalDeviceManager destroy callback to initiate the rest of the teardown.
+ destroyedListener.onDestroyed(ifaceName);
+
+ validateOnDestroyedClientInterface(
+ anyOtherStaIface, anyOtherApIface, ifaceName, callback, networkObserver);
+ }
+
+ private void validateOnDestroyedClientInterface(
+ boolean anyOtherStaIface, boolean anyOtherApIface,
+ String ifaceName, @Mock WifiNative.InterfaceCallback callback,
+ BaseNetworkObserver networkObserver) throws Exception {
+ InOrder inOrder = inOrder(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
+ mNwManagementService, callback);
+
+ inOrder.verify(mNwManagementService).unregisterObserver(networkObserver);
+ inOrder.verify(mSupplicantStaIfaceHal).teardownIface(ifaceName);
+ inOrder.verify(mWificondControl).tearDownClientInterface(ifaceName);
+
+ if (!anyOtherStaIface) {
+ inOrder.verify(mSupplicantStaIfaceHal).deregisterDeathHandler();
+ inOrder.verify(mWificondControl).disableSupplicant();
+ }
+ if (!anyOtherStaIface && !anyOtherApIface) {
+ inOrder.verify(mWificondControl).tearDownInterfaces();
+ inOrder.verify(mWifiVendorHal).stopVendorHal();
+ }
+ inOrder.verify(callback).onDestroyed(ifaceName);
+ }
+
+ private void executeAndValidateSetupSoftApInterface(
+ boolean existingStaIface, boolean existingApIface,
+ String ifaceName, @Mock WifiNative.InterfaceCallback callback,
+ ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor,
+ ArgumentCaptor<BaseNetworkObserver> networkObserverCaptor) throws Exception {
+ when(mWifiVendorHal.createApIface(any())).thenReturn(ifaceName);
+ assertEquals(ifaceName, mWifiNative.setupInterfaceForSoftApMode(callback));
+
+ validateSetupSoftApInterface(
+ existingStaIface, existingApIface, ifaceName, destroyedListenerCaptor,
+ networkObserverCaptor);
+ }
+
+ private void validateSetupSoftApInterface(
+ boolean existingStaIface, boolean existingApIface,
+ String ifaceName, ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor,
+ ArgumentCaptor<BaseNetworkObserver> networkObserverCaptor) throws Exception {
+ InOrder inOrder = inOrder(mWifiVendorHal, mWificondControl, mNwManagementService);
+
+ if (!existingStaIface && !existingApIface) {
+ inOrder.verify(mWifiVendorHal).startVendorHal();
+ }
+ inOrder.verify(mWifiVendorHal).createApIface(destroyedListenerCaptor.capture());
+ inOrder.verify(mWificondControl).setupInterfaceForSoftApMode(ifaceName);
+ inOrder.verify(mNwManagementService).registerObserver(networkObserverCaptor.capture());
+ }
+
+ private void executeAndValidateTeardownSoftApInterface(
+ boolean anyOtherStaIface, boolean anyOtherApIface,
+ String ifaceName, @Mock WifiNative.InterfaceCallback callback,
+ InterfaceDestroyedListener destroyedListener,
+ BaseNetworkObserver networkObserver) throws Exception {
+ InOrder inOrder = inOrder(mWifiVendorHal, mWificondControl, mNwManagementService, callback);
+
+ mWifiNative.teardownInterface(ifaceName);
+
+ inOrder.verify(mWifiVendorHal).removeApIface(ifaceName);
+
+ // Now trigger the HalDeviceManager destroy callback to initiate the rest of the teardown.
+ destroyedListener.onDestroyed(ifaceName);
+
+ validateOnDestroyedSoftApInterface(
+ anyOtherStaIface, anyOtherApIface, ifaceName, callback, networkObserver);
+ }
+
+ private void validateOnDestroyedSoftApInterface(
+ boolean anyOtherStaIface, boolean anyOtherApIface,
+ String ifaceName, @Mock WifiNative.InterfaceCallback callback,
+ BaseNetworkObserver networkObserver) throws Exception {
+ InOrder inOrder = inOrder(mWifiVendorHal, mWificondControl, mNwManagementService, callback);
+
+ inOrder.verify(mNwManagementService).unregisterObserver(networkObserver);
+ inOrder.verify(mWificondControl).stopSoftAp(ifaceName);
+ inOrder.verify(mWificondControl).tearDownSoftApInterface(ifaceName);
+
+ if (!anyOtherStaIface && !anyOtherApIface) {
+ inOrder.verify(mWificondControl).tearDownInterfaces();
+ inOrder.verify(mWifiVendorHal).stopVendorHal();
+ }
+ inOrder.verify(callback).onDestroyed(ifaceName);
+ }
+}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java
index 9a79a23..4c2b6f7 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java
@@ -28,6 +28,7 @@
import android.net.wifi.IApInterface;
import android.net.wifi.IClientInterface;
import android.net.wifi.WifiConfiguration;
+import android.os.INetworkManagementService;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Pair;
@@ -148,6 +149,7 @@
@Mock private WifiVendorHal mWifiVendorHal;
@Mock private WificondControl mWificondControl;
@Mock private SupplicantStaIfaceHal mStaIfaceHal;
+ @Mock private INetworkManagementService mNwService;
private WifiNative mWifiNative;
@Before
@@ -156,8 +158,8 @@
when(mWifiVendorHal.isVendorHalSupported()).thenReturn(true);
when(mWifiVendorHal.startVendorHalSta()).thenReturn(true);
when(mWifiVendorHal.startVendorHalAp()).thenReturn(true);
- mWifiNative =
- new WifiNative(WIFI_IFACE_NAME, mWifiVendorHal, mStaIfaceHal, mWificondControl);
+ mWifiNative = new WifiNative(
+ WIFI_IFACE_NAME, mWifiVendorHal, mStaIfaceHal, mWificondControl, mNwService);
}
/**
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
index d0a482e..52281df 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
@@ -1177,7 +1177,7 @@
IFACE_IP_MODE_LOCAL_ONLY);
mLooper.dispatchAll();
- verifyNoMoreInteractions(mHandler);
+ verify(mHandler, never()).handleMessage(any(Message.class));
}
/**
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
index 5208c74..7e2a17b 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
@@ -2766,4 +2766,38 @@
mWsm.dump(null, writer, null);
verify(mWakeupController).dump(null, writer, null);
}
+
+ /**
+ * Verify that entering and exiting scan mode state correctly triggers Wakeup lifecycle events.
+ */
+ @Test
+ public void verifyScanModeStateTransitionsTriggerWakeupLifecycleEvents() throws Exception {
+ loadComponentsInStaMode();
+
+ // enter scan mode
+ mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_MODE);
+ mLooper.dispatchAll();
+
+ // exit scan mode
+ mWsm.setOperationalMode(WifiStateMachine.DISABLED_MODE);
+ mLooper.dispatchAll();
+
+ InOrder inOrder = inOrder(mWakeupController);
+ inOrder.verify(mWakeupController).start();
+ inOrder.verify(mWakeupController).stop();
+ }
+
+ /**
+ * Verify that entering connect mode state resets WakeupController events.
+ */
+ @Test
+ public void verifyConnectModeStateTransitionsTriggerWakeupLifecycleEvents() throws Exception {
+ loadComponentsInStaMode();
+
+ // enter connect mode
+ mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
+ mLooper.dispatchAll();
+
+ verify(mWakeupController).reset();
+ }
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java b/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java
index 812ef03..9830b91 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java
@@ -88,6 +88,7 @@
import android.util.Pair;
import com.android.server.connectivity.KeepalivePacketData;
+import com.android.server.wifi.HalDeviceManager.InterfaceDestroyedListener;
import com.android.server.wifi.util.NativeUtil;
import org.junit.Before;
@@ -191,9 +192,9 @@
mHalDeviceManagerStatusCallbacks.onStatusChanged();
}
}).when(mHalDeviceManager).stop();
- when(mHalDeviceManager.createStaIface(eq(null), eq(null)))
+ when(mHalDeviceManager.createStaIface(any(), eq(null)))
.thenReturn(mIWifiStaIface);
- when(mHalDeviceManager.createApIface(eq(null), eq(null)))
+ when(mHalDeviceManager.createApIface(any(), eq(null)))
.thenReturn(mIWifiApIface);
when(mHalDeviceManager.removeIface(any())).thenReturn(true);
when(mHalDeviceManager.getChip(any(IWifiIface.class)))
@@ -255,7 +256,7 @@
assertTrue(mWifiVendorHal.isHalStarted());
verify(mHalDeviceManager).start();
- verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
+ verify(mHalDeviceManager).createStaIface(any(), eq(null));
verify(mHalDeviceManager).getChip(eq(mIWifiStaIface));
verify(mHalDeviceManager).createRttController();
verify(mHalDeviceManager).isReady();
@@ -263,7 +264,7 @@
verify(mIWifiStaIface).registerEventCallback(any(IWifiStaIfaceEventCallback.class));
verify(mIWifiChip).registerEventCallback(any(IWifiChipEventCallback.class));
- verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
+ verify(mHalDeviceManager, never()).createApIface(any(), eq(null));
}
/**
@@ -276,12 +277,12 @@
assertTrue(mWifiVendorHal.isHalStarted());
verify(mHalDeviceManager).start();
- verify(mHalDeviceManager).createApIface(eq(null), eq(null));
+ verify(mHalDeviceManager).createApIface(any(), eq(null));
verify(mHalDeviceManager).getChip(eq(mIWifiApIface));
verify(mHalDeviceManager).isReady();
verify(mHalDeviceManager).isStarted();
- verify(mHalDeviceManager, never()).createStaIface(eq(null), eq(null));
+ verify(mHalDeviceManager, never()).createStaIface(any(), eq(null));
verify(mHalDeviceManager, never()).createRttController();
}
@@ -303,8 +304,8 @@
verify(mHalDeviceManager).start();
- verify(mHalDeviceManager, never()).createStaIface(eq(null), eq(null));
- verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
+ verify(mHalDeviceManager, never()).createStaIface(any(), eq(null));
+ verify(mHalDeviceManager, never()).createApIface(any(), eq(null));
verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class));
verify(mHalDeviceManager, never()).createRttController();
verify(mIWifiStaIface, never())
@@ -317,15 +318,15 @@
*/
@Test
public void testStartHalFailureInIfaceCreationInStaMode() throws Exception {
- when(mHalDeviceManager.createStaIface(eq(null), eq(null))).thenReturn(null);
+ when(mHalDeviceManager.createStaIface(any(), eq(null))).thenReturn(null);
assertFalse(mWifiVendorHal.startVendorHalSta());
assertFalse(mWifiVendorHal.isHalStarted());
verify(mHalDeviceManager).start();
- verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
+ verify(mHalDeviceManager).createStaIface(any(), eq(null));
verify(mHalDeviceManager).stop();
- verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
+ verify(mHalDeviceManager, never()).createApIface(any(), eq(null));
verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class));
verify(mHalDeviceManager, never()).createRttController();
verify(mIWifiStaIface, never())
@@ -343,12 +344,12 @@
assertFalse(mWifiVendorHal.isHalStarted());
verify(mHalDeviceManager).start();
- verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
+ verify(mHalDeviceManager).createStaIface(any(), eq(null));
verify(mHalDeviceManager).createRttController();
verify(mHalDeviceManager).stop();
verify(mIWifiStaIface).registerEventCallback(any(IWifiStaIfaceEventCallback.class));
- verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
+ verify(mHalDeviceManager, never()).createApIface(any(), eq(null));
verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class));
}
@@ -363,13 +364,13 @@
assertFalse(mWifiVendorHal.isHalStarted());
verify(mHalDeviceManager).start();
- verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
+ verify(mHalDeviceManager).createStaIface(any(), eq(null));
verify(mHalDeviceManager).createRttController();
verify(mHalDeviceManager).getChip(any(IWifiIface.class));
verify(mHalDeviceManager).stop();
verify(mIWifiStaIface).registerEventCallback(any(IWifiStaIfaceEventCallback.class));
- verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
+ verify(mHalDeviceManager, never()).createApIface(any(), eq(null));
}
/**
@@ -384,13 +385,13 @@
assertFalse(mWifiVendorHal.isHalStarted());
verify(mHalDeviceManager).start();
- verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
+ verify(mHalDeviceManager).createStaIface(any(), eq(null));
verify(mHalDeviceManager).stop();
verify(mIWifiStaIface).registerEventCallback(any(IWifiStaIfaceEventCallback.class));
verify(mHalDeviceManager, never()).createRttController();
verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class));
- verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
+ verify(mHalDeviceManager, never()).createApIface(any(), eq(null));
}
/**
@@ -405,14 +406,14 @@
assertFalse(mWifiVendorHal.isHalStarted());
verify(mHalDeviceManager).start();
- verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
+ verify(mHalDeviceManager).createStaIface(any(), eq(null));
verify(mHalDeviceManager).createRttController();
verify(mHalDeviceManager).getChip(any(IWifiIface.class));
verify(mHalDeviceManager).stop();
verify(mIWifiStaIface).registerEventCallback(any(IWifiStaIfaceEventCallback.class));
verify(mIWifiChip).registerEventCallback(any(IWifiChipEventCallback.class));
- verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
+ verify(mHalDeviceManager, never()).createApIface(any(), eq(null));
}
/**
@@ -421,15 +422,15 @@
*/
@Test
public void testStartHalFailureInApMode() throws Exception {
- when(mHalDeviceManager.createApIface(eq(null), eq(null))).thenReturn(null);
+ when(mHalDeviceManager.createApIface(any(), eq(null))).thenReturn(null);
assertFalse(mWifiVendorHal.startVendorHalAp());
assertFalse(mWifiVendorHal.isHalStarted());
verify(mHalDeviceManager).start();
- verify(mHalDeviceManager).createApIface(eq(null), eq(null));
+ verify(mHalDeviceManager).createApIface(any(), eq(null));
verify(mHalDeviceManager).stop();
- verify(mHalDeviceManager, never()).createStaIface(eq(null), eq(null));
+ verify(mHalDeviceManager, never()).createStaIface(any(), eq(null));
verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class));
verify(mHalDeviceManager, never()).createRttController();
}
@@ -448,13 +449,13 @@
verify(mHalDeviceManager).start();
verify(mHalDeviceManager).stop();
- verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
+ verify(mHalDeviceManager).createStaIface(any(), eq(null));
verify(mHalDeviceManager).getChip(eq(mIWifiStaIface));
verify(mHalDeviceManager).createRttController();
verify(mHalDeviceManager, times(2)).isReady();
verify(mHalDeviceManager, times(2)).isStarted();
- verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
+ verify(mHalDeviceManager, never()).createApIface(any(), eq(null));
}
/**
@@ -471,16 +472,78 @@
verify(mHalDeviceManager).start();
verify(mHalDeviceManager).stop();
- verify(mHalDeviceManager).createApIface(eq(null), eq(null));
+ verify(mHalDeviceManager).createApIface(any(), eq(null));
verify(mHalDeviceManager).getChip(eq(mIWifiApIface));
verify(mHalDeviceManager, times(2)).isReady();
verify(mHalDeviceManager, times(2)).isStarted();
- verify(mHalDeviceManager, never()).createStaIface(eq(null), eq(null));
+ verify(mHalDeviceManager, never()).createStaIface(any(), eq(null));
verify(mHalDeviceManager, never()).createRttController();
}
/**
+ * Tests the handling of interface destroyed callback from HalDeviceManager.
+ */
+ @Test
+ public void testStaInterfaceDestroyedHandling() throws Exception {
+ ArgumentCaptor<InterfaceDestroyedListener> internalListenerCaptor =
+ ArgumentCaptor.forClass(InterfaceDestroyedListener.class);
+ InterfaceDestroyedListener externalLister = mock(InterfaceDestroyedListener.class);
+
+ assertTrue(mWifiVendorHal.startVendorHal());
+ assertNotNull(mWifiVendorHal.createStaIface(externalLister));
+ assertTrue(mWifiVendorHal.isHalStarted());
+
+ verify(mHalDeviceManager).start();
+ verify(mHalDeviceManager).createStaIface(internalListenerCaptor.capture(), eq(null));
+ verify(mHalDeviceManager).getChip(eq(mIWifiStaIface));
+ verify(mHalDeviceManager).createRttController();
+ verify(mHalDeviceManager).isReady();
+ verify(mHalDeviceManager).isStarted();
+ verify(mIWifiStaIface).registerEventCallback(any(IWifiStaIfaceEventCallback.class));
+ verify(mIWifiChip).registerEventCallback(any(IWifiChipEventCallback.class));
+
+ // Now trigger the interface destroyed callback from HalDeviceManager and ensure the
+ // external listener is invoked and iface removed from internal database.
+ internalListenerCaptor.getValue().onDestroyed(TEST_IFACE_NAME);
+ verify(externalLister).onDestroyed(TEST_IFACE_NAME);
+
+ // This should fail now, since the interface was already destroyed.
+ assertFalse(mWifiVendorHal.removeStaIface(TEST_IFACE_NAME));
+ verify(mHalDeviceManager, never()).removeIface(any());
+ }
+
+ /**
+ * Tests the handling of interface destroyed callback from HalDeviceManager.
+ */
+ @Test
+ public void testApInterfaceDestroyedHandling() throws Exception {
+ ArgumentCaptor<InterfaceDestroyedListener> internalListenerCaptor =
+ ArgumentCaptor.forClass(InterfaceDestroyedListener.class);
+ InterfaceDestroyedListener externalLister = mock(InterfaceDestroyedListener.class);
+
+ assertTrue(mWifiVendorHal.startVendorHal());
+ assertNotNull(mWifiVendorHal.createApIface(externalLister));
+ assertTrue(mWifiVendorHal.isHalStarted());
+
+ verify(mHalDeviceManager).start();
+ verify(mHalDeviceManager).createApIface(internalListenerCaptor.capture(), eq(null));
+ verify(mHalDeviceManager).getChip(eq(mIWifiApIface));
+ verify(mHalDeviceManager).isReady();
+ verify(mHalDeviceManager).isStarted();
+ verify(mIWifiChip).registerEventCallback(any(IWifiChipEventCallback.class));
+
+ // Now trigger the interface destroyed callback from HalDeviceManager and ensure the
+ // external listener is invoked and iface removed from internal database.
+ internalListenerCaptor.getValue().onDestroyed(TEST_IFACE_NAME);
+ verify(externalLister).onDestroyed(TEST_IFACE_NAME);
+
+ // This should fail now, since the interface was already destroyed.
+ assertFalse(mWifiVendorHal.removeApIface(TEST_IFACE_NAME));
+ verify(mHalDeviceManager, never()).removeIface(any());
+ }
+
+ /**
* Test that enter logs when verbose logging is enabled
*/
@Test
@@ -1957,7 +2020,7 @@
assertTrue(mWifiVendorHal.startVendorHal());
assertNull(mWifiVendorHal.createStaIface(null));
- verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
+ verify(mHalDeviceManager).createStaIface(any(), eq(null));
}
/**
@@ -1974,7 +2037,7 @@
assertTrue(mWifiVendorHal.startVendorHal());
assertNull(mWifiVendorHal.createApIface(null));
- verify(mHalDeviceManager).createApIface(eq(null), eq(null));
+ verify(mHalDeviceManager).createApIface(any(), eq(null));
}
/**
@@ -1984,7 +2047,7 @@
public void testCreateRemoveStaIface() throws RemoteException {
assertTrue(mWifiVendorHal.startVendorHal());
String ifaceName = mWifiVendorHal.createStaIface(null);
- verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
+ verify(mHalDeviceManager).createStaIface(any(), eq(null));
assertEquals(TEST_IFACE_NAME, ifaceName);
assertTrue(mWifiVendorHal.removeStaIface(ifaceName));
verify(mHalDeviceManager).removeIface(eq(mIWifiStaIface));
@@ -1997,7 +2060,7 @@
public void testCreateRemoveApIface() throws RemoteException {
assertTrue(mWifiVendorHal.startVendorHal());
String ifaceName = mWifiVendorHal.createApIface(null);
- verify(mHalDeviceManager).createApIface(eq(null), eq(null));
+ verify(mHalDeviceManager).createApIface(any(), eq(null));
assertEquals(TEST_IFACE_NAME, ifaceName);
assertTrue(mWifiVendorHal.removeApIface(ifaceName));
verify(mHalDeviceManager).removeIface(eq(mIWifiApIface));
diff --git a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareNativeManagerTest.java b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareNativeManagerTest.java
index 122d6e6..56515ee 100644
--- a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareNativeManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareNativeManagerTest.java
@@ -16,11 +16,12 @@
package com.android.server.wifi.aware;
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.hamcrest.core.IsNull.nullValue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
@@ -78,86 +79,165 @@
mDut.start(mHandlerMock);
mInOrder = inOrder(mWifiAwareStateManagerMock, mHalDeviceManager);
+
+ // validate (and capture) that register manage status callback
+ mInOrder.verify(mHalDeviceManager).initialize();
+ mInOrder.verify(mHalDeviceManager).registerStatusListener(
+ mManagerStatusListenerCaptor.capture(), any());
}
/**
- * Test the control flow of the manager:
+ * Test the control flow of the manager when Aware isn't being actively used:
+ *
* 1. onStatusChange (ready/started)
- * 2. null NAN iface
- * 3. onAvailableForRequest
- * 4. non-null NAN iface -> enableUsage
- * 5. onStatusChange (!started) -> disableUsage
- * 6. onStatusChange (ready/started)
- * 7. non-null NAN iface -> enableUsage
- * 8. onDestroyed -> disableUsage
- * 9. onStatusChange (!started)
+ * 2. on available -> enableUsage
+ * 3. onStatusChange (!started) -> disableUsage
+ * 4. onStatusChange (ready/started) + available -> enableUsage
+ * 5. on not available -> disableUsage
+ *
+ * --> no interface creation at any point!
*/
@Test
- public void testControlFlow() {
- // configure HalDeviceManager as ready/wifi started
+ public void testControlFlowWithoutInterface() {
+ // configure HalDeviceManager as ready/wifi started (and to return an interface if
+ // requested)
when(mHalDeviceManager.isReady()).thenReturn(true);
when(mHalDeviceManager.isStarted()).thenReturn(true);
+ when(mHalDeviceManager.createNanIface(any(), any())).thenReturn(mWifiNanIfaceMock);
- // validate (and capture) that register manage status callback
- mInOrder.verify(mHalDeviceManager).registerStatusListener(
- mManagerStatusListenerCaptor.capture(), any());
-
- // 1 & 2 onStatusChange (ready/started): validate that trying to get a NAN interface
- // (make sure gets a NULL)
- when(mHalDeviceManager.createNanIface(any(), any())).thenReturn(null);
-
+ // 1. onStatusChange (ready/started)
mManagerStatusListenerCaptor.getValue().onStatusChanged();
mInOrder.verify(mHalDeviceManager).registerInterfaceAvailableForRequestListener(
eq(IfaceType.NAN), mAvailListenerCaptor.capture(), any(Handler.class));
- mAvailListenerCaptor.getValue().onAvailableForRequest();
- mInOrder.verify(mHalDeviceManager).createNanIface(
- mDestroyedListenerCaptor.capture(), any());
- collector.checkThat("null interface", mDut.getWifiNanIface(), nullValue());
-
- // 3 & 4 onAvailableForRequest + non-null return value: validate that enables usage
- when(mHalDeviceManager.createNanIface(any(), any())).thenReturn(mWifiNanIfaceMock);
-
- mAvailListenerCaptor.getValue().onAvailableForRequest();
-
- mInOrder.verify(mHalDeviceManager).createNanIface(
- mDestroyedListenerCaptor.capture(), any());
+ // 2. NAN is available -> enableUsage
+ mAvailListenerCaptor.getValue().onAvailabilityChanged(true);
mInOrder.verify(mWifiAwareStateManagerMock).enableUsage();
- collector.checkThat("non-null interface", mDut.getWifiNanIface(),
- equalTo(mWifiNanIfaceMock));
- // 5 onStatusChange (!started): disable usage
+ // 3. onStatusChange (not ready) -> disableUsage
when(mHalDeviceManager.isStarted()).thenReturn(false);
mManagerStatusListenerCaptor.getValue().onStatusChanged();
mInOrder.verify(mWifiAwareStateManagerMock).disableUsage();
- collector.checkThat("null interface", mDut.getWifiNanIface(), nullValue());
- // 6 & 7 onStatusChange (ready/started) + non-null NAN interface: enable usage
+ // 4. onStatusChange (ready/started) + available -> enableUsage
when(mHalDeviceManager.isStarted()).thenReturn(true);
mManagerStatusListenerCaptor.getValue().onStatusChanged();
mManagerStatusListenerCaptor.getValue().onStatusChanged();
mInOrder.verify(mHalDeviceManager).registerInterfaceAvailableForRequestListener(
eq(IfaceType.NAN), mAvailListenerCaptor.capture(), any(Handler.class));
- mAvailListenerCaptor.getValue().onAvailableForRequest();
+ mAvailListenerCaptor.getValue().onAvailabilityChanged(true);
- mInOrder.verify(mHalDeviceManager).createNanIface(
- mDestroyedListenerCaptor.capture(), any());
mInOrder.verify(mWifiAwareStateManagerMock).enableUsage();
- collector.checkThat("non-null interface", mDut.getWifiNanIface(),
- equalTo(mWifiNanIfaceMock));
- // 8 onDestroyed: disable usage
- mDestroyedListenerCaptor.getValue().onDestroyed(new String());
+ // 5. not available -> disableUsage
+ mAvailListenerCaptor.getValue().onAvailabilityChanged(false);
mInOrder.verify(mWifiAwareStateManagerMock).disableUsage();
- collector.checkThat("null interface", mDut.getWifiNanIface(), nullValue());
- // 9 onStatusChange (!started): nothing more happens
- when(mHalDeviceManager.isStarted()).thenReturn(false);
+ mInOrder.verify(mHalDeviceManager, never()).createNanIface(any(), any());
+ verifyNoMoreInteractions(mWifiAwareStateManagerMock);
+ assertNull("Interface non-null!", mDut.getWifiNanIface());
+ }
+
+ /**
+ * Test the control flow (and reference counting) of the manager when Aware is actively used and
+ * reference counted (i.e. irregular requests/releases).
+ */
+ @Test
+ public void testReferenceCounting() {
+ // configure HalDeviceManager as ready/wifi started (and to return an interface if
+ // requested)
+ when(mHalDeviceManager.isReady()).thenReturn(true);
+ when(mHalDeviceManager.isStarted()).thenReturn(true);
+ when(mHalDeviceManager.createNanIface(any(), any())).thenReturn(mWifiNanIfaceMock);
+
+ // 1. onStatusChange (ready/started)
mManagerStatusListenerCaptor.getValue().onStatusChanged();
+ mInOrder.verify(mHalDeviceManager).registerInterfaceAvailableForRequestListener(
+ eq(IfaceType.NAN), mAvailListenerCaptor.capture(), any(Handler.class));
+ assertNull("Interface non-null!", mDut.getWifiNanIface());
+ mAvailListenerCaptor.getValue().onAvailabilityChanged(true);
+ mInOrder.verify(mWifiAwareStateManagerMock).enableUsage();
+
+ // 2. request (interface obtained)
+ mDut.tryToGetAware();
+ mInOrder.verify(mHalDeviceManager).createNanIface(mDestroyedListenerCaptor.capture(),
+ any());
+ assertEquals("Interface mismatch", mWifiNanIfaceMock, mDut.getWifiNanIface());
+
+ // 3. release (interface released)
+ mDut.releaseAware();
+ mInOrder.verify(mHalDeviceManager).removeIface(mWifiNanIfaceMock);
+ assertNull("Interface non-null!", mDut.getWifiNanIface());
+
+ mDestroyedListenerCaptor.getValue().onDestroyed("nan0");
+
+ // 4. request (interface obtained)
+ mDut.tryToGetAware();
+ mInOrder.verify(mHalDeviceManager).createNanIface(mDestroyedListenerCaptor.capture(),
+ any());
+ assertEquals("Interface mismatch", mWifiNanIfaceMock, mDut.getWifiNanIface());
+
+ // 5. request (nop - already have interface)
+ mDut.tryToGetAware();
+ assertEquals("Interface mismatch", mWifiNanIfaceMock, mDut.getWifiNanIface());
+
+ // 6. release (nop - reference counting requests)
+ mDut.releaseAware();
+ assertEquals("Interface mismatch", mWifiNanIfaceMock, mDut.getWifiNanIface());
+
+ // 7. release (interface released)
+ mDut.releaseAware();
+ mInOrder.verify(mHalDeviceManager).removeIface(mWifiNanIfaceMock);
+ assertNull("Interface non-null!", mDut.getWifiNanIface());
+
+ mDestroyedListenerCaptor.getValue().onDestroyed("nan0");
+
+ mInOrder.verify(mHalDeviceManager, never()).createNanIface(any(), any());
+ mInOrder.verify(mHalDeviceManager, never()).removeIface(any());
+ verifyNoMoreInteractions(mWifiAwareStateManagerMock);
+ }
+
+ /**
+ * Test the control flow when the interface gets deleted due to external
+ */
+ @Test
+ public void testRequestFlowWithAsyncDeletes() {
+ // configure HalDeviceManager as ready/wifi started (and to return an interface if
+ // requested)
+ when(mHalDeviceManager.isReady()).thenReturn(true);
+ when(mHalDeviceManager.isStarted()).thenReturn(true);
+ when(mHalDeviceManager.createNanIface(any(), any())).thenReturn(mWifiNanIfaceMock);
+
+ // 1. onStatusChange (ready/started)
+ mManagerStatusListenerCaptor.getValue().onStatusChanged();
+ mInOrder.verify(mHalDeviceManager).registerInterfaceAvailableForRequestListener(
+ eq(IfaceType.NAN), mAvailListenerCaptor.capture(), any(Handler.class));
+ assertNull("Interface non-null!", mDut.getWifiNanIface());
+
+ mAvailListenerCaptor.getValue().onAvailabilityChanged(true);
+ mInOrder.verify(mWifiAwareStateManagerMock).enableUsage();
+
+ // 2. request (interface obtained)
+ mDut.tryToGetAware();
+ mInOrder.verify(mHalDeviceManager).createNanIface(mDestroyedListenerCaptor.capture(),
+ any());
+ assertEquals("Interface mismatch", mWifiNanIfaceMock, mDut.getWifiNanIface());
+
+ // 3. interface gets destroyed
+ mDestroyedListenerCaptor.getValue().onDestroyed("nan0");
+
+ mInOrder.verify(mWifiAwareStateManagerMock).disableUsage();
+ assertNull("Interface non-null!", mDut.getWifiNanIface());
+
+ // 4. a release doesn't do much
+ mDut.releaseAware();
+
+ mInOrder.verify(mHalDeviceManager, never()).createNanIface(any(), any());
+ mInOrder.verify(mHalDeviceManager, never()).removeIface(any());
verifyNoMoreInteractions(mWifiAwareStateManagerMock);
}
}
diff --git a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java
index fb11789..765d868 100644
--- a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java
@@ -3069,13 +3069,16 @@
mDut.enableUsage();
mMockLooper.dispatchAll();
+ inOrder.verify(mMockNativeManager).tryToGetAware();
inOrder.verify(mMockNative).getCapabilities(transactionId.capture());
mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities());
mMockLooper.dispatchAll();
+ inOrder.verify(mMockNativeManager).releaseAware();
// (1) connect
mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false);
mMockLooper.dispatchAll();
+ inOrder.verify(mMockNativeManager).tryToGetAware();
inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
eq(configRequest), eq(false), eq(true), eq(true), eq(false));
mDut.onConfigSuccessResponse(transactionId.getValue());