From bdebe2a4348c6b61375a683a4010263a0a835c18 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Fri, 17 Aug 2018 11:06:30 -0700 Subject: HostapdHal: Register for failure callbacks Register for callbacks from V1.1 hostapd HAL. This CL just contains the plumbing needed for registering the HAL Callback. The next CL in the stack will use the onFailure callback to handle errors. Bug: 112705137 Test: Manual test. Simulated the issue reported in the bug and ensured that UI toggled off. Test: Unit tests Change-Id: I1406aafe6af72364a58e5f40cbe318b4df51ef6f --- service/Android.mk | 1 + .../java/com/android/server/wifi/HostapdHal.java | 77 +++++++++++++++++++--- 2 files changed, 68 insertions(+), 10 deletions(-) (limited to 'service') diff --git a/service/Android.mk b/service/Android.mk index 21d776855..c43acfae8 100644 --- a/service/Android.mk +++ b/service/Android.mk @@ -68,6 +68,7 @@ LOCAL_STATIC_JAVA_LIBRARIES := \ android.hardware.wifi-V1.2-java \ android.hardware.wifi-V1.3-java \ android.hardware.wifi.hostapd-V1.0-java \ + android.hardware.wifi.hostapd-V1.1-java \ android.hardware.wifi.supplicant-V1.0-java \ android.hardware.wifi.supplicant-V1.1-java \ ksoap2 diff --git a/service/java/com/android/server/wifi/HostapdHal.java b/service/java/com/android/server/wifi/HostapdHal.java index 9395e2daf..b44e68fb7 100644 --- a/service/java/com/android/server/wifi/HostapdHal.java +++ b/service/java/com/android/server/wifi/HostapdHal.java @@ -44,6 +44,8 @@ import javax.annotation.concurrent.ThreadSafe; @ThreadSafe public class HostapdHal { private static final String TAG = "HostapdHal"; + @VisibleForTesting + public static final String HAL_INSTANCE_NAME = "default"; private final Object mLock = new Object(); private boolean mVerboseLoggingEnabled = false; @@ -106,6 +108,30 @@ public class HostapdHal { } } + /** + * Uses the IServiceManager to check if the device is running V1_1 of the HAL from the VINTF for + * the device. + * @return true if supported, false otherwise. + */ + private boolean isV1_1() { + synchronized (mLock) { + if (mIServiceManager == null) { + Log.e(TAG, "isV1_1: called but mServiceManager is null!?"); + return false; + } + try { + return (mIServiceManager.getTransport( + android.hardware.wifi.hostapd.V1_1.IHostapd.kInterfaceName, + HAL_INSTANCE_NAME) + != IServiceManager.Transport.EMPTY); + } catch (RemoteException e) { + Log.e(TAG, "Exception while operating on IServiceManager: " + e); + handleRemoteException(e, "getTransport"); + return false; + } + } + } + /** * Link to death for IServiceManager object. * @return true on success, false otherwise. @@ -195,6 +221,22 @@ public class HostapdHal { } } + private boolean registerCallback( + android.hardware.wifi.hostapd.V1_1.IHostapdCallback callback) { + synchronized (mLock) { + String methodStr = "registerCallback_1_1"; + try { + android.hardware.wifi.hostapd.V1_1.IHostapd iHostapdV1_1 = getHostapdMockableV1_1(); + if (iHostapdV1_1 == null) return false; + HostapdStatus status = iHostapdV1_1.registerCallback(callback); + return checkStatusAndLogFailure(status, methodStr); + } catch (RemoteException e) { + handleRemoteException(e, methodStr); + return false; + } + } + } + /** * Initialize the IHostapd object. * @return true on success, false otherwise. @@ -212,6 +254,12 @@ public class HostapdHal { return false; } if (!linkToHostapdDeath()) { + mIHostapd = null; + return false; + } + // Register for callbacks for 1.1 hostapd. + if (isV1_1() && !registerCallback(new HostapdCallback())) { + mIHostapd = null; return false; } } @@ -414,6 +462,19 @@ public class HostapdHal { } } + @VisibleForTesting + protected android.hardware.wifi.hostapd.V1_1.IHostapd getHostapdMockableV1_1() + throws RemoteException { + synchronized (mLock) { + try { + return android.hardware.wifi.hostapd.V1_1.IHostapd.castFrom(mIHostapd); + } catch (NoSuchElementException e) { + Log.e(TAG, "Failed to get IHostapd", e); + return null; + } + } + } + private static int getEncryptionType(WifiConfiguration localConfig) { int encryptionType; switch (localConfig.getAuthType()) { @@ -493,15 +554,11 @@ public class HostapdHal { } } - private static void logd(String s) { - Log.d(TAG, s); - } - - private static void logi(String s) { - Log.i(TAG, s); - } - - private static void loge(String s) { - Log.e(TAG, s); + private class HostapdCallback extends + android.hardware.wifi.hostapd.V1_1.IHostapdCallback.Stub { + @Override + public void onFailure(String ifaceName) { + Log.w(TAG, "Failure on iface " + ifaceName); + } } } -- cgit v1.2.3 From 4d4ab7b5b841ea7284aa7510ab24112c1874dab4 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Fri, 17 Aug 2018 11:37:11 -0700 Subject: SoftApManager: Handle asynchronous failures SoftApManager currently does not get a notification when hostapd runs into any failure after |IHostapd.addAccesPoint|. Use the new onFailure() callback from hostapd to handle asynchronous failures. The failure callback from hostapd will be treated similar to an interface down indication (i.e will send CMD_INTERFACE_STATUS_CHANGED message). Bug: 112705137 Test: Manual test. Simulated the issue reported in the bug and ensured that UI toggled off. Test: Unit tests Change-Id: I59e36fc7e457d1b21f5426b4b9f32a5e64b3463b --- .../java/com/android/server/wifi/HostapdHal.java | 22 +++++++++++++++++++--- .../com/android/server/wifi/SoftApManager.java | 10 ++++++++++ .../java/com/android/server/wifi/WifiNative.java | 7 ++++++- 3 files changed, 35 insertions(+), 4 deletions(-) (limited to 'service') diff --git a/service/java/com/android/server/wifi/HostapdHal.java b/service/java/com/android/server/wifi/HostapdHal.java index b44e68fb7..5fb828ba0 100644 --- a/service/java/com/android/server/wifi/HostapdHal.java +++ b/service/java/com/android/server/wifi/HostapdHal.java @@ -33,6 +33,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.server.wifi.WifiNative.HostapdDeathEventHandler; import com.android.server.wifi.util.NativeUtil; +import java.util.HashMap; import java.util.NoSuchElementException; import javax.annotation.concurrent.ThreadSafe; @@ -55,6 +56,7 @@ public class HostapdHal { // Hostapd HAL interface objects private IServiceManager mIServiceManager = null; private IHostapd mIHostapd; + private HashMap mSoftApListeners = new HashMap<>(); private HostapdDeathEventHandler mDeathEventHandler; private final IServiceNotification mServiceNotificationCallback = @@ -271,9 +273,11 @@ public class HostapdHal { * * @param ifaceName Name of the interface. * @param config Configuration to use for the AP. + * @param listener Callback for AP events. * @return true on success, false otherwise. */ - public boolean addAccessPoint(@NonNull String ifaceName, @NonNull WifiConfiguration config) { + public boolean addAccessPoint(@NonNull String ifaceName, @NonNull WifiConfiguration config, + @NonNull WifiNative.SoftApListener listener) { synchronized (mLock) { final String methodStr = "addAccessPoint"; IHostapd.IfaceParams ifaceParams = new IHostapd.IfaceParams(); @@ -314,7 +318,11 @@ public class HostapdHal { if (!checkHostapdAndLogFailure(methodStr)) return false; try { HostapdStatus status = mIHostapd.addAccessPoint(ifaceParams, nwParams); - return checkStatusAndLogFailure(status, methodStr); + if (!checkStatusAndLogFailure(status, methodStr)) { + return false; + } + mSoftApListeners.put(ifaceName, listener); + return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); return false; @@ -334,7 +342,11 @@ public class HostapdHal { if (!checkHostapdAndLogFailure(methodStr)) return false; try { HostapdStatus status = mIHostapd.removeAccessPoint(ifaceName); - return checkStatusAndLogFailure(status, methodStr); + if (!checkStatusAndLogFailure(status, methodStr)) { + return false; + } + mSoftApListeners.remove(ifaceName); + return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); return false; @@ -559,6 +571,10 @@ public class HostapdHal { @Override public void onFailure(String ifaceName) { Log.w(TAG, "Failure on iface " + ifaceName); + WifiNative.SoftApListener listener = mSoftApListeners.get(ifaceName); + if (listener != null) { + listener.onFailure(); + } } } } diff --git a/service/java/com/android/server/wifi/SoftApManager.java b/service/java/com/android/server/wifi/SoftApManager.java index 1d11996b4..53cbd7958 100644 --- a/service/java/com/android/server/wifi/SoftApManager.java +++ b/service/java/com/android/server/wifi/SoftApManager.java @@ -99,6 +99,12 @@ public class SoftApManager implements ActiveModeManager { * Listener for soft AP events. */ private final SoftApListener mSoftApListener = new SoftApListener() { + + @Override + public void onFailure() { + mStateMachine.sendMessage(SoftApStateMachine.CMD_FAILURE); + } + @Override public void onNumAssociatedStationsChanged(int numStations) { mStateMachine.sendMessage( @@ -292,6 +298,7 @@ public class SoftApManager implements ActiveModeManager { private class SoftApStateMachine extends StateMachine { // Commands for the state machine. public static final int CMD_START = 0; + public static final int CMD_FAILURE = 2; public static final int CMD_INTERFACE_STATUS_CHANGED = 3; public static final int CMD_NUM_ASSOCIATED_STATIONS_CHANGED = 4; public static final int CMD_NO_ASSOCIATED_STATIONS_TIMEOUT = 5; @@ -622,6 +629,9 @@ public class SoftApManager implements ActiveModeManager { mApInterfaceName = null; transitionTo(mIdleState); break; + case CMD_FAILURE: + Log.w(TAG, "hostapd failure, stop and report failure"); + /* fall through */ case CMD_INTERFACE_DOWN: Log.w(TAG, "interface error, stop and report failure"); updateApState(WifiManager.WIFI_AP_STATE_FAILED, diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java index 625f89cfa..72663e7ab 100644 --- a/service/java/com/android/server/wifi/WifiNative.java +++ b/service/java/com/android/server/wifi/WifiNative.java @@ -1320,6 +1320,11 @@ public class WifiNative { * Callbacks for SoftAp interface. */ public interface SoftApListener { + /** + * Invoked when there is some fatal failure in the lower layers. + */ + void onFailure(); + /** * Invoked when the number of associated stations changes. */ @@ -1378,7 +1383,7 @@ public class WifiNative { Log.e(TAG, "Failed to register ap listener"); return false; } - if (!mHostapdHal.addAccessPoint(ifaceName, config)) { + if (!mHostapdHal.addAccessPoint(ifaceName, config, listener)) { Log.e(TAG, "Failed to add acccess point"); mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd(); return false; -- cgit v1.2.3