diff options
7 files changed, 809 insertions, 147 deletions
diff --git a/flags/wifi_flags.aconfig b/flags/wifi_flags.aconfig index 1fb14cc8ec..304dcd0900 100644 --- a/flags/wifi_flags.aconfig +++ b/flags/wifi_flags.aconfig @@ -161,4 +161,11 @@ flag { description: "For new API added to Android V" bug: "319927407" is_fixed_read_only: true -}
\ No newline at end of file +} + +flag { + name: "d2d_usage_when_wifi_off" + namespace: "wifi" + description: "Add new API to configure d2d usage when wifi is off" + bug: "295792510" +} diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java index 9b9a456cdd..de96c660e9 100644 --- a/service/java/com/android/server/wifi/WifiInjector.java +++ b/service/java/com/android/server/wifi/WifiInjector.java @@ -355,7 +355,7 @@ public class WifiInjector { mWifiP2pMonitor = new WifiP2pMonitor(); mSupplicantP2pIfaceHal = new SupplicantP2pIfaceHal(mWifiP2pMonitor, mWifiGlobals, this); mWifiP2pNative = new WifiP2pNative(mWifiCondManager, mWifiNative, mWifiMetrics, - mWifiVendorHal, mSupplicantP2pIfaceHal, mHalDeviceManager, mPropertyService); + mWifiVendorHal, mSupplicantP2pIfaceHal, mHalDeviceManager, mPropertyService, this); SubscriptionManager subscriptionManager = mContext.getSystemService(SubscriptionManager.class); if (SdkLevel.isAtLeastS()) { diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java index bda8d1d755..575095f0e5 100644 --- a/service/java/com/android/server/wifi/WifiNative.java +++ b/service/java/com/android/server/wifi/WifiNative.java @@ -22,6 +22,8 @@ import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_AP; import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_AP_BRIDGE; import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_STA; import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_NATIVE_SUPPORTED_FEATURES; +import static com.android.server.wifi.p2p.WifiP2pNative.P2P_IFACE_NAME; +import static com.android.server.wifi.p2p.WifiP2pNative.P2P_INTERFACE_PROPERTY; import android.annotation.IntDef; import android.annotation.NonNull; @@ -348,13 +350,15 @@ public class WifiNative { /** * Meta-info about every iface that is active. */ - private static class Iface { + public static class Iface { /** Type of ifaces possible */ public static final int IFACE_TYPE_AP = 0; public static final int IFACE_TYPE_STA_FOR_CONNECTIVITY = 1; public static final int IFACE_TYPE_STA_FOR_SCAN = 2; + public static final int IFACE_TYPE_P2P = 3; - @IntDef({IFACE_TYPE_AP, IFACE_TYPE_STA_FOR_CONNECTIVITY, IFACE_TYPE_STA_FOR_SCAN}) + @IntDef({IFACE_TYPE_AP, IFACE_TYPE_STA_FOR_CONNECTIVITY, IFACE_TYPE_STA_FOR_SCAN, + IFACE_TYPE_P2P}) @Retention(RetentionPolicy.SOURCE) public @interface IfaceType{} @@ -478,6 +482,11 @@ public class WifiNative { return false; } + /** Checks if there are any P2P iface active. */ + private boolean hasAnyP2pIface() { + return hasAnyIfaceOfType(Iface.IFACE_TYPE_P2P); + } + /** Checks if there are any STA (for connectivity) iface active. */ private boolean hasAnyStaIfaceForConnectivity() { return hasAnyIfaceOfType(Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY); @@ -701,10 +710,19 @@ public class WifiNative { private void stopSupplicantIfNecessary() { synchronized (mLock) { if (!mIfaceMgr.hasAnyStaIfaceForConnectivity()) { - if (!mSupplicantStaIfaceHal.deregisterDeathHandler()) { - Log.e(TAG, "Failed to deregister supplicant death handler"); + if (mSupplicantStaIfaceHal.isInitializationStarted()) { + if (!mSupplicantStaIfaceHal.deregisterDeathHandler()) { + Log.e(TAG, "Failed to deregister supplicant death handler"); + } + + } + if (!mIfaceMgr.hasAnyP2pIface()) { + if (mSupplicantStaIfaceHal.isInitializationStarted()) { + mSupplicantStaIfaceHal.terminate(); + } else { + mWifiInjector.getWifiP2pNative().stopP2pSupplicantIfNecessary(); + } } - mSupplicantStaIfaceHal.terminate(); } } } @@ -1197,6 +1215,68 @@ public class WifiNative { } } + private String createP2pIfaceFromHalOrGetNameFromProperty( + HalDeviceManager.InterfaceDestroyedListener p2pInterfaceDestroyedListener, + Handler handler, WorkSource requestorWs) { + synchronized (mLock) { + if (mWifiVendorHal.isVendorHalSupported()) { + return mWifiInjector.getHalDeviceManager().createP2pIface( + p2pInterfaceDestroyedListener, handler, requestorWs); + } else { + Log.i(TAG, "Vendor Hal not supported, ignoring createStaIface."); + return mPropertyService.getString(P2P_INTERFACE_PROPERTY, P2P_IFACE_NAME); + } + } + } + + /** + * Helper function to handle creation of P2P iface. + * For devices which do not the support the HAL, this will bypass HalDeviceManager & + * teardown any existing iface. + */ + public Iface createP2pIface( + HalDeviceManager.InterfaceDestroyedListener p2pInterfaceDestroyedListener, + Handler handler, WorkSource requestorWs) { + synchronized (mLock) { + // Make sure HAL is started for p2p + if (!startHal()) { + Log.e(TAG, "Failed to start Hal"); + mWifiMetrics.incrementNumSetupP2pInterfaceFailureDueToHal(); + return null; + } + // maintain iface status in WifiNative + Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_P2P); + if (iface == null) { + Log.e(TAG, "Failed to allocate new P2P iface"); + stopHalAndWificondIfNecessary(); + return null; + } + iface.name = createP2pIfaceFromHalOrGetNameFromProperty( + p2pInterfaceDestroyedListener, handler, requestorWs); + if (TextUtils.isEmpty(iface.name)) { + Log.e(TAG, "Failed to create P2p iface in HalDeviceManager"); + mIfaceMgr.removeIface(iface.id); + mWifiMetrics.incrementNumSetupP2pInterfaceFailureDueToHal(); + stopHalAndWificondIfNecessary(); + return null; + } + return iface; + } + } + + /** + * Teardown P2p iface with input interface Id which was returned by createP2pIface. + * + * @param interfaceId the interface identify which was gerenated when creating P2p iface. + */ + public void teardownP2pIface(int interfaceId) { + synchronized (mLock) { + mIfaceMgr.removeIface(interfaceId); + stopHalAndWificondIfNecessary(); + stopSupplicantIfNecessary(); + } + } + /** * Get list of instance name from this bridged AP iface. * @@ -5002,30 +5082,36 @@ public class WifiNative { return mHostapdHal.isSoftApInstanceDiedHandlerSupported(); } - @VisibleForTesting /** Checks if there are any STA (for connectivity) iface active. */ + @VisibleForTesting boolean hasAnyStaIfaceForConnectivity() { return mIfaceMgr.hasAnyStaIfaceForConnectivity(); } - @VisibleForTesting /** Checks if there are any STA (for scan) iface active. */ + @VisibleForTesting boolean hasAnyStaIfaceForScan() { return mIfaceMgr.hasAnyStaIfaceForScan(); } - @VisibleForTesting /** Checks if there are any AP iface active. */ + @VisibleForTesting boolean hasAnyApIface() { return mIfaceMgr.hasAnyApIface(); } - @VisibleForTesting /** Checks if there are any iface active. */ + @VisibleForTesting boolean hasAnyIface() { return mIfaceMgr.hasAnyIface(); } + /** Checks if there are any P2P iface active. */ + @VisibleForTesting + boolean hasAnyP2pIface() { + return mIfaceMgr.hasAnyP2pIface(); + } + /** * Sets or clean mock wifi service * diff --git a/service/java/com/android/server/wifi/p2p/WifiP2pNative.java b/service/java/com/android/server/wifi/p2p/WifiP2pNative.java index c85dd7ffdf..5ee116a4af 100644 --- a/service/java/com/android/server/wifi/p2p/WifiP2pNative.java +++ b/service/java/com/android/server/wifi/p2p/WifiP2pNative.java @@ -37,9 +37,11 @@ import android.util.Log; import com.android.server.wifi.HalDeviceManager; import com.android.server.wifi.PropertyService; +import com.android.server.wifi.WifiInjector; import com.android.server.wifi.WifiMetrics; import com.android.server.wifi.WifiNative; import com.android.server.wifi.WifiVendorHal; +import com.android.wifi.flags.FeatureFlags; import java.util.HashSet; import java.util.List; @@ -59,9 +61,26 @@ public class WifiP2pNative { private final HalDeviceManager mHalDeviceManager; private final PropertyService mPropertyService; private final WifiVendorHal mWifiVendorHal; + private final WifiInjector mWifiInjector; + private final FeatureFlags mFeatureFlags; + private final Object mLock = new Object(); + private WifiNative.Iface mP2pIface; private String mP2pIfaceName; private InterfaceDestroyedListenerInternal mInterfaceDestroyedListener; + /** + * Death handler for the supplicant daemon. + */ + private class SupplicantDeathHandlerInternal implements WifiNative.SupplicantDeathEventHandler { + @Override + public void onDeath() { + if (mP2pIface != null) { + Log.i(TAG, "wpa_supplicant died. Cleaning up internal state."); + mInterfaceDestroyedListener.teardownAndInvalidate(mP2pIface.name); + mWifiMetrics.incrementNumSupplicantCrashes(); + } + } + } // Internal callback registered to HalDeviceManager. private class InterfaceDestroyedListenerInternal implements @@ -76,22 +95,35 @@ public class WifiP2pNative { } public void teardownAndInvalidate(@Nullable String ifaceName) { - if (!TextUtils.isEmpty(ifaceName)) { - mSupplicantP2pIfaceHal.teardownIface(ifaceName); + synchronized (mLock) { + if (mFeatureFlags.d2dUsageWhenWifiOff() + && !mSupplicantP2pIfaceHal.deregisterDeathHandler()) { + Log.i(TAG, "Failed to deregister p2p supplicant death handler"); + } + if (!TextUtils.isEmpty(ifaceName)) { + mSupplicantP2pIfaceHal.teardownIface(ifaceName); + if (mP2pIface != null) { + mWifiNative.teardownP2pIface(mP2pIface.id); + } + } + mP2pIfaceName = null; + mP2pIface = null; + mValid = false; + Log.i(TAG, "teardownAndInvalidate is completed"); } - mP2pIfaceName = null; - mValid = false; } @Override public void onDestroyed(String ifaceName) { - Log.d(TAG, "P2P InterfaceDestroyedListener " + ifaceName); - if (!mValid) { - Log.d(TAG, "Ignoring stale interface destroyed listener"); - return; + synchronized (mLock) { + Log.d(TAG, "P2P InterfaceDestroyedListener " + ifaceName); + if (!mValid) { + Log.d(TAG, "Ignoring stale interface destroyed listener"); + return; + } + teardownAndInvalidate(ifaceName); + mExternalListener.onDestroyed(ifaceName); } - teardownAndInvalidate(ifaceName); - mExternalListener.onDestroyed(ifaceName); } } @@ -102,7 +134,8 @@ public class WifiP2pNative { WifiVendorHal wifiVendorHal, SupplicantP2pIfaceHal p2pIfaceHal, HalDeviceManager halDeviceManager, - PropertyService propertyService) { + PropertyService propertyService, + WifiInjector wifiInjector) { mWifiNative = wifiNative; mWifiMetrics = wifiMetrics; mWifiNl80211Manager = wifiNl80211Manager; @@ -110,6 +143,8 @@ public class WifiP2pNative { mSupplicantP2pIfaceHal = p2pIfaceHal; mHalDeviceManager = halDeviceManager; mPropertyService = propertyService; + mWifiInjector = wifiInjector; + mFeatureFlags = wifiInjector.getDeviceConfigFacade().getFeatureFlags(); } /** @@ -150,8 +185,11 @@ public class WifiP2pNative { /** * Close supplicant connection. */ - public void closeSupplicantConnection() { - // Nothing to do for HAL. + public void stopP2pSupplicantIfNecessary() { + if (mFeatureFlags.d2dUsageWhenWifiOff() + && mSupplicantP2pIfaceHal.isInitializationStarted()) { + mSupplicantP2pIfaceHal.terminate(); + } } /** @@ -161,8 +199,8 @@ public class WifiP2pNative { return mHalDeviceManager.isSupported(); } - private static final String P2P_IFACE_NAME = "p2p0"; - private static final String P2P_INTERFACE_PROPERTY = "wifi.direct.interface"; + public static final String P2P_IFACE_NAME = "p2p0"; + public static final String P2P_INTERFACE_PROPERTY = "wifi.direct.interface"; /** * Helper function to handle creation of P2P iface. @@ -194,39 +232,58 @@ public class WifiP2pNative { public String setupInterface( @Nullable HalDeviceManager.InterfaceDestroyedListener destroyedListener, @NonNull Handler handler, @NonNull WorkSource requestorWs) { - Log.d(TAG, "Setup P2P interface"); - if (mP2pIfaceName == null) { - mInterfaceDestroyedListener = (null == destroyedListener) - ? null - : new InterfaceDestroyedListenerInternal(destroyedListener); - String ifaceName = createP2pIface(handler, requestorWs); - if (ifaceName == null) { - Log.e(TAG, "Failed to create P2p iface"); - if (mHalDeviceManager.isItPossibleToCreateIface(HDM_CREATE_IFACE_P2P, - requestorWs)) { - mWifiMetrics.incrementNumSetupP2pInterfaceFailureDueToHal(); + synchronized (mLock) { + Log.d(TAG, "Setup P2P interface"); + if (mP2pIfaceName == null) { + mInterfaceDestroyedListener = (null == destroyedListener) + ? null + : new InterfaceDestroyedListenerInternal(destroyedListener); + if (mFeatureFlags.d2dUsageWhenWifiOff()) { + mP2pIface = mWifiNative.createP2pIface(mInterfaceDestroyedListener, handler, + requestorWs); + if (mP2pIface != null) { + mP2pIfaceName = mP2pIface.name; + } + } else { + mP2pIfaceName = createP2pIface(handler, requestorWs); } - return null; - } - if (!waitForSupplicantConnection()) { - Log.e(TAG, "Failed to connect to supplicant"); - teardownInterface(); - mWifiMetrics.incrementNumSetupP2pInterfaceFailureDueToSupplicant(); - return null; - } - if (!mSupplicantP2pIfaceHal.setupIface(ifaceName)) { - Log.e(TAG, "Failed to setup P2p iface in supplicant"); - teardownInterface(); - mWifiMetrics.incrementNumSetupP2pInterfaceFailureDueToSupplicant(); - return null; + if (mP2pIfaceName == null) { + Log.e(TAG, "Failed to create P2p iface"); + if (mHalDeviceManager.isItPossibleToCreateIface(HDM_CREATE_IFACE_P2P, + requestorWs)) { + mWifiMetrics.incrementNumSetupP2pInterfaceFailureDueToHal(); + } + return null; + } + if (!waitForSupplicantConnection()) { + Log.e(TAG, "Failed to connect to supplicant"); + teardownInterface(); + mWifiMetrics.incrementNumSetupP2pInterfaceFailureDueToSupplicant(); + return null; + } + if (!mSupplicantP2pIfaceHal.setupIface(mP2pIfaceName)) { + Log.e(TAG, "Failed to setup P2p iface in supplicant"); + teardownInterface(); + mWifiMetrics.incrementNumSetupP2pInterfaceFailureDueToSupplicant(); + return null; + } + if (mFeatureFlags.d2dUsageWhenWifiOff() + && !mSupplicantP2pIfaceHal.registerDeathHandler( + new SupplicantDeathHandlerInternal())) { + Log.e(TAG, "Failed to register supplicant death handler" + + "(because hidl supplicant?)"); + teardownInterface(); + mWifiMetrics.incrementNumSetupP2pInterfaceFailureDueToSupplicant(); + return null; + } + Log.i(TAG, "P2P interface setup completed"); + return mP2pIfaceName; + } else { + Log.i(TAG, "P2P interface already exists"); + return mHalDeviceManager.isSupported() + ? mP2pIfaceName + : mPropertyService.getString(P2P_INTERFACE_PROPERTY, P2P_IFACE_NAME); } - Log.i(TAG, "P2P interface setup completed"); - return ifaceName; - } else { - Log.i(TAG, "P2P interface already exists"); - return mHalDeviceManager.isSupported() - ? mP2pIfaceName - : mPropertyService.getString(P2P_INTERFACE_PROPERTY, P2P_IFACE_NAME); } } @@ -234,20 +291,25 @@ public class WifiP2pNative { * Teardown P2p interface. */ public void teardownInterface() { - Log.d(TAG, "Teardown P2P interface"); - if (mHalDeviceManager.isSupported()) { - if (mP2pIfaceName != null) { - mHalDeviceManager.removeP2pIface(mP2pIfaceName); + synchronized (mLock) { + Log.d(TAG, "Teardown P2P interface:" + mP2pIfaceName); + if (mHalDeviceManager.isSupported()) { + if (mP2pIfaceName != null) { + mHalDeviceManager.removeP2pIface(mP2pIfaceName); + Log.i(TAG, "P2P interface teardown completed"); + if (!mFeatureFlags.d2dUsageWhenWifiOff()) { + if (null != mInterfaceDestroyedListener) { + mInterfaceDestroyedListener.teardownAndInvalidate(mP2pIfaceName); + } + } + } + } else { + Log.i(TAG, "HAL is not supported. Destroy listener for the interface."); + String ifaceName = mPropertyService.getString(P2P_INTERFACE_PROPERTY, + P2P_IFACE_NAME); if (null != mInterfaceDestroyedListener) { - mInterfaceDestroyedListener.teardownAndInvalidate(mP2pIfaceName); + mInterfaceDestroyedListener.teardownAndInvalidate(ifaceName); } - Log.i(TAG, "P2P interface teardown completed"); - } - } else { - Log.i(TAG, "HAL is not supported. Destroy listener for the interface."); - String ifaceName = mPropertyService.getString(P2P_INTERFACE_PROPERTY, P2P_IFACE_NAME); - if (null != mInterfaceDestroyedListener) { - mInterfaceDestroyedListener.teardownAndInvalidate(ifaceName); } } } @@ -256,12 +318,14 @@ public class WifiP2pNative { * Replace requestorWs in-place when iface is already enabled. */ public boolean replaceRequestorWs(WorkSource requestorWs) { - if (mHalDeviceManager.isSupported()) { - if (mP2pIfaceName == null) return false; - return mHalDeviceManager.replaceRequestorWsForP2pIface(mP2pIfaceName, requestorWs); - } else { - Log.i(TAG, "HAL is not supported. Ignore replace requestorWs"); - return true; + synchronized (mLock) { + if (mHalDeviceManager.isSupported()) { + if (mP2pIfaceName == null) return false; + return mHalDeviceManager.replaceRequestorWsForP2pIface(mP2pIfaceName, requestorWs); + } else { + Log.i(TAG, "HAL is not supported. Ignore replace requestorWs"); + return true; + } } } @@ -936,9 +1000,11 @@ public class WifiP2pNative { /** Indicate whether or not 5GHz/6GHz DBS is supported. */ public boolean is5g6gDbsSupported() { - if (mP2pIfaceName == null) return false; - if (!mHalDeviceManager.isSupported()) return false; - return mHalDeviceManager.is5g6gDbsSupportedOnP2pIface(mP2pIfaceName); + synchronized (mLock) { + if (mP2pIfaceName == null) return false; + if (!mHalDeviceManager.isSupported()) return false; + return mHalDeviceManager.is5g6gDbsSupportedOnP2pIface(mP2pIfaceName); + } } /** diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiNativeInterfaceManagementTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiNativeInterfaceManagementTest.java index 92a111fea7..b17651aa5b 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiNativeInterfaceManagementTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiNativeInterfaceManagementTest.java @@ -16,8 +16,12 @@ package com.android.server.wifi; +import static com.android.server.wifi.p2p.WifiP2pNative.P2P_IFACE_NAME; +import static com.android.server.wifi.p2p.WifiP2pNative.P2P_INTERFACE_PROPERTY; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; @@ -53,6 +57,7 @@ import com.android.modules.utils.build.SdkLevel; 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.p2p.WifiP2pNative; import com.android.server.wifi.util.NetdWrapper; import com.android.server.wifi.util.NetdWrapper.NetdEventObserver; import com.android.wifi.resources.R; @@ -88,6 +93,7 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { private static final int SOFTAP_FAILURE_CODE_START_DAEMON = 2; private static final int SOFTAP_FAILURE_CODE_CREATE_IFACE = 3; private static final int SOFTAP_FAILURE_CODE_BRIDGED_AP_INSTANCES = 4; + private static final int P2P_FAILURE_CODE_CREATE_INTERFACE = 1; private static final int TEST_SUPPORTED_BANDS = 15; MockResources mResources; @@ -103,11 +109,15 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { @Mock BuildProperties mBuildProperties; @Mock private WifiInjector mWifiInjector; @Mock private WifiContext mContext; + @Mock private HalDeviceManager mHalDeviceManager; + @Mock private WifiP2pNative mWifiP2pNative; @Mock private WifiNative.StatusListener mStatusListener; @Mock private WifiNative.InterfaceCallback mIfaceCallback0; @Mock private WifiNative.InterfaceCallback mIfaceCallback1; @Mock private WifiNative.InterfaceEventCallback mIfaceEventCallback0; + @Mock private HalDeviceManager.InterfaceDestroyedListener mP2pInterfaceDestroyedListener; + @Mock private Handler mP2pEventHandler; @Mock private WifiSettingsConfigStore mWifiSettingsConfigStore; @Mock private WifiGlobals mWifiGlobals; @@ -116,6 +126,7 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { @Mock DeviceConfigFacade mDeviceConfigFacade; private TestLooper mLooper; + private WifiNative.Iface mActiveP2pIface; private ArgumentCaptor<VendorHalDeathEventHandler> mWifiVendorHalDeathHandlerCaptor = ArgumentCaptor.forClass(VendorHalDeathEventHandler.class); @@ -206,6 +217,8 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { when(mWifiInjector.getSettingsConfigStore()).thenReturn(mWifiSettingsConfigStore); when(mWifiInjector.getContext()).thenReturn(mContext); when(mWifiInjector.getWifiGlobals()).thenReturn(mWifiGlobals); + when(mWifiInjector.getHalDeviceManager()).thenReturn(mHalDeviceManager); + when(mWifiInjector.getWifiP2pNative()).thenReturn(mWifiP2pNative); mResources = getMockResources(); mResources.setBoolean(R.bool.config_wifiNetworkCentricQosPolicyFeatureEnabled, false); mResources.setString( @@ -223,7 +236,7 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { mInOrder = inOrder(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal, mHostapdHal, mWifiMonitor, mNetdWrapper, mIfaceCallback0, mIfaceCallback1, mIfaceEventCallback0, - mWifiMetrics); + mWifiMetrics, mWifiP2pNative); mWifiNative = new WifiNative( mWifiVendorHal, mSupplicantStaIfaceHal, mHostapdHal, mWificondControl, @@ -237,6 +250,7 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { mWificondDeathHandlerCaptor.capture()); mInOrder.verify(mWificondControl).tearDownInterfaces(); mInOrder.verify(mWifiVendorHal).registerRadioModeChangeHandler(any()); + mActiveP2pIface = null; } @After @@ -493,6 +507,7 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { verify(mNetdWrapper).unregisterObserver(mNetworkObserverCaptor1.getValue()); verify(mSupplicantStaIfaceHal).teardownIface(IFACE_NAME_1); verify(mWificondControl).tearDownClientInterface(IFACE_NAME_1); + verify(mSupplicantStaIfaceHal, atLeastOnce()).isInitializationStarted(); verify(mSupplicantStaIfaceHal).deregisterDeathHandler(); verify(mSupplicantStaIfaceHal).terminate(); verify(mIfaceCallback1).onDestroyed(IFACE_NAME_1); @@ -557,7 +572,9 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); mInOrder.verify(mWifiVendorHal).replaceStaIfaceRequestorWs(ifaceName, workSource); mInOrder.verify(mSupplicantStaIfaceHal).teardownIface(ifaceName); + mInOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted(); mInOrder.verify(mSupplicantStaIfaceHal).deregisterDeathHandler(); + mInOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted(); mInOrder.verify(mSupplicantStaIfaceHal).terminate(); mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedCapabilities(ifaceName); mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(ifaceName); @@ -1340,6 +1357,7 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { } mInOrder.verify(mSupplicantStaIfaceHal).isInitializationComplete(); mInOrder.verify(mSupplicantStaIfaceHal).registerDeathHandler(any()); + when(mSupplicantStaIfaceHal.isInitializationStarted()).thenReturn(true); } mInOrder.verify(mSupplicantStaIfaceHal).setupIface(ifaceName); if (failureCode == STA_FAILURE_CODE_SETUP_INTERFACE) { @@ -1395,6 +1413,88 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { assertEquals(Set.of(IFACE_NAME_0, IFACE_NAME_1), mWifiNative.getClientInterfaceNames()); } + @Test + public void testSetupP2pInterfaceAndTeardownP2p() throws Exception { + executeAndValidateCreateP2pInterface(false, false, false, P2P_IFACE_NAME, true, 0); + executeAndValidateTeardownP2pInterface(false, false, false, false, false, + mActiveP2pIface, true); + } + + @Test + public void testSetupP2pInterfaceAndTeardownP2pWhenClientInterfaceExist() throws Exception { + // Start client interface + executeAndValidateSetupClientInterface( + false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, + mNetworkObserverCaptor0); + assertEquals(Set.of(IFACE_NAME_0), mWifiNative.getClientInterfaceNames()); + executeAndValidateCreateP2pInterface(true, false, false, P2P_IFACE_NAME, true, 0); + assertTrue(mWifiNative.hasAnyP2pIface()); + executeAndValidateTeardownP2pInterface(true, true, true, false, false, + mActiveP2pIface, true); + assertFalse(mWifiNative.hasAnyP2pIface()); + verify(mWifiVendorHal, never()).stopVendorHal(); + } + + /** + * Verifies the setup of a single client interface and teardown by P2P on. + */ + @Test + public void testSetupClientInterfaceAndTeardownP2p() throws Exception { + executeAndValidateCreateP2pInterface(false, false, false, P2P_IFACE_NAME, true, 0); + // Trigger the P2P interface teardown when STA interface is created. + // The iface name will remain the same. + doAnswer(new MockAnswerUtil.AnswerWithArguments() { + public String answer(InterfaceDestroyedListener destroyedListener, WorkSource ws, + ConcreteClientModeManager concreteClientModeManager) { + mWifiNative.teardownP2pIface(mActiveP2pIface.id); + return IFACE_NAME_0; + } + }).when(mWifiVendorHal).createStaIface(any(), any(), eq(mConcreteClientModeManager)); + + assertEquals(IFACE_NAME_0, + mWifiNative.setupInterfaceForClientInScanMode(mIfaceCallback0, TEST_WORKSOURCE, + mConcreteClientModeManager)); + assertEquals(Set.of(IFACE_NAME_0), mWifiNative.getClientInterfaceNames()); + validateSetupClientInterfaceForScan( + false, false, true, IFACE_NAME_0, mIfaceDestroyedListenerCaptor0, + mNetworkObserverCaptor0, true, 0); + verify(mSupplicantStaIfaceHal, atLeastOnce()).isInitializationStarted(); + verify(mWifiVendorHal, never()).stopVendorHal(); + verify(mWifiP2pNative).stopP2pSupplicantIfNecessary(); + } + + /** + * Verifies the setup of a single client interface (for scan) and teardown by P2P on. + */ + @Test + public void testCreateP2pIfaceAndTeardownClientIface() throws Exception { + executeAndValidateSetupClientInterface( + false, false, IFACE_NAME_0, mIfaceCallback0, mIfaceDestroyedListenerCaptor0, + mNetworkObserverCaptor0); + assertEquals(Set.of(IFACE_NAME_0), mWifiNative.getClientInterfaceNames()); + // Trigger the STA interface teardown when P2p interface is created. + // The iface name will remain the same. + doAnswer(new MockAnswerUtil.AnswerWithArguments() { + public String answer( + HalDeviceManager.InterfaceDestroyedListener p2pInterfaceDestroyedListener, + Handler handler, WorkSource requestorWs) { + mIfaceDestroyedListenerCaptor0.getValue().onDestroyed(IFACE_NAME_0); + return P2P_IFACE_NAME; + } + }).when(mHalDeviceManager).createP2pIface(any(), any(), any()); + mActiveP2pIface = mWifiNative.createP2pIface(mP2pInterfaceDestroyedListener, + mP2pEventHandler, TEST_WORKSOURCE); + assertEquals(P2P_IFACE_NAME, mActiveP2pIface.name); + // Creation of P2P interface should trigger the STA interface destroy + verify(mWifiVendorHal, atLeastOnce()).isVendorHalSupported(); + verify(mWifiVendorHal, atLeastOnce()).isVendorHalReady(); + validateOnDestroyedClientInterface(false, false, true, + IFACE_NAME_0, mIfaceCallback0, mNetworkObserverCaptor0.getValue()); + validateCreateP2pInterface(true, false, false, P2P_IFACE_NAME, true, 0); + executeAndValidateTeardownP2pInterface(false, false, false, false, false, + mActiveP2pIface, true); + } + private void executeAndValidateSetupClientInterface( boolean hasStaIface, boolean hasApIface, String ifaceName, @Mock WifiNative.InterfaceCallback callback, @@ -1411,10 +1511,21 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor, ArgumentCaptor<NetdEventObserver> networkObserverCaptor, boolean vendorHalSupported, int failureCode) throws Exception { + executeAndValidateSetupClientInterface(hasStaIface, hasApIface, false, ifaceName, callback, + destroyedListenerCaptor, + networkObserverCaptor, vendorHalSupported, failureCode); + } + + private void executeAndValidateSetupClientInterface( + boolean hasStaIface, boolean hasApIface, boolean hasP2pIface, + String ifaceName, @Mock WifiNative.InterfaceCallback callback, + ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor, + ArgumentCaptor<NetdEventObserver> networkObserverCaptor, boolean vendorHalSupported, + int failureCode) throws Exception { when(mWifiVendorHal.createStaIface(any(), any(), eq(mConcreteClientModeManager))) .thenReturn(ifaceName); executeAndValidateSetupClientInterfaceForScan( - hasStaIface, hasApIface, ifaceName, callback, destroyedListenerCaptor, + hasStaIface, hasApIface, hasP2pIface, ifaceName, callback, destroyedListenerCaptor, networkObserverCaptor, vendorHalSupported, failureCode); executeAndValidateSwitchClientInterfaceToConnectivityMode(hasStaIface, hasApIface, ifaceName, TEST_WORKSOURCE, vendorHalSupported, failureCode); @@ -1425,6 +1536,16 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { String ifaceName, @Mock WifiNative.InterfaceCallback callback, InterfaceDestroyedListener destroyedListener, NetdEventObserver networkObserver) throws Exception { + executeAndValidateTeardownClientInterface(anyOtherStaIface, anyOtherApIface, + false /* anyOtherP2pIface */, ifaceName, callback, destroyedListener, + networkObserver); + } + + private void executeAndValidateTeardownClientInterface( + boolean anyOtherStaIface, boolean anyOtherApIface, boolean anyOtherP2pIface, + String ifaceName, @Mock WifiNative.InterfaceCallback callback, + InterfaceDestroyedListener destroyedListener, + NetdEventObserver networkObserver) throws Exception { mWifiNative.teardownInterface(ifaceName); mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); @@ -1434,13 +1555,23 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { destroyedListener.onDestroyed(ifaceName); validateOnDestroyedClientInterface( - anyOtherStaIface, anyOtherApIface, ifaceName, callback, networkObserver); + anyOtherStaIface, anyOtherApIface, anyOtherP2pIface, + ifaceName, callback, networkObserver); } private void validateOnDestroyedClientInterface( boolean anyOtherStaIface, boolean anyOtherApIface, String ifaceName, @Mock WifiNative.InterfaceCallback callback, NetdEventObserver networkObserver) throws Exception { + validateOnDestroyedClientInterface( + anyOtherStaIface, anyOtherApIface, false /* anyOtherP2pIface */, + ifaceName, callback, networkObserver); + } + + private void validateOnDestroyedClientInterface( + boolean anyOtherStaIface, boolean anyOtherApIface, boolean anyOtherP2pIface, + String ifaceName, @Mock WifiNative.InterfaceCallback callback, + NetdEventObserver networkObserver) throws Exception { mInOrder.verify(mWifiMonitor).stopMonitoring(ifaceName); if (networkObserver != null) { mInOrder.verify(mNetdWrapper).unregisterObserver(networkObserver); @@ -1449,10 +1580,15 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { mInOrder.verify(mWificondControl).tearDownClientInterface(ifaceName); if (!anyOtherStaIface) { + mInOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted(); mInOrder.verify(mSupplicantStaIfaceHal).deregisterDeathHandler(); - mInOrder.verify(mSupplicantStaIfaceHal).terminate(); + if (!anyOtherP2pIface) { + mInOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted(); + mInOrder.verify(mSupplicantStaIfaceHal).terminate(); + } + when(mSupplicantStaIfaceHal.isInitializationStarted()).thenReturn(false); } - if (!anyOtherStaIface && !anyOtherApIface) { + if (!anyOtherStaIface && !anyOtherApIface && !anyOtherP2pIface) { mInOrder.verify(mWificondControl).tearDownInterfaces(); mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); mInOrder.verify(mWifiVendorHal).stopVendorHal(); @@ -1476,6 +1612,17 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor, ArgumentCaptor<NetdEventObserver> networkObserverCaptor, boolean vendorHalSupported, int failureCode) throws Exception { + executeAndValidateSetupClientInterfaceForScan(hasStaIface, hasApIface, + false /* hasP2pIface */, ifaceName, callback, + destroyedListenerCaptor, networkObserverCaptor, vendorHalSupported, failureCode); + } + + private void executeAndValidateSetupClientInterfaceForScan( + boolean hasStaIface, boolean hasApIface, boolean hasP2pIface, + String ifaceName, @Mock WifiNative.InterfaceCallback callback, + ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor, + ArgumentCaptor<NetdEventObserver> networkObserverCaptor, + boolean vendorHalSupported, int failureCode) throws Exception { if (failureCode != STA_FAILURE_CODE_CREAT_IFACE) { when(mWifiVendorHal.createStaIface(any(), any(), eq(mConcreteClientModeManager))) .thenReturn(ifaceName); @@ -1485,7 +1632,7 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { mConcreteClientModeManager)); validateSetupClientInterfaceForScan( - hasStaIface, hasApIface, ifaceName, destroyedListenerCaptor, + hasStaIface, hasApIface, hasP2pIface, ifaceName, destroyedListenerCaptor, networkObserverCaptor, vendorHalSupported, failureCode); } @@ -1510,7 +1657,17 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { String ifaceName, ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor, ArgumentCaptor<NetdEventObserver> networkObserverCaptor, boolean vendorHalSupported, int failureCode) throws Exception { - validateStartHal(hasStaIface || hasApIface, vendorHalSupported); + validateSetupClientInterfaceForScan(hasStaIface, hasApIface, false /* hasP2pIfacd */, + ifaceName, destroyedListenerCaptor, networkObserverCaptor, vendorHalSupported, + failureCode); + } + + private void validateSetupClientInterfaceForScan( + boolean hasStaIface, boolean hasApIface, boolean hasP2pIface, + String ifaceName, ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor, + ArgumentCaptor<NetdEventObserver> networkObserverCaptor, boolean vendorHalSupported, + int failureCode) throws Exception { + validateStartHal(hasStaIface || hasApIface || hasP2pIface, vendorHalSupported); if (vendorHalSupported) { mInOrder.verify(mWifiVendorHal).createStaIface( destroyedListenerCaptor.capture(), eq(TEST_WORKSOURCE), @@ -1557,6 +1714,16 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { String ifaceName, @Mock WifiNative.InterfaceCallback callback, InterfaceDestroyedListener destroyedListener, NetdEventObserver networkObserver) throws Exception { + executeAndValidateTeardownClientInterfaceForScan(anyOtherStaIface, anyOtherApIface, + false /* anyOtherP2pIface */, ifaceName, callback, destroyedListener, + networkObserver); + } + + private void executeAndValidateTeardownClientInterfaceForScan( + boolean anyOtherStaIface, boolean anyOtherApIface, boolean anyOtherP2pIface, + String ifaceName, @Mock WifiNative.InterfaceCallback callback, + InterfaceDestroyedListener destroyedListener, + NetdEventObserver networkObserver) throws Exception { mWifiNative.teardownInterface(ifaceName); mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); @@ -1566,20 +1733,30 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { destroyedListener.onDestroyed(ifaceName); validateOnDestroyedClientInterfaceForScan( - anyOtherStaIface, anyOtherApIface, ifaceName, callback, networkObserver); + anyOtherStaIface, anyOtherApIface, anyOtherP2pIface, + ifaceName, callback, networkObserver); } private void validateOnDestroyedClientInterfaceForScan( boolean anyOtherStaIface, boolean anyOtherApIface, String ifaceName, @Mock WifiNative.InterfaceCallback callback, NetdEventObserver networkObserver) throws Exception { + validateOnDestroyedClientInterfaceForScan( + anyOtherStaIface, anyOtherApIface, false /* anyOtherP2pIface */, + ifaceName, callback, networkObserver); + } + + private void validateOnDestroyedClientInterfaceForScan( + boolean anyOtherStaIface, boolean anyOtherApIface, boolean anyOtherP2pIface, + String ifaceName, @Mock WifiNative.InterfaceCallback callback, + NetdEventObserver networkObserver) throws Exception { mInOrder.verify(mWifiMonitor).stopMonitoring(ifaceName); if (networkObserver != null) { mInOrder.verify(mNetdWrapper).unregisterObserver(networkObserver); } mInOrder.verify(mWificondControl).tearDownClientInterface(ifaceName); - if (!anyOtherStaIface && !anyOtherApIface) { + if (!anyOtherStaIface && !anyOtherApIface && !anyOtherP2pIface) { mInOrder.verify(mWificondControl).tearDownInterfaces(); mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); mInOrder.verify(mWifiVendorHal).stopVendorHal(); @@ -1603,6 +1780,17 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor, ArgumentCaptor<NetdEventObserver> networkObserverCaptor, boolean isBridged, boolean vendorHalSupported, int failureCode) throws Exception { + executeAndValidateSetupSoftApInterface(hasStaIface, hasApIface, false /* hasP2pIface */, + ifaceName, callback, destroyedListenerCaptor, networkObserverCaptor, + isBridged, vendorHalSupported, failureCode); + } + + private void executeAndValidateSetupSoftApInterface( + boolean hasStaIface, boolean hasApIface, boolean hasP2pIface, + String ifaceName, @Mock WifiNative.InterfaceCallback callback, + ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor, + ArgumentCaptor<NetdEventObserver> networkObserverCaptor, boolean isBridged, + boolean vendorHalSupported, int failureCode) throws Exception { when(mWifiVendorHal.createApIface(any(), any(), anyInt(), eq(isBridged), any(), anyList())) .thenReturn(ifaceName); assertEquals(failureCode == 0 ? ifaceName : null, mWifiNative.setupInterfaceForSoftApMode( @@ -1619,7 +1807,17 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { String ifaceName, ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor, ArgumentCaptor<NetdEventObserver> networkObserverCaptor, boolean isBridged, boolean vendorHalSupported, int failureCode) throws Exception { - validateStartHal(hasStaIface || hasApIface, vendorHalSupported); + validateSetupSoftApInterface(hasStaIface, hasApIface, false /* hasP2pIface */, + ifaceName, destroyedListenerCaptor, + networkObserverCaptor, isBridged, vendorHalSupported, failureCode); + } + + private void validateSetupSoftApInterface( + boolean hasStaIface, boolean hasApIface, boolean hasP2pIface, + String ifaceName, ArgumentCaptor<InterfaceDestroyedListener> destroyedListenerCaptor, + ArgumentCaptor<NetdEventObserver> networkObserverCaptor, boolean isBridged, + boolean vendorHalSupported, int failureCode) throws Exception { + validateStartHal(hasStaIface || hasApIface || hasP2pIface, vendorHalSupported); if (!hasApIface) { mInOrder.verify(mHostapdHal).isInitializationStarted(); mInOrder.verify(mHostapdHal).initialize(); @@ -1651,8 +1849,11 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { } mInOrder.verify(mWificondControl).tearDownClientInterface(ifaceName); if (mWifiNative.hasAnyStaIfaceForConnectivity()) { + mInOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted(); mInOrder.verify(mSupplicantStaIfaceHal).deregisterDeathHandler(); + mInOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted(); mInOrder.verify(mSupplicantStaIfaceHal).terminate(); + when(mSupplicantStaIfaceHal.isInitializationStarted()).thenReturn(false); } mInOrder.verify(mWifiVendorHal).isVendorHalReady(); mInOrder.verify(mIfaceCallback0).onDestroyed(ifaceName); @@ -1695,13 +1896,23 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { destroyedListener.onDestroyed(ifaceName); validateOnDestroyedSoftApInterface( - anyOtherStaIface, anyOtherApIface, ifaceName, callback, networkObserver); + anyOtherStaIface, anyOtherApIface, false /* anyOtherP2pIface */, + ifaceName, callback, networkObserver); } private void validateOnDestroyedSoftApInterface( boolean anyOtherStaIface, boolean anyOtherApIface, String ifaceName, @Mock WifiNative.InterfaceCallback callback, NetdEventObserver networkObserver) throws Exception { + validateOnDestroyedSoftApInterface( + anyOtherStaIface, anyOtherApIface, false /* anyOtherP2pIface */, + ifaceName, callback, networkObserver); + } + + private void validateOnDestroyedSoftApInterface( + boolean anyOtherStaIface, boolean anyOtherApIface, boolean anyOtherP2pIface, + String ifaceName, @Mock WifiNative.InterfaceCallback callback, + NetdEventObserver networkObserver) throws Exception { if (networkObserver != null) { mInOrder.verify(mNetdWrapper).unregisterObserver(networkObserver); } @@ -1712,7 +1923,7 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { mInOrder.verify(mHostapdHal).deregisterDeathHandler(); mInOrder.verify(mHostapdHal).terminate(); } - if (!anyOtherStaIface && !anyOtherApIface) { + if (!anyOtherStaIface && !anyOtherApIface && !anyOtherP2pIface) { mInOrder.verify(mWificondControl).tearDownInterfaces(); mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); mInOrder.verify(mWifiVendorHal).stopVendorHal(); @@ -1735,4 +1946,77 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { mLooper.dispatchAll(); mInOrder.verify(mIfaceEventCallback0).onInterfaceAdded(ifaceName); } + + private void executeAndValidateCreateP2pInterface( + boolean hasStaIface, boolean hasApIface, boolean hasP2pIface, + String ifaceName, boolean vendorHalSupported, int failureCode) throws Exception { + if (failureCode != P2P_FAILURE_CODE_CREATE_INTERFACE) { + if (vendorHalSupported) { + when(mHalDeviceManager.createP2pIface(any(), any(), any())) + .thenReturn(ifaceName); + } else { + when(mPropertyService.getString(P2P_INTERFACE_PROPERTY, P2P_IFACE_NAME)) + .thenReturn(ifaceName); + } + } + mActiveP2pIface = mWifiNative.createP2pIface(mP2pInterfaceDestroyedListener, + mP2pEventHandler, TEST_WORKSOURCE); + if (failureCode == 0) { + assertNotNull(mActiveP2pIface); + assertEquals(mActiveP2pIface.name, ifaceName); + } else { + assertNull(mActiveP2pIface); + } + validateCreateP2pInterface(hasStaIface, hasApIface, hasP2pIface, + ifaceName, vendorHalSupported, failureCode); + } + + private void validateCreateP2pInterface( + boolean hasStaIface, boolean hasApIface, boolean hasP2pIface, + String ifaceName, boolean vendorHalSupported, int failureCode) throws Exception { + validateStartHal(hasStaIface || hasApIface || hasP2pIface, vendorHalSupported); + if (vendorHalSupported) { + verify(mHalDeviceManager).createP2pIface(eq(mP2pInterfaceDestroyedListener), + eq(mP2pEventHandler), eq(TEST_WORKSOURCE)); + if (failureCode == P2P_FAILURE_CODE_CREATE_INTERFACE) { + verify(mWifiMetrics).incrementNumSetupP2pInterfaceFailureDueToHal(); + } + } else { + verify(mPropertyService).getString(eq(P2P_INTERFACE_PROPERTY), eq(P2P_IFACE_NAME)); + } + } + + private void executeAndValidateTeardownP2pInterface( + boolean anyOtherStaIface, boolean anyOtherConnectivityStaIface, + boolean isSupplicantStartedBefore, boolean anyOtherApIface, + boolean anyOtherP2pIface, WifiNative.Iface iface, boolean vendorHalSupported) + throws Exception { + mWifiNative.teardownP2pIface(iface.id); + + validateOnDestroyedP2pInterface(anyOtherStaIface, anyOtherConnectivityStaIface, + isSupplicantStartedBefore, anyOtherApIface, + anyOtherP2pIface, vendorHalSupported); + } + + private void validateOnDestroyedP2pInterface( + boolean anyOtherStaIface, boolean anyOtherConnectivityStaIface, + boolean isSupplicantStartedBefore, boolean anyOtherApIface, + boolean anyOtherP2pIface, boolean vendorHalSupported) throws Exception { + if (vendorHalSupported && !anyOtherStaIface && !anyOtherApIface && !anyOtherP2pIface) { + mInOrder.verify(mWificondControl).tearDownInterfaces(); + mInOrder.verify(mWifiVendorHal).isVendorHalSupported(); + mInOrder.verify(mWifiVendorHal).stopVendorHal(); + } + if (!anyOtherConnectivityStaIface) { + mInOrder.verify(mSupplicantStaIfaceHal, atLeastOnce()).isInitializationStarted(); + if (isSupplicantStartedBefore) { + mInOrder.verify(mSupplicantStaIfaceHal).deregisterDeathHandler(); + mInOrder.verify(mSupplicantStaIfaceHal).terminate(); + } else { + if (!anyOtherP2pIface) { + mInOrder.verify(mWifiP2pNative).stopP2pSupplicantIfNecessary(); + } + } + } + } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeInterfaceManagementTest.java b/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeInterfaceManagementTest.java index cc2456f238..77453d4cac 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeInterfaceManagementTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeInterfaceManagementTest.java @@ -20,6 +20,7 @@ import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -34,18 +35,22 @@ import android.os.WorkSource; import androidx.test.filters.SmallTest; +import com.android.server.wifi.DeviceConfigFacade; import com.android.server.wifi.HalDeviceManager; import com.android.server.wifi.HalDeviceManager.InterfaceDestroyedListener; import com.android.server.wifi.HalDeviceManager.ManagerStatusListener; import com.android.server.wifi.PropertyService; import com.android.server.wifi.WifiBaseTest; +import com.android.server.wifi.WifiInjector; import com.android.server.wifi.WifiMetrics; import com.android.server.wifi.WifiNative; import com.android.server.wifi.WifiVendorHal; import com.android.server.wifi.hal.WifiHal; +import com.android.wifi.flags.FeatureFlags; import org.junit.Before; import org.junit.Test; +import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -55,8 +60,7 @@ import org.mockito.MockitoAnnotations; */ @SmallTest public class WifiP2pNativeInterfaceManagementTest extends WifiBaseTest { - private static final String P2P_IFACE_NAME = "p2p0"; - private static final String P2P_INTERFACE_PROPERTY = "wifi.direct.interface"; + private static final String TEST_P2P_IFACE_NAME = "p2p0"; private static final WorkSource TEST_WS = new WorkSource(); @Mock private SupplicantP2pIfaceHal mSupplicantP2pIfaceHal; @@ -70,6 +74,11 @@ public class WifiP2pNativeInterfaceManagementTest extends WifiBaseTest { @Mock private WifiNl80211Manager mWifiNl80211Manager; @Mock private WifiNative mWifiNative; @Mock private WifiMetrics mWifiMetrics; + @Mock private WifiNative.Iface mMockP2pIface; + @Mock private WifiInjector mWifiInjector; + @Mock private DeviceConfigFacade mDeviceConfigFacade; + @Mock private FeatureFlags mFeatureFlags; + private WifiP2pNative mWifiP2pNative; private WifiStatus mWifiStatusSuccess; private ManagerStatusListener mManagerStatusListener; @@ -84,31 +93,60 @@ public class WifiP2pNativeInterfaceManagementTest extends WifiBaseTest { mWifiStatusSuccess.code = WifiStatusCode.SUCCESS; when(mHalDeviceManager.isSupported()).thenReturn(true); + mMockP2pIface.name = TEST_P2P_IFACE_NAME; + when(mWifiNative.createP2pIface(any(InterfaceDestroyedListener.class), + any(Handler.class), any(WorkSource.class))).thenReturn(mMockP2pIface); when(mHalDeviceManager.createP2pIface(any(InterfaceDestroyedListener.class), - any(Handler.class), any(WorkSource.class))).thenReturn(P2P_IFACE_NAME); + any(Handler.class), any(WorkSource.class))).thenReturn(TEST_P2P_IFACE_NAME); when(mSupplicantP2pIfaceHal.isInitializationStarted()).thenReturn(true); when(mSupplicantP2pIfaceHal.initialize()).thenReturn(true); when(mSupplicantP2pIfaceHal.isInitializationComplete()).thenReturn(true); - when(mSupplicantP2pIfaceHal.setupIface(P2P_IFACE_NAME)).thenReturn(true); - when(mPropertyService.getString(P2P_INTERFACE_PROPERTY, P2P_IFACE_NAME)) - .thenReturn(P2P_IFACE_NAME); - + when(mSupplicantP2pIfaceHal.setupIface(TEST_P2P_IFACE_NAME)).thenReturn(true); + when(mSupplicantP2pIfaceHal.registerDeathHandler(any())).thenReturn(true); + when(mPropertyService.getString( + WifiP2pNative.P2P_INTERFACE_PROPERTY, WifiP2pNative.P2P_IFACE_NAME)) + .thenReturn(TEST_P2P_IFACE_NAME); + when(mWifiInjector.getDeviceConfigFacade()).thenReturn(mDeviceConfigFacade); + when(mDeviceConfigFacade.getFeatureFlags()).thenReturn(mFeatureFlags); + when(mFeatureFlags.d2dUsageWhenWifiOff()).thenReturn(true); mWifiP2pNative = new WifiP2pNative(mWifiNl80211Manager, mWifiNative, mWifiMetrics, - mWifiVendorHal, mSupplicantP2pIfaceHal, mHalDeviceManager, mPropertyService); + mWifiVendorHal, mSupplicantP2pIfaceHal, mHalDeviceManager, mPropertyService, + mWifiInjector); + } + + /** + * Verifies the setup of a p2p interface. + */ + @Test + public void testSetUpInterfaceByHDM() throws Exception { + when(mFeatureFlags.d2dUsageWhenWifiOff()).thenReturn(false); + testSetUpInterface(false); } /** * Verifies the setup of a p2p interface. */ @Test - public void testSetUpInterface() throws Exception { - assertEquals(P2P_IFACE_NAME, + public void testSetUpInterfaceByWifiNative() throws Exception { + testSetUpInterface(true); + } + + private void testSetUpInterface(boolean isD2dAloneFeatureEnabled) throws Exception { + assertEquals(TEST_P2P_IFACE_NAME, mWifiP2pNative.setupInterface( mHalDeviceInterfaceDestroyedListener, mHandler, TEST_WS)); - - verify(mHalDeviceManager).createP2pIface(any(InterfaceDestroyedListener.class), - eq(mHandler), eq(TEST_WS)); - verify(mSupplicantP2pIfaceHal).setupIface(eq(P2P_IFACE_NAME)); + if (isD2dAloneFeatureEnabled) { + verify(mWifiNative).createP2pIface(any(InterfaceDestroyedListener.class), + eq(mHandler), eq(TEST_WS)); + verify(mHalDeviceManager, never()).createP2pIface(any(InterfaceDestroyedListener.class), + any(), any()); + } else { + verify(mHalDeviceManager).createP2pIface(any(InterfaceDestroyedListener.class), + eq(mHandler), eq(TEST_WS)); + verify(mWifiNative, never()).createP2pIface(any(InterfaceDestroyedListener.class), + any(), any()); + } + verify(mSupplicantP2pIfaceHal).setupIface(eq(TEST_P2P_IFACE_NAME)); } /** @@ -118,13 +156,22 @@ public class WifiP2pNativeInterfaceManagementTest extends WifiBaseTest { public void testSetUpInterfaceWithNoVendorHal() throws Exception { when(mHalDeviceManager.isSupported()).thenReturn(false); - assertEquals(P2P_IFACE_NAME, mWifiP2pNative.setupInterface( + assertEquals(TEST_P2P_IFACE_NAME, mWifiP2pNative.setupInterface( mHalDeviceInterfaceDestroyedListener, mHandler, TEST_WS)); verify(mHalDeviceManager, never()) .createP2pIface(any(InterfaceDestroyedListener.class), any(Handler.class), any(WorkSource.class)); - verify(mSupplicantP2pIfaceHal).setupIface(eq(P2P_IFACE_NAME)); + verify(mSupplicantP2pIfaceHal).setupIface(eq(TEST_P2P_IFACE_NAME)); + } + + /** + * Verifies the teardown of a p2p interface. + */ + @Test + public void testTeardownInterfaceWhenD2dWithoutSTADisabled() throws Exception { + when(mFeatureFlags.d2dUsageWhenWifiOff()).thenReturn(false); + testTeardownInterface(false); } /** @@ -132,29 +179,54 @@ public class WifiP2pNativeInterfaceManagementTest extends WifiBaseTest { */ @Test public void testTeardownInterface() throws Exception { - assertEquals(P2P_IFACE_NAME, + testTeardownInterface(true); + } + + private void testTeardownInterface(boolean isD2dAloneFeatureEnabled) throws Exception { + assertEquals(TEST_P2P_IFACE_NAME, mWifiP2pNative.setupInterface(mHalDeviceInterfaceDestroyedListener, mHandler, TEST_WS)); mWifiP2pNative.teardownInterface(); verify(mHalDeviceManager).removeP2pIface(anyString()); - verify(mSupplicantP2pIfaceHal).teardownIface(eq(P2P_IFACE_NAME)); + if (!isD2dAloneFeatureEnabled) { + verify(mSupplicantP2pIfaceHal).teardownIface(eq(TEST_P2P_IFACE_NAME)); + } } /** * Verifies the teardown of a p2p interface with no HAL (HIDL) support. */ @Test - public void testTeardownInterfaceWithNoVendorHal() throws Exception { - when(mHalDeviceManager.isSupported()).thenReturn(false); + public void testTeardownInterfaceWithNoVendorHalWhenD2dAloneFeatureEnabled() throws Exception { + testTeardownInterfaceWithNoVendorHal(true); + } + /** + * Verifies the teardown of a p2p interface with no HAL (HIDL) support. + */ + @Test + public void testTeardownInterfaceWithNoVendorHalD2dAloneFeatureDisabled() throws Exception { + when(mFeatureFlags.d2dUsageWhenWifiOff()).thenReturn(false); + testTeardownInterfaceWithNoVendorHal(false); + } - assertEquals(P2P_IFACE_NAME, mWifiP2pNative.setupInterface( + private void testTeardownInterfaceWithNoVendorHal(boolean isD2dAloneFeatureEnabled) + throws Exception { + when(mHalDeviceManager.isSupported()).thenReturn(false); + InOrder order = inOrder(mSupplicantP2pIfaceHal, mWifiNative); + assertEquals(TEST_P2P_IFACE_NAME, mWifiP2pNative.setupInterface( mHalDeviceInterfaceDestroyedListener, mHandler, TEST_WS)); mWifiP2pNative.teardownInterface(); verify(mHalDeviceManager, never()).removeIface(any(WifiHal.WifiInterface.class)); - verify(mSupplicantP2pIfaceHal).teardownIface(eq(P2P_IFACE_NAME)); + if (isD2dAloneFeatureEnabled) { + order.verify(mSupplicantP2pIfaceHal).deregisterDeathHandler(); + order.verify(mSupplicantP2pIfaceHal).teardownIface(eq(TEST_P2P_IFACE_NAME)); + order.verify(mWifiNative).teardownP2pIface(eq(mMockP2pIface.id)); + } else { + order.verify(mSupplicantP2pIfaceHal).teardownIface(eq(TEST_P2P_IFACE_NAME)); + } } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeTest.java b/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeTest.java index 41054548d8..f931d76d3a 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeTest.java @@ -46,13 +46,16 @@ import android.os.WorkSource; import androidx.test.filters.SmallTest; import com.android.dx.mockito.inline.extended.ExtendedMockito; +import com.android.server.wifi.DeviceConfigFacade; import com.android.server.wifi.HalDeviceManager; import com.android.server.wifi.PropertyService; import com.android.server.wifi.WifiBaseTest; +import com.android.server.wifi.WifiInjector; import com.android.server.wifi.WifiMetrics; import com.android.server.wifi.WifiNative; import com.android.server.wifi.WifiVendorHal; import com.android.server.wifi.hal.WifiHal; +import com.android.wifi.flags.FeatureFlags; import org.junit.After; import org.junit.Before; @@ -104,6 +107,10 @@ public class WifiP2pNativeTest extends WifiBaseTest { @Mock private Handler mHandlerMock; @Mock private WorkSource mWorkSourceMock; @Mock private IWifiP2pIface mIWifiP2pIfaceMock; + @Mock private WifiNative.Iface mMockP2pIface; + @Mock private WifiInjector mWifiInjector; + @Mock private DeviceConfigFacade mDeviceConfigFacade; + @Mock private FeatureFlags mFeatureFlags; private MockitoSession mSession; private WifiP2pNative mWifiP2pNative; @@ -131,10 +138,12 @@ public class WifiP2pNativeTest extends WifiBaseTest { .startMocking(); mWifiClientInterfaceNames.add("wlan0"); mWifiClientInterfaceNames.add("wlan1"); - + when(mWifiInjector.getDeviceConfigFacade()).thenReturn(mDeviceConfigFacade); + when(mDeviceConfigFacade.getFeatureFlags()).thenReturn(mFeatureFlags); + when(mFeatureFlags.d2dUsageWhenWifiOff()).thenReturn(true); mWifiP2pNative = new WifiP2pNative(mWifiCondManager, mWifiNative, mWifiMetrics, mWifiVendorHalMock, mSupplicantP2pIfaceHalMock, mHalDeviceManagerMock, - mPropertyServiceMock); + mPropertyServiceMock, mWifiInjector); when(mWifiNative.getClientInterfaceNames()).thenReturn(mWifiClientInterfaceNames); @@ -149,7 +158,9 @@ public class WifiP2pNativeTest extends WifiBaseTest { // setup default mock behaviors when(mHalDeviceManagerMock.isSupported()).thenReturn(true); - + mMockP2pIface.name = TEST_IFACE; + when(mWifiNative.createP2pIface(any(HalDeviceManager.InterfaceDestroyedListener.class), + any(Handler.class), any(WorkSource.class))).thenReturn(mMockP2pIface); doAnswer(new AnswerWithArguments() { public boolean answer(WifiP2pGroupList groupList) { for (WifiP2pGroup g : mWifiP2pGroupList.getGroupList()) { @@ -178,16 +189,34 @@ public class WifiP2pNativeTest extends WifiBaseTest { } /** - * Verifies that setupInterface returns correct values when successfully creating P2P Iface. + * Verifies that setupInterface by calling HalDeviceManager returns correct values + * when successfully creating P2P Iface. (Old design, feature is disabled) */ @Test - public void testSetupInterfaceSuccessInCreatingP2pIface() { - when(mHalDeviceManagerMock.createP2pIface( - any(HalDeviceManager.InterfaceDestroyedListener.class), - eq(mHandlerMock), eq(mWorkSourceMock))).thenReturn(TEST_IFACE); + public void testSetupInterfaceByHDMSuccessInCreatingP2pIface() { + when(mFeatureFlags.d2dUsageWhenWifiOff()).thenReturn(false); + testSetupInterfaceSuccessInCreatingP2pIface(false); + } + + /** + * Verifies that setupInterface by WifiNative returns correct values + * when successfully creating P2P Iface. (The default behavior) + */ + @Test + public void testSetupInterfaceByWifiNativeSuccessInCreatingP2pIface() { + testSetupInterfaceSuccessInCreatingP2pIface(true); + } + + private void testSetupInterfaceSuccessInCreatingP2pIface(boolean isD2dAloneFeatureEnabled) { + if (!isD2dAloneFeatureEnabled) { + when(mHalDeviceManagerMock.createP2pIface( + any(HalDeviceManager.InterfaceDestroyedListener.class), + eq(mHandlerMock), eq(mWorkSourceMock))).thenReturn(TEST_IFACE); + } when(mSupplicantP2pIfaceHalMock.initialize()).thenReturn(true); when(mSupplicantP2pIfaceHalMock.isInitializationComplete()).thenReturn(true); when(mSupplicantP2pIfaceHalMock.setupIface(eq(TEST_IFACE))).thenReturn(true); + when(mSupplicantP2pIfaceHalMock.registerDeathHandler(any())).thenReturn(true); assertEquals( mWifiP2pNative.setupInterface( @@ -205,6 +234,7 @@ public class WifiP2pNativeTest extends WifiBaseTest { when(mSupplicantP2pIfaceHalMock.initialize()).thenReturn(true); when(mSupplicantP2pIfaceHalMock.isInitializationComplete()).thenReturn(true); when(mSupplicantP2pIfaceHalMock.setupIface(eq(TEST_IFACE))).thenReturn(true); + when(mSupplicantP2pIfaceHalMock.registerDeathHandler(any())).thenReturn(true); assertEquals( mWifiP2pNative.setupInterface( @@ -213,13 +243,34 @@ public class WifiP2pNativeTest extends WifiBaseTest { } /** - * Verifies that setupInterface returns correct values when failing in creating P2P Iface. + * Verifies that setupInterface returns correct values when failing in creating P2P Iface + * by HDM. */ @Test - public void testSetupInterfaceFailureInCreatingP2pIface() { - when(mHalDeviceManagerMock.createP2pIface( - any(HalDeviceManager.InterfaceDestroyedListener.class), - eq(mHandlerMock), eq(mWorkSourceMock))).thenReturn(null); + public void testSetupInterfaceFailureInCreatingP2pIfaceByHDM() { + when(mFeatureFlags.d2dUsageWhenWifiOff()).thenReturn(false); + testSetupInterfaceFailureInCreatingP2pIface(false); + } + + /** + * Verifies that setupInterface returns correct values when failing in creating P2P Iface + * by WifiNative. + */ + @Test + public void testSetupInterfaceFailureInCreatingP2pIfaceByWifiNative() { + testSetupInterfaceFailureInCreatingP2pIface(true); + } + + private void testSetupInterfaceFailureInCreatingP2pIface(boolean isD2dAloneFeatureEnabled) { + if (isD2dAloneFeatureEnabled) { + when(mWifiNative.createP2pIface( + any(HalDeviceManager.InterfaceDestroyedListener.class), + eq(mHandlerMock), eq(mWorkSourceMock))).thenReturn(null); + } else { + when(mHalDeviceManagerMock.createP2pIface( + any(HalDeviceManager.InterfaceDestroyedListener.class), + eq(mHandlerMock), eq(mWorkSourceMock))).thenReturn(null); + } when(mHalDeviceManagerMock.isItPossibleToCreateIface( eq(HalDeviceManager.HDM_CREATE_IFACE_P2P), eq(mWorkSourceMock))).thenReturn(true); @@ -236,10 +287,31 @@ public class WifiP2pNativeTest extends WifiBaseTest { * HalDevMgr not possibly creating it. */ @Test - public void testSetupInterfaceFailureInCreatingP2pIfaceWhenHalDevMgrNotPossiblyCreate() { - when(mHalDeviceManagerMock.createP2pIface( - any(HalDeviceManager.InterfaceDestroyedListener.class), - eq(mHandlerMock), eq(mWorkSourceMock))).thenReturn(null); + public void testSetupInterfaceFailureInHDMCreatingP2pIfaceWhenHalDevMgrNotPossiblyCreate() { + when(mFeatureFlags.d2dUsageWhenWifiOff()).thenReturn(false); + testSetupInterfaceFailureInCreatingP2pIfaceAndHalDevMgrNotPossiblyCreate(false); + } + + /** + * Verifies that Wi-Fi metrics do correct action when setting up p2p interface failed and + * HalDevMgr not possibly creating it. + */ + @Test + public void testSetupInterfaceFailureInCreatingP2pByWifiNativeAndHalDevMgrNotPossiblyCreate() { + testSetupInterfaceFailureInCreatingP2pIfaceAndHalDevMgrNotPossiblyCreate(true); + } + + private void testSetupInterfaceFailureInCreatingP2pIfaceAndHalDevMgrNotPossiblyCreate( + boolean isD2dAloneFeatureEnabled) { + if (isD2dAloneFeatureEnabled) { + when(mWifiNative.createP2pIface( + any(HalDeviceManager.InterfaceDestroyedListener.class), + eq(mHandlerMock), eq(mWorkSourceMock))).thenReturn(null); + } else { + when(mHalDeviceManagerMock.createP2pIface( + any(HalDeviceManager.InterfaceDestroyedListener.class), + eq(mHandlerMock), eq(mWorkSourceMock))).thenReturn(null); + } when(mHalDeviceManagerMock.isItPossibleToCreateIface( eq(HalDeviceManager.HDM_CREATE_IFACE_P2P), eq(mWorkSourceMock))).thenReturn(false); @@ -252,19 +324,34 @@ public class WifiP2pNativeTest extends WifiBaseTest { * initialization fails. */ @Test - public void testSetupInterfaceFailureInSupplicantConnectionInitialization() { - when(mHalDeviceManagerMock.createP2pIface( - any(HalDeviceManager.InterfaceDestroyedListener.class), - eq(mHandlerMock), eq(mWorkSourceMock))).thenReturn(TEST_IFACE); + public void testSetupInterfaceByHDMAndFailureInSupplicantConnectionInitialization() { + when(mFeatureFlags.d2dUsageWhenWifiOff()).thenReturn(false); + testSetupInterfaceFailureInSupplicantConnectionInitialization(false); + } + + /** + * Verifies that setupInterface returns correct values when supplicant connection + * initialization fails. + */ + @Test + public void testSetupInterfaceByWifiNativeAndFailureInSupplicantConnectionInitialization() { + testSetupInterfaceFailureInSupplicantConnectionInitialization(true); + } + + private void testSetupInterfaceFailureInSupplicantConnectionInitialization( + boolean isD2dAloneFeatureEnabled) { + if (!isD2dAloneFeatureEnabled) { + when(mHalDeviceManagerMock.createP2pIface( + any(HalDeviceManager.InterfaceDestroyedListener.class), + eq(mHandlerMock), eq(mWorkSourceMock))).thenReturn(TEST_IFACE); + } when(mSupplicantP2pIfaceHalMock.isInitializationStarted()).thenReturn(false); when(mSupplicantP2pIfaceHalMock.initialize()).thenReturn(false); - - mWifiP2pNative.setupInterface(mDestroyedListenerMock, mHandlerMock, mWorkSourceMock); - verify(mWifiMetrics).incrementNumSetupP2pInterfaceFailureDueToSupplicant(); assertEquals( mWifiP2pNative.setupInterface( mDestroyedListenerMock, mHandlerMock, mWorkSourceMock), null); + verify(mWifiMetrics).incrementNumSetupP2pInterfaceFailureDueToSupplicant(); } /** @@ -272,20 +359,36 @@ public class WifiP2pNativeTest extends WifiBaseTest { * initialization never completes. */ @Test - public void testSetupInterfaceFailureInSupplicantConnectionInitNotCompleted() { - when(mHalDeviceManagerMock.createP2pIface( - any(HalDeviceManager.InterfaceDestroyedListener.class), - eq(mHandlerMock), eq(mWorkSourceMock))).thenReturn(TEST_IFACE); + public void testSetupInterfaceByHDMAndFailureInSupplicantConnectionInitNotCompleted() { + when(mFeatureFlags.d2dUsageWhenWifiOff()).thenReturn(false); + testSetupInterfaceFailureInSupplicantConnectionInitNotCompleted(false); + } + + /** + * Verifies that setupInterface returns correct values when supplicant connection + * initialization never completes. + */ + @Test + public void testSetupInterfaceByWifiNativeAndFailureInSupplicantConnectionInitNotCompleted() { + testSetupInterfaceFailureInSupplicantConnectionInitNotCompleted(true); + } + + private void testSetupInterfaceFailureInSupplicantConnectionInitNotCompleted( + boolean isD2dAloneFeatureEnabled) { + if (!isD2dAloneFeatureEnabled) { + when(mHalDeviceManagerMock.createP2pIface( + any(HalDeviceManager.InterfaceDestroyedListener.class), + eq(mHandlerMock), eq(mWorkSourceMock))).thenReturn(TEST_IFACE); + } when(mSupplicantP2pIfaceHalMock.setupIface(eq(TEST_IFACE))).thenReturn(true); when(mSupplicantP2pIfaceHalMock.initialize()).thenReturn(true); when(mSupplicantP2pIfaceHalMock.isInitializationComplete()).thenReturn(false); - mWifiP2pNative.setupInterface(mDestroyedListenerMock, mHandlerMock, mWorkSourceMock); - verify(mWifiMetrics).incrementNumSetupP2pInterfaceFailureDueToSupplicant(); assertEquals( mWifiP2pNative.setupInterface( mDestroyedListenerMock, mHandlerMock, mWorkSourceMock), null); + verify(mWifiMetrics).incrementNumSetupP2pInterfaceFailureDueToSupplicant(); } /** @@ -293,20 +396,52 @@ public class WifiP2pNativeTest extends WifiBaseTest { * for supplicant. */ @Test - public void testSetupInterfaceFailureInSettingUpP2pIfaceInSupplicant() { - when(mHalDeviceManagerMock.createP2pIface( - any(HalDeviceManager.InterfaceDestroyedListener.class), - eq(mHandlerMock), eq(mWorkSourceMock))).thenReturn(TEST_IFACE); + public void testSetupInterfaceByHDMAndFailureInSettingUpP2pIfaceInSupplicant() { + when(mFeatureFlags.d2dUsageWhenWifiOff()).thenReturn(false); + testSetupInterfaceFailureInSettingUpP2pIfaceInSupplicant(false); + } + + /** + * Verifies that setupInterface returns correct values when failing in setting up P2P Iface + * for supplicant. + */ + @Test + public void testSetupInterfaceByWifiNativeAndFailureInSettingUpP2pIfaceInSupplicant() { + testSetupInterfaceFailureInSettingUpP2pIfaceInSupplicant(true); + } + private void testSetupInterfaceFailureInSettingUpP2pIfaceInSupplicant( + boolean isD2dAloneFeatureEnabled) { + if (!isD2dAloneFeatureEnabled) { + when(mHalDeviceManagerMock.createP2pIface( + any(HalDeviceManager.InterfaceDestroyedListener.class), + eq(mHandlerMock), eq(mWorkSourceMock))).thenReturn(TEST_IFACE); + } when(mSupplicantP2pIfaceHalMock.initialize()).thenReturn(true); when(mSupplicantP2pIfaceHalMock.isInitializationComplete()).thenReturn(true); when(mSupplicantP2pIfaceHalMock.setupIface(eq(TEST_IFACE))).thenReturn(false); - mWifiP2pNative.setupInterface(mDestroyedListenerMock, mHandlerMock, mWorkSourceMock); + assertEquals( + mWifiP2pNative.setupInterface( + mDestroyedListenerMock, mHandlerMock, mWorkSourceMock), + null); verify(mWifiMetrics).incrementNumSetupP2pInterfaceFailureDueToSupplicant(); + } + + /** + * Verifies that setupInterface returns correct values when failing in setting up + * P2P supplicant handler. + */ + @Test + public void testSetupInterfaceFailureInSettingUpP2pIfaceInSupplicantRegisterDeathHandler() { + when(mSupplicantP2pIfaceHalMock.initialize()).thenReturn(true); + when(mSupplicantP2pIfaceHalMock.isInitializationComplete()).thenReturn(true); + when(mSupplicantP2pIfaceHalMock.setupIface(eq(TEST_IFACE))).thenReturn(true); + when(mSupplicantP2pIfaceHalMock.registerDeathHandler(any())).thenReturn(false); assertEquals( mWifiP2pNative.setupInterface( mDestroyedListenerMock, mHandlerMock, mWorkSourceMock), null); + verify(mWifiMetrics).incrementNumSetupP2pInterfaceFailureDueToSupplicant(); } /** @@ -1014,6 +1149,7 @@ public class WifiP2pNativeTest extends WifiBaseTest { when(mSupplicantP2pIfaceHalMock.initialize()).thenReturn(true); when(mSupplicantP2pIfaceHalMock.isInitializationComplete()).thenReturn(true); when(mSupplicantP2pIfaceHalMock.setupIface(any())).thenReturn(true); + when(mSupplicantP2pIfaceHalMock.registerDeathHandler(any())).thenReturn(true); mWifiP2pNative.setupInterface(mDestroyedListenerMock, mHandlerMock, mWorkSourceMock); } @@ -1056,4 +1192,15 @@ public class WifiP2pNativeTest extends WifiBaseTest { verify(mSupplicantP2pIfaceHalMock).configureEapolIpAddressAllocationParams(eq(0x0101A8C0), eq(0x00FFFFFF), eq(0x0501A8C0), eq(0x0801A8C0)); } + + @Test + public void testStopP2pSupplicantIfNecessary() throws Exception { + when(mSupplicantP2pIfaceHalMock.isInitializationStarted()).thenReturn(false); + mWifiP2pNative.stopP2pSupplicantIfNecessary(); + verify(mSupplicantP2pIfaceHalMock, never()).terminate(); + + when(mSupplicantP2pIfaceHalMock.isInitializationStarted()).thenReturn(true); + mWifiP2pNative.stopP2pSupplicantIfNecessary(); + verify(mSupplicantP2pIfaceHalMock).terminate(); + } } |