diff options
Diffstat (limited to 'service/java/com/android/server/wifi/HostapdHal.java')
-rw-r--r-- | service/java/com/android/server/wifi/HostapdHal.java | 1067 |
1 files changed, 0 insertions, 1067 deletions
diff --git a/service/java/com/android/server/wifi/HostapdHal.java b/service/java/com/android/server/wifi/HostapdHal.java deleted file mode 100644 index 1ff8368e3..000000000 --- a/service/java/com/android/server/wifi/HostapdHal.java +++ /dev/null @@ -1,1067 +0,0 @@ -/* - * 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 android.annotation.NonNull; -import android.content.Context; -import android.hardware.wifi.hostapd.V1_0.HostapdStatus; -import android.hardware.wifi.hostapd.V1_0.HostapdStatusCode; -import android.hardware.wifi.hostapd.V1_0.IHostapd; -import android.hardware.wifi.hostapd.V1_2.DebugLevel; -import android.hardware.wifi.hostapd.V1_2.Ieee80211ReasonCode; -import android.hidl.manager.V1_0.IServiceManager; -import android.hidl.manager.V1_0.IServiceNotification; -import android.net.MacAddress; -import android.net.wifi.SoftApConfiguration; -import android.net.wifi.SoftApConfiguration.BandType; -import android.net.wifi.WifiManager; -import android.os.Handler; -import android.os.IHwBinder.DeathRecipient; -import android.os.RemoteException; -import android.text.TextUtils; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wifi.WifiNative.HostapdDeathEventHandler; -import com.android.server.wifi.util.ApConfigUtil; -import com.android.server.wifi.util.NativeUtil; -import com.android.wifi.resources.R; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Random; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import javax.annotation.concurrent.ThreadSafe; - -/** - * To maintain thread-safety, the locking protocol is that every non-static method (regardless of - * access level) acquires mLock. - */ -@ThreadSafe -public class HostapdHal { - private static final String TAG = "HostapdHal"; - @VisibleForTesting - public static final String HAL_INSTANCE_NAME = "default"; - @VisibleForTesting - public static final long WAIT_FOR_DEATH_TIMEOUT_MS = 50L; - - private final Object mLock = new Object(); - private boolean mVerboseLoggingEnabled = false; - private final Context mContext; - private final Handler mEventHandler; - private boolean mForceApChannel = false; - private int mForcedApBand; - private int mForcedApChannel; - private String mConfig2gChannelList; - private String mConfig5gChannelList; - private String mConfig6gChannelList; - - // Hostapd HAL interface objects - private IServiceManager mIServiceManager = null; - private IHostapd mIHostapd; - private HashMap<String, Runnable> mSoftApFailureListeners = new HashMap<>(); - private HostapdDeathEventHandler mDeathEventHandler; - private ServiceManagerDeathRecipient mServiceManagerDeathRecipient; - private HostapdDeathRecipient mHostapdDeathRecipient; - // Death recipient cookie registered for current supplicant instance. - private long mDeathRecipientCookie = 0; - - private final IServiceNotification mServiceNotificationCallback = - new IServiceNotification.Stub() { - public void onRegistration(String fqName, String name, boolean preexisting) { - synchronized (mLock) { - if (mVerboseLoggingEnabled) { - Log.i(TAG, "IServiceNotification.onRegistration for: " + fqName - + ", " + name + " preexisting=" + preexisting); - } - if (!initHostapdService()) { - Log.e(TAG, "initalizing IHostapd failed."); - hostapdServiceDiedHandler(mDeathRecipientCookie); - } else { - Log.i(TAG, "Completed initialization of IHostapd."); - } - } - } - }; - private class ServiceManagerDeathRecipient implements DeathRecipient { - @Override - public void serviceDied(long cookie) { - mEventHandler.post(() -> { - synchronized (mLock) { - Log.w(TAG, "IServiceManager died: cookie=" + cookie); - hostapdServiceDiedHandler(mDeathRecipientCookie); - mIServiceManager = null; // Will need to register a new ServiceNotification - } - }); - } - } - private class HostapdDeathRecipient implements DeathRecipient { - @Override - public void serviceDied(long cookie) { - mEventHandler.post(() -> { - synchronized (mLock) { - Log.w(TAG, "IHostapd/IHostapd died: cookie=" + cookie); - hostapdServiceDiedHandler(cookie); - } - }); - } - } - - public HostapdHal(Context context, Handler handler) { - mContext = context; - mEventHandler = handler; - mServiceManagerDeathRecipient = new ServiceManagerDeathRecipient(); - mHostapdDeathRecipient = new HostapdDeathRecipient(); - } - - /** - * Enable/Disable verbose logging. - * - * @param enable true to enable, false to disable. - */ - void enableVerboseLogging(boolean enable) { - synchronized (mLock) { - mVerboseLoggingEnabled = enable; - setLogLevel(); - } - } - - /** - * 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() { - return checkHalVersionByInterfaceName( - android.hardware.wifi.hostapd.V1_1.IHostapd.kInterfaceName); - } - - /** - * Uses the IServiceManager to check if the device is running V1_2 of the HAL from the VINTF for - * the device. - * @return true if supported, false otherwise. - */ - private boolean isV1_2() { - return checkHalVersionByInterfaceName( - android.hardware.wifi.hostapd.V1_2.IHostapd.kInterfaceName); - } - - private boolean checkHalVersionByInterfaceName(String interfaceName) { - if (interfaceName == null) { - return false; - } - synchronized (mLock) { - if (mIServiceManager == null) { - Log.e(TAG, "checkHalVersionByInterfaceName called but mServiceManager is null!?"); - return false; - } - try { - return (mIServiceManager.getTransport( - interfaceName, - 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. - */ - private boolean linkToServiceManagerDeath() { - synchronized (mLock) { - if (mIServiceManager == null) return false; - try { - if (!mIServiceManager.linkToDeath(mServiceManagerDeathRecipient, 0)) { - Log.wtf(TAG, "Error on linkToDeath on IServiceManager"); - hostapdServiceDiedHandler(mDeathRecipientCookie); - mIServiceManager = null; // Will need to register a new ServiceNotification - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "IServiceManager.linkToDeath exception", e); - mIServiceManager = null; // Will need to register a new ServiceNotification - return false; - } - return true; - } - } - - /** - * Registers a service notification for the IHostapd service, which triggers intialization of - * the IHostapd - * @return true if the service notification was successfully registered - */ - public boolean initialize() { - synchronized (mLock) { - if (mVerboseLoggingEnabled) { - Log.i(TAG, "Registering IHostapd service ready callback."); - } - mIHostapd = null; - if (mIServiceManager != null) { - // Already have an IServiceManager and serviceNotification registered, don't - // don't register another. - return true; - } - try { - mIServiceManager = getServiceManagerMockable(); - if (mIServiceManager == null) { - Log.e(TAG, "Failed to get HIDL Service Manager"); - return false; - } - if (!linkToServiceManagerDeath()) { - return false; - } - /* TODO(b/33639391) : Use the new IHostapd.registerForNotifications() once it - exists */ - if (!mIServiceManager.registerForNotifications( - IHostapd.kInterfaceName, "", mServiceNotificationCallback)) { - Log.e(TAG, "Failed to register for notifications to " - + IHostapd.kInterfaceName); - mIServiceManager = null; // Will need to register a new ServiceNotification - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "Exception while trying to register a listener for IHostapd service: " - + e); - hostapdServiceDiedHandler(mDeathRecipientCookie); - mIServiceManager = null; // Will need to register a new ServiceNotification - return false; - } - return true; - } - } - - /** - * Link to death for IHostapd object. - * @return true on success, false otherwise. - */ - private boolean linkToHostapdDeath(DeathRecipient deathRecipient, long cookie) { - synchronized (mLock) { - if (mIHostapd == null) return false; - try { - if (!mIHostapd.linkToDeath(deathRecipient, cookie)) { - Log.wtf(TAG, "Error on linkToDeath on IHostapd"); - hostapdServiceDiedHandler(mDeathRecipientCookie); - return false; - } - } catch (RemoteException e) { - Log.e(TAG, "IHostapd.linkToDeath exception", e); - return false; - } - return true; - } - } - - 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. - */ - private boolean initHostapdService() { - synchronized (mLock) { - try { - mIHostapd = getHostapdMockable(); - } catch (RemoteException e) { - Log.e(TAG, "IHostapd.getService exception: " + e); - return false; - } catch (NoSuchElementException e) { - Log.e(TAG, "IHostapd.getService exception: " + e); - return false; - } - if (mIHostapd == null) { - Log.e(TAG, "Got null IHostapd service. Stopping hostapd HIDL startup"); - return false; - } - if (!linkToHostapdDeath(mHostapdDeathRecipient, ++mDeathRecipientCookie)) { - Log.e(TAG, "Fail to link to Hostapd Death, Stopping hostapd HIDL startup"); - mIHostapd = null; - return false; - } - // Register for callbacks for 1.1 hostapd. - if (isV1_1() && !registerCallback(new HostapdCallback())) { - Log.e(TAG, "Fail to regiester Callback, Stopping hostapd HIDL startup"); - mIHostapd = null; - return false; - } - - // Setup log level - setLogLevel(); - } - return true; - } - - /** - * Enable force-soft-AP-channel mode which takes effect when soft AP starts next time - * @param forcedApChannel The forced IEEE channel number - */ - void enableForceSoftApChannel(int forcedApChannel, int forcedApBand) { - mForceApChannel = true; - mForcedApChannel = forcedApChannel; - mForcedApBand = forcedApBand; - } - - /** - * Disable force-soft-AP-channel mode which take effect when soft AP starts next time - */ - void disableForceSoftApChannel() { - mForceApChannel = false; - } - - private boolean isSendFreqRangesNeeded(@BandType int band) { - // Fist we check if one of the selected bands has restrictions in the overlay file. - // Note, - // - We store the config string here for future use, hence we need to check all bands. - // - If there is no OEM restriction, we store the full band - boolean retVal = false; - if ((band & SoftApConfiguration.BAND_2GHZ) != 0) { - mConfig2gChannelList = - mContext.getResources().getString(R.string.config_wifiSoftap2gChannelList); - if (TextUtils.isEmpty(mConfig2gChannelList)) { - mConfig2gChannelList = "1-14"; - } else { - retVal = true; - } - } - - if ((band & SoftApConfiguration.BAND_5GHZ) != 0) { - mConfig5gChannelList = - mContext.getResources().getString(R.string.config_wifiSoftap5gChannelList); - if (TextUtils.isEmpty(mConfig5gChannelList)) { - mConfig5gChannelList = "34-173"; - } else { - retVal = true; - } - } - - if ((band & SoftApConfiguration.BAND_6GHZ) != 0) { - mConfig6gChannelList = - mContext.getResources().getString(R.string.config_wifiSoftap6gChannelList); - if (TextUtils.isEmpty(mConfig6gChannelList)) { - mConfig6gChannelList = "1-254"; - } else { - retVal = true; - } - } - - // If any of the selected band has restriction in the overlay file, we return true. - if (retVal) { - return true; - } - - // Next, if only one of 5G or 6G is selected, then we need freqList to separate them - // Since there is no other way. - if (((band & SoftApConfiguration.BAND_5GHZ) != 0) - && ((band & SoftApConfiguration.BAND_6GHZ) == 0)) { - return true; - } - if (((band & SoftApConfiguration.BAND_5GHZ) == 0) - && ((band & SoftApConfiguration.BAND_6GHZ) != 0)) { - return true; - } - - // In all other cases, we don't need to set the freqList - return false; - } - - /** - * Add and start a new access point. - * - * @param ifaceName Name of the interface. - * @param config Configuration to use for the AP. - * @param onFailureListener A runnable to be triggered on failure. - * @return true on success, false otherwise. - */ - public boolean addAccessPoint(@NonNull String ifaceName, @NonNull SoftApConfiguration config, - @NonNull Runnable onFailureListener) { - synchronized (mLock) { - final String methodStr = "addAccessPoint"; - IHostapd.IfaceParams ifaceParams = new IHostapd.IfaceParams(); - ifaceParams.ifaceName = ifaceName; - ifaceParams.hwModeParams.enable80211N = true; - ifaceParams.hwModeParams.enable80211AC = - mContext.getResources().getBoolean( - R.bool.config_wifi_softap_ieee80211ac_supported); - int band; - boolean enableAcs = ApConfigUtil.isAcsSupported(mContext) && config.getChannel() == 0 - && !mForceApChannel; - if (enableAcs) { - ifaceParams.channelParams.enableAcs = true; - ifaceParams.channelParams.acsShouldExcludeDfs = !mContext.getResources() - .getBoolean(R.bool.config_wifiSoftapAcsIncludeDfs); - } - ifaceParams.channelParams.channel = - mForceApChannel ? mForcedApChannel : config.getChannel(); - band = mForceApChannel ? mForcedApBand : config.getBand(); - - android.hardware.wifi.hostapd.V1_2.IHostapd.NetworkParams nwParamsV1_2 = - prepareNetworkParams(config); - if (nwParamsV1_2 == null) return false; - if (!checkHostapdAndLogFailure(methodStr)) return false; - try { - HostapdStatus status; - if (!isV1_1() && !isV1_2()) { - ifaceParams.channelParams.band = getHalBand(band); - status = mIHostapd.addAccessPoint(ifaceParams, nwParamsV1_2.V1_0); - if (!checkStatusAndLogFailure(status, methodStr)) { - return false; - } - } else { - android.hardware.wifi.hostapd.V1_1.IHostapd.IfaceParams ifaceParams1_1 = - new android.hardware.wifi.hostapd.V1_1.IHostapd.IfaceParams(); - ifaceParams1_1.V1_0 = ifaceParams; - if (!isV1_2()) { - ifaceParams.channelParams.band = getHalBand(band); - - if (ifaceParams.channelParams.enableAcs) { - if ((band & SoftApConfiguration.BAND_2GHZ) != 0) { - ifaceParams1_1.channelParams.acsChannelRanges.addAll( - toAcsChannelRanges(mContext.getResources().getString( - R.string.config_wifiSoftap2gChannelList))); - } - if ((band & SoftApConfiguration.BAND_5GHZ) != 0) { - ifaceParams1_1.channelParams.acsChannelRanges.addAll( - toAcsChannelRanges(mContext.getResources().getString( - R.string.config_wifiSoftap5gChannelList))); - } - } - - android.hardware.wifi.hostapd.V1_1.IHostapd iHostapdV1_1 = - getHostapdMockableV1_1(); - if (iHostapdV1_1 == null) return false; - - status = iHostapdV1_1.addAccessPoint_1_1(ifaceParams1_1, nwParamsV1_2.V1_0); - if (!checkStatusAndLogFailure(status, methodStr)) { - return false; - } - } else { - android.hardware.wifi.hostapd.V1_2.HostapdStatus status12; - android.hardware.wifi.hostapd.V1_2.IHostapd.IfaceParams ifaceParams1_2 = - new android.hardware.wifi.hostapd.V1_2.IHostapd.IfaceParams(); - ifaceParams1_2.V1_1 = ifaceParams1_1; - - ifaceParams1_2.hwModeParams.enable80211AX = - mContext.getResources().getBoolean( - R.bool.config_wifiSoftapIeee80211axSupported); - ifaceParams1_2.hwModeParams.enable6GhzBand = - mContext.getResources().getBoolean( - R.bool.config_wifiSoftap6ghzSupported); - ifaceParams1_2.hwModeParams.enableHeSingleUserBeamformer = - mContext.getResources().getBoolean( - R.bool.config_wifiSoftapHeSuBeamformerSupported); - ifaceParams1_2.hwModeParams.enableHeSingleUserBeamformee = - mContext.getResources().getBoolean( - R.bool.config_wifiSoftapHeSuBeamformeeSupported); - ifaceParams1_2.hwModeParams.enableHeMultiUserBeamformer = - mContext.getResources().getBoolean( - R.bool.config_wifiSoftapHeMuBeamformerSupported); - ifaceParams1_2.hwModeParams.enableHeTargetWakeTime = - mContext.getResources().getBoolean( - R.bool.config_wifiSoftapHeTwtSupported); - ifaceParams1_2.channelParams.bandMask = getHalBandMask(band); - - // Prepare freq ranges/lists if needed - if (ifaceParams.channelParams.enableAcs - && isSendFreqRangesNeeded(band)) { - if ((band & SoftApConfiguration.BAND_2GHZ) != 0) { - ifaceParams1_2.channelParams.acsChannelFreqRangesMhz.addAll( - toAcsFreqRanges(SoftApConfiguration.BAND_2GHZ)); - } - if ((band & SoftApConfiguration.BAND_5GHZ) != 0) { - ifaceParams1_2.channelParams.acsChannelFreqRangesMhz.addAll( - toAcsFreqRanges(SoftApConfiguration.BAND_5GHZ)); - } - if ((band & SoftApConfiguration.BAND_6GHZ) != 0) { - ifaceParams1_2.channelParams.acsChannelFreqRangesMhz.addAll( - toAcsFreqRanges(SoftApConfiguration.BAND_6GHZ)); - } - } - - android.hardware.wifi.hostapd.V1_2.IHostapd iHostapdV1_2 = - getHostapdMockableV1_2(); - if (iHostapdV1_2 == null) return false; - status12 = iHostapdV1_2.addAccessPoint_1_2(ifaceParams1_2, nwParamsV1_2); - if (!checkStatusAndLogFailure12(status12, methodStr)) { - return false; - } - } - } - - mSoftApFailureListeners.put(ifaceName, onFailureListener); - return true; - } catch (IllegalArgumentException e) { - Log.e(TAG, "Unrecognized apBand: " + band); - return false; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Remove a previously started access point. - * - * @param ifaceName Name of the interface. - * @return true on success, false otherwise. - */ - public boolean removeAccessPoint(@NonNull String ifaceName) { - synchronized (mLock) { - final String methodStr = "removeAccessPoint"; - if (!checkHostapdAndLogFailure(methodStr)) return false; - try { - HostapdStatus status = mIHostapd.removeAccessPoint(ifaceName); - if (!checkStatusAndLogFailure(status, methodStr)) { - return false; - } - mSoftApFailureListeners.remove(ifaceName); - return true; - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - return false; - } - } - } - - /** - * Remove a previously connected client. - * - * @param ifaceName Name of the interface. - * @param client Mac Address of the client. - * @param reasonCode One of disconnect reason code which defined in {@link WifiManager}. - * @return true on success, false otherwise. - */ - public boolean forceClientDisconnect(@NonNull String ifaceName, - @NonNull MacAddress client, int reasonCode) { - final String methodStr = "forceClientDisconnect"; - if (isV1_2()) { - try { - android.hardware.wifi.hostapd.V1_2.IHostapd iHostapdV1_2 = - getHostapdMockableV1_2(); - if (iHostapdV1_2 == null) return false; - byte[] clientMacByteArray = client.toByteArray(); - short disconnectReason; - switch (reasonCode) { - case WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER: - disconnectReason = Ieee80211ReasonCode.WLAN_REASON_PREV_AUTH_NOT_VALID; - break; - case WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS: - disconnectReason = Ieee80211ReasonCode.WLAN_REASON_DISASSOC_AP_BUSY; - break; - case WifiManager.SAP_CLIENT_DISCONNECT_REASON_CODE_UNSPECIFIED: - disconnectReason = Ieee80211ReasonCode.WLAN_REASON_UNSPECIFIED; - break; - default: - throw new IllegalArgumentException( - "Unknown disconnect reason code:" + reasonCode); - } - android.hardware.wifi.hostapd.V1_2.HostapdStatus status = - iHostapdV1_2.forceClientDisconnect(ifaceName, - clientMacByteArray, disconnectReason); - if (status.code == HostapdStatusCode.SUCCESS) { - return true; - } - Log.d(TAG, "Error when call forceClientDisconnect, status.code = " + status.code); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - } - } else { - Log.d(TAG, "HIDL doesn't support forceClientDisconnect"); - } - return false; - } - - /** - * Registers a death notification for hostapd. - * @return Returns true on success. - */ - public boolean registerDeathHandler(@NonNull HostapdDeathEventHandler handler) { - if (mDeathEventHandler != null) { - Log.e(TAG, "Death handler already present"); - } - mDeathEventHandler = handler; - return true; - } - - /** - * Deregisters a death notification for hostapd. - * @return Returns true on success. - */ - public boolean deregisterDeathHandler() { - if (mDeathEventHandler == null) { - Log.e(TAG, "No Death handler present"); - } - mDeathEventHandler = null; - return true; - } - - /** - * Clear internal state. - */ - private void clearState() { - synchronized (mLock) { - mIHostapd = null; - } - } - - /** - * Handle hostapd death. - */ - private void hostapdServiceDiedHandler(long cookie) { - synchronized (mLock) { - if (mDeathRecipientCookie != cookie) { - Log.i(TAG, "Ignoring stale death recipient notification"); - return; - } - clearState(); - if (mDeathEventHandler != null) { - mDeathEventHandler.onDeath(); - } - } - } - - /** - * Signals whether Initialization completed successfully. - */ - public boolean isInitializationStarted() { - synchronized (mLock) { - return mIServiceManager != null; - } - } - - /** - * Signals whether Initialization completed successfully. - */ - public boolean isInitializationComplete() { - synchronized (mLock) { - return mIHostapd != null; - } - } - - /** - * Start the hostapd daemon. - * - * @return true on success, false otherwise. - */ - public boolean startDaemon() { - synchronized (mLock) { - try { - // This should startup hostapd daemon using the lazy start HAL mechanism. - getHostapdMockable(); - } catch (RemoteException e) { - Log.e(TAG, "Exception while trying to start hostapd: " - + e); - hostapdServiceDiedHandler(mDeathRecipientCookie); - return false; - } catch (NoSuchElementException e) { - // We're starting the daemon, so expect |NoSuchElementException|. - Log.d(TAG, "Successfully triggered start of hostapd using HIDL"); - } - return true; - } - } - - /** - * Terminate the hostapd daemon & wait for it's death. - */ - public void terminate() { - synchronized (mLock) { - // Register for a new death listener to block until hostapd is dead. - final long waitForDeathCookie = new Random().nextLong(); - final CountDownLatch waitForDeathLatch = new CountDownLatch(1); - linkToHostapdDeath((cookie) -> { - Log.d(TAG, "IHostapd died: cookie=" + cookie); - if (cookie != waitForDeathCookie) return; - waitForDeathLatch.countDown(); - }, waitForDeathCookie); - - final String methodStr = "terminate"; - if (!checkHostapdAndLogFailure(methodStr)) return; - try { - mIHostapd.terminate(); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - } - - // Now wait for death listener callback to confirm that it's dead. - try { - if (!waitForDeathLatch.await(WAIT_FOR_DEATH_TIMEOUT_MS, TimeUnit.MILLISECONDS)) { - Log.w(TAG, "Timed out waiting for confirmation of hostapd death"); - } - } catch (InterruptedException e) { - Log.w(TAG, "Failed to wait for hostapd death"); - } - } - } - - /** - * Wrapper functions to access static HAL methods, created to be mockable in unit tests - */ - @VisibleForTesting - protected IServiceManager getServiceManagerMockable() throws RemoteException { - synchronized (mLock) { - return IServiceManager.getService(); - } - } - - @VisibleForTesting - protected IHostapd getHostapdMockable() throws RemoteException { - synchronized (mLock) { - return IHostapd.getService(); - } - } - - @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; - } - } - } - - @VisibleForTesting - protected android.hardware.wifi.hostapd.V1_2.IHostapd getHostapdMockableV1_2() - throws RemoteException { - synchronized (mLock) { - try { - return android.hardware.wifi.hostapd.V1_2.IHostapd.castFrom(mIHostapd); - } catch (NoSuchElementException e) { - Log.e(TAG, "Failed to get IHostapd", e); - return null; - } - } - } - - private android.hardware.wifi.hostapd.V1_2.IHostapd.NetworkParams - prepareNetworkParams(SoftApConfiguration config) { - android.hardware.wifi.hostapd.V1_2.IHostapd.NetworkParams nwParamsV1_2 = - new android.hardware.wifi.hostapd.V1_2.IHostapd.NetworkParams(); - nwParamsV1_2.V1_0.ssid.addAll(NativeUtil.stringToByteArrayList(config.getSsid())); - nwParamsV1_2.V1_0.isHidden = config.isHiddenSsid(); - int encryptionType = getEncryptionType(config); - nwParamsV1_2.encryptionType = encryptionType; - nwParamsV1_2.passphrase = (config.getPassphrase() != null) - ? config.getPassphrase() : ""; - if (encryptionType - == android.hardware.wifi.hostapd.V1_2.IHostapd.EncryptionType.WPA3_SAE - || encryptionType == android.hardware.wifi.hostapd.V1_2.IHostapd - .EncryptionType.WPA3_SAE_TRANSITION) { - if (!isV1_2()) { - // It should not happen since we should reject configuration in SoftApManager - Log.e(TAG, "Unsupported Configuration found: " + config); - return null; - } - } else { - // Fill old parameter for old hidl. - nwParamsV1_2.V1_0.encryptionType = encryptionType; - nwParamsV1_2.V1_0.pskPassphrase = (config.getPassphrase() != null) - ? config.getPassphrase() : ""; - } - return nwParamsV1_2; - } - - private static int getEncryptionType(SoftApConfiguration localConfig) { - int encryptionType; - switch (localConfig.getSecurityType()) { - case SoftApConfiguration.SECURITY_TYPE_OPEN: - encryptionType = IHostapd.EncryptionType.NONE; - break; - case SoftApConfiguration.SECURITY_TYPE_WPA2_PSK: - encryptionType = IHostapd.EncryptionType.WPA2; - break; - case SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION: - encryptionType = android.hardware.wifi.hostapd.V1_2 - .IHostapd.EncryptionType.WPA3_SAE_TRANSITION; - break; - case SoftApConfiguration.SECURITY_TYPE_WPA3_SAE: - encryptionType = android.hardware.wifi.hostapd.V1_2 - .IHostapd.EncryptionType.WPA3_SAE; - break; - default: - // We really shouldn't default to None, but this was how NetworkManagementService - // used to do this. - encryptionType = IHostapd.EncryptionType.NONE; - break; - } - return encryptionType; - } - - private static int getHalBandMask(int apBand) { - int bandMask = 0; - - if (!ApConfigUtil.isBandValid(apBand)) { - throw new IllegalArgumentException(); - } - - if (ApConfigUtil.containsBand(apBand, SoftApConfiguration.BAND_2GHZ)) { - bandMask |= android.hardware.wifi.hostapd.V1_2.IHostapd.BandMask.BAND_2_GHZ; - } - if (ApConfigUtil.containsBand(apBand, SoftApConfiguration.BAND_5GHZ)) { - bandMask |= android.hardware.wifi.hostapd.V1_2.IHostapd.BandMask.BAND_5_GHZ; - } - if (ApConfigUtil.containsBand(apBand, SoftApConfiguration.BAND_6GHZ)) { - bandMask |= android.hardware.wifi.hostapd.V1_2.IHostapd.BandMask.BAND_6_GHZ; - } - - return bandMask; - } - - private static int getHalBand(int apBand) { - if (!ApConfigUtil.isBandValid(apBand)) { - throw new IllegalArgumentException(); - } - - switch (apBand) { - case SoftApConfiguration.BAND_2GHZ: - return IHostapd.Band.BAND_2_4_GHZ; - case SoftApConfiguration.BAND_5GHZ: - return IHostapd.Band.BAND_5_GHZ; - default: - return IHostapd.Band.BAND_ANY; - } - } - - /** - * Convert channel list string like '1-6,11' to list of AcsChannelRanges - */ - private List<android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange> - toAcsChannelRanges(String channelListStr) { - ArrayList<android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange> acsChannelRanges = - new ArrayList<>(); - - for (String channelRange : channelListStr.split(",")) { - android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange acsChannelRange = - new android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange(); - try { - if (channelRange.contains("-")) { - String[] channels = channelRange.split("-"); - if (channels.length != 2) { - Log.e(TAG, "Unrecognized channel range, length is " + channels.length); - continue; - } - int start = Integer.parseInt(channels[0].trim()); - int end = Integer.parseInt(channels[1].trim()); - if (start > end) { - Log.e(TAG, "Invalid channel range, from " + start + " to " + end); - continue; - } - acsChannelRange.start = start; - acsChannelRange.end = end; - } else { - acsChannelRange.start = Integer.parseInt(channelRange.trim()); - acsChannelRange.end = acsChannelRange.start; - } - } catch (NumberFormatException e) { - // Ignore malformed value - Log.e(TAG, "Malformed channel value detected: " + e); - continue; - } - acsChannelRanges.add(acsChannelRange); - } - return acsChannelRanges; - } - - /** - * Convert channel list string like '1-6,11' to list of AcsFreqRange - */ - private List<android.hardware.wifi.hostapd.V1_2.IHostapd.AcsFrequencyRange> - toAcsFreqRanges(@BandType int band) { - List<android.hardware.wifi.hostapd.V1_2.IHostapd.AcsFrequencyRange> - acsFrequencyRanges = new ArrayList<>(); - - if (!ApConfigUtil.isBandValid(band) || ApConfigUtil.isMultiband(band)) { - Log.e(TAG, "Invalid band : " + band); - return acsFrequencyRanges; - } - - String channelListStr; - switch (band) { - case SoftApConfiguration.BAND_2GHZ: - channelListStr = mConfig2gChannelList; - break; - case SoftApConfiguration.BAND_5GHZ: - channelListStr = mConfig5gChannelList; - break; - case SoftApConfiguration.BAND_6GHZ: - channelListStr = mConfig6gChannelList; - break; - default: - return acsFrequencyRanges; - } - - for (String channelRange : channelListStr.split(",")) { - android.hardware.wifi.hostapd.V1_2.IHostapd.AcsFrequencyRange acsFrequencyRange = - new android.hardware.wifi.hostapd.V1_2.IHostapd.AcsFrequencyRange(); - try { - if (channelRange.contains("-")) { - String[] channels = channelRange.split("-"); - if (channels.length != 2) { - Log.e(TAG, "Unrecognized channel range, length is " + channels.length); - continue; - } - int start = Integer.parseInt(channels[0].trim()); - int end = Integer.parseInt(channels[1].trim()); - if (start > end) { - Log.e(TAG, "Invalid channel range, from " + start + " to " + end); - continue; - } - acsFrequencyRange.start = ApConfigUtil.convertChannelToFrequency(start, band); - acsFrequencyRange.end = ApConfigUtil.convertChannelToFrequency(end, band); - } else { - int channel = Integer.parseInt(channelRange.trim()); - acsFrequencyRange.start = ApConfigUtil.convertChannelToFrequency(channel, band); - acsFrequencyRange.end = acsFrequencyRange.start; - } - } catch (NumberFormatException e) { - // Ignore malformed value - Log.e(TAG, "Malformed channel value detected: " + e); - continue; - } - acsFrequencyRanges.add(acsFrequencyRange); - } - return acsFrequencyRanges; - } - - /** - * Returns false if Hostapd is null, and logs failure to call methodStr - */ - private boolean checkHostapdAndLogFailure(String methodStr) { - synchronized (mLock) { - if (mIHostapd == null) { - Log.e(TAG, "Can't call " + methodStr + ", IHostapd is null"); - return false; - } - return true; - } - } - - /** - * Returns true if provided status code is SUCCESS, logs debug message and returns false - * otherwise - */ - private boolean checkStatusAndLogFailure(HostapdStatus status, - String methodStr) { - synchronized (mLock) { - if (status.code != HostapdStatusCode.SUCCESS) { - Log.e(TAG, "IHostapd." + methodStr + " failed: " + status.code - + ", " + status.debugMessage); - return false; - } else { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "IHostapd." + methodStr + " succeeded"); - } - return true; - } - } - } - - /** - * Returns true if provided status code is SUCCESS, logs debug message and returns false - * otherwise - */ - private boolean checkStatusAndLogFailure12( - android.hardware.wifi.hostapd.V1_2.HostapdStatus status, String methodStr) { - synchronized (mLock) { - if (status.code != HostapdStatusCode.SUCCESS) { - Log.e(TAG, "IHostapd." + methodStr + " failed: " + status.code - + ", " + status.debugMessage); - return false; - } else { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "IHostapd." + methodStr + " succeeded"); - } - return true; - } - } - } - - private void handleRemoteException(RemoteException e, String methodStr) { - synchronized (mLock) { - hostapdServiceDiedHandler(mDeathRecipientCookie); - Log.e(TAG, "IHostapd." + methodStr + " failed with exception", e); - } - } - - 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); - Runnable onFailureListener = mSoftApFailureListeners.get(ifaceName); - if (onFailureListener != null) { - onFailureListener.run(); - } - } - } - - /** - * Set the debug log level for hostapd. - * - * @return true if request is sent successfully, false otherwise. - */ - public boolean setLogLevel() { - synchronized (mLock) { - final String methodStr = "setDebugParams"; - if (!checkHostapdAndLogFailure(methodStr)) return false; - if (isV1_2()) { - try { - android.hardware.wifi.hostapd.V1_2.IHostapd iHostapdV1_2 = - getHostapdMockableV1_2(); - if (iHostapdV1_2 == null) return false; - android.hardware.wifi.hostapd.V1_2.HostapdStatus status = - iHostapdV1_2.setDebugParams(mVerboseLoggingEnabled - ? DebugLevel.DEBUG - : DebugLevel.INFO); - return checkStatusAndLogFailure12(status, methodStr); - } catch (RemoteException e) { - handleRemoteException(e, methodStr); - } - } else { - Log.d(TAG, "HIDL doesn't support setDebugParams"); - } - return false; - } - } -} |