(九十二) Android O WiFi热点 开启流程梳理续

前言:之前在(七十一)Android O WiFi热点 开启流程梳理 梳理到了WifiStateMachine就没梳理得下去了,现在继续梳理下面流程。

 

1.流程梳理

    class SoftApState extends State {
        private SoftApManager mSoftApManager;
        private String mIfaceName;
        private int mMode;

        private class SoftApListener implements SoftApManager.Listener {
            @Override
            public void onStateChanged(int state, int reason) {
                if (state == WIFI_AP_STATE_DISABLED) {
                    sendMessage(CMD_AP_STOPPED);
                } else if (state == WIFI_AP_STATE_FAILED) {
                    sendMessage(CMD_START_AP_FAILURE);
                }

                setWifiApState(state, reason, mIfaceName, mMode);
            }
        }

        @Override
        public void enter() {
            final Message message = getCurrentMessage();
            if (message.what != CMD_START_AP) {
                throw new RuntimeException("Illegal transition to SoftApState: " + message);
            }
            SoftApModeConfiguration config = (SoftApModeConfiguration) message.obj;
            mMode = config.getTargetMode();

            IApInterface apInterface = null;
            Pair<Integer, IApInterface> statusAndInterface = mWifiNative.setupForSoftApMode();
            if (statusAndInterface.first == WifiNative.SETUP_SUCCESS) {
                apInterface = statusAndInterface.second;
            } else {
                incrementMetricsForSetupFailure(statusAndInterface.first);
            }
            if (apInterface == null) {
                setWifiApState(WIFI_AP_STATE_FAILED,
                        WifiManager.SAP_START_FAILURE_GENERAL, null, mMode);
                /**
                 * Transition to InitialState to reset the
                 * driver/HAL back to the initial state.
                 */
                transitionTo(mInitialState);
                return;
            }

            try {
                mIfaceName = apInterface.getInterfaceName();
            } catch (RemoteException e) {
                // Failed to get the interface name. The name will not be available for
                // the enabled broadcast, but since we had an error getting the name, we most likely
                // won't be able to fully start softap mode.
            }

            checkAndSetConnectivityInstance();
            mSoftApManager = mWifiInjector.makeSoftApManager(mNwService,
                                                             new SoftApListener(),
                                                             apInterface,
                                                             config.getWifiConfiguration());
            mSoftApManager.start();
            mWifiStateTracker.updateState(WifiStateTracker.SOFT_AP);
        }

先看下mWifiNative.setupForSoftApMode,与WiFi启动的时候做个对照

   /**
    * Setup wifi native for Client mode operations.
    *
    * 1. Starts the Wifi HAL and configures it in client/STA mode.
    * 2. Setup Wificond to operate in client mode and retrieve the handle to use for client
    * operations.
    *
    * @return Pair of <Integer, IClientInterface> to indicate the status and the associated wificond
    * client interface binder handler (will be null on failure).
    */
    public Pair<Integer, IClientInterface> setupForClientMode() {
        if (!startHalIfNecessary(true)) {
            Log.e(mTAG, "Failed to start HAL for client mode");
            return Pair.create(SETUP_FAILURE_HAL, null);
        }
        IClientInterface iClientInterface = mWificondControl.setupDriverForClientMode();
        if (iClientInterface == null) {
            return Pair.create(SETUP_FAILURE_WIFICOND, null);
        }
        return Pair.create(SETUP_SUCCESS, iClientInterface);
    }

    /**
     * Setup wifi native for AP mode operations.
     *
     * 1. Starts the Wifi HAL and configures it in AP mode.
     * 2. Setup Wificond to operate in AP mode and retrieve the handle to use for ap operations.
     *
     * @return Pair of <Integer, IApInterface> to indicate the status and the associated wificond
     * AP interface binder handler (will be null on failure).
     */
    public Pair<Integer, IApInterface> setupForSoftApMode() {
        if (!startHalIfNecessary(false)) {
            Log.e(mTAG, "Failed to start HAL for AP mode");
            return Pair.create(SETUP_FAILURE_HAL, null);
        }
        IApInterface iApInterface = mWificondControl.setupDriverForSoftApMode();
        if (iApInterface == null) {
            return Pair.create(SETUP_FAILURE_WIFICOND, null);
        }
        return Pair.create(SETUP_SUCCESS, iApInterface);
    }

区别

1.startHalIfNecessary传入的参数不同

2.调用的是mWificondControl.setupDriverForClientMode/mWificondControl.setupDriverForSoftApMode

1.1 startHalIfNecessary

WifiNative

    /**
     * Bring up the Vendor HAL and configure for STA mode or AP mode, if vendor HAL is supported.
     *
     * @param isStaMode true to start HAL in STA mode, false to start in AP mode.
     * @return false if the HAL start fails, true if successful or if vendor HAL not supported.
     */
    private boolean startHalIfNecessary(boolean isStaMode) {
        if (!mWifiVendorHal.isVendorHalSupported()) {
            Log.i(mTAG, "Vendor HAL not supported, Ignore start...");
            return true;
        }
        return mWifiVendorHal.startVendorHal(isStaMode);
    }

WifiVendorHal

    /**
     * Bring up the HIDL Vendor HAL and configure for STA mode or AP mode.
     *
     * @param isStaMode true to start HAL in STA mode, false to start in AP mode.
     */
    public boolean startVendorHal(boolean isStaMode) {
        synchronized (sLock) {
            if (mIWifiStaIface != null) return boolResult(false);
            if (mIWifiApIface != null) return boolResult(false);
            if (!mHalDeviceManager.start()) {
                return startFailedTo("start the vendor HAL");
            }
            IWifiIface iface;
            if (isStaMode) {
                mIWifiStaIface = mHalDeviceManager.createStaIface(null, null);
                if (mIWifiStaIface == null) {
                    return startFailedTo("create STA Iface");
                }
                iface = (IWifiIface) mIWifiStaIface;
                if (!registerStaIfaceCallback()) {
                    return startFailedTo("register sta iface callback");
                }
                mIWifiRttController = mHalDeviceManager.createRttController(iface);
                if (mIWifiRttController == null) {
                    return startFailedTo("create RTT controller");
                }
                if (!registerRttEventCallback()) {
                    return startFailedTo("register RTT iface callback");
                }
                enableLinkLayerStats();
            } else {
                mIWifiApIface = mHalDeviceManager.createApIface(null, null);
                if (mIWifiApIface == null) {
                    return startFailedTo("create AP Iface");
                }
                iface = (IWifiIface) mIWifiApIface;
            }
            mIWifiChip = mHalDeviceManager.getChip(iface);
            if (mIWifiChip == null) {
                return startFailedTo("get the chip created for the Iface");
            }
            if (!registerChipCallback()) {
                return startFailedTo("register chip callback");
            }
            mLog.i("Vendor Hal started successfully");
            return true;
        }
    }

mHalDeviceManager.start()这个流程是和WiFi启动一样的,就是将frameworks/opt/net/wifi/libwifi_hal/Android.mk中的libwifi-hal-fallback/libwifi-hal-bcm/libwifi-hal-qcom/libwifi-hal-mt66xx 初始化一下,过程略。

区别在于mHalDeviceManager.createApIface是创建ap的interface。

先看一下WiFi启动的时序图

可以料想softap这块也是加载驱动。

HalDeviceManager

    /**
     * Create AP interface if possible (see createStaIface doc).
     */
    public IWifiApIface createApIface(InterfaceDestroyedListener destroyedListener,
            Looper looper) {
        return (IWifiApIface) createIface(IfaceType.AP, destroyedListener, looper);
    }

    private IWifiIface createIface(int ifaceType, InterfaceDestroyedListener destroyedListener,
            Looper looper) {
        if (DBG) Log.d(TAG, "createIface: ifaceType=" + ifaceType);

        synchronized (mLock) {
            WifiChipInfo[] chipInfos = getAllChipInfo();
            if (chipInfos == null) {
                Log.e(TAG, "createIface: no chip info found");
                stopWifi(); // major error: shutting down
                return null;
            }

            if (!validateInterfaceCache(chipInfos)) {
                Log.e(TAG, "createIface: local cache is invalid!");
                stopWifi(); // major error: shutting down
                return null;
            }

            IWifiIface iface = createIfaceIfPossible(chipInfos, ifaceType, destroyedListener,
                    looper);
            if (iface != null) { // means that some configuration has changed
                if (!dispatchAvailableForRequestListeners()) {
                    return null; // catastrophic failure - shut down
                }
            }

            return iface;
        }
    }

    private IWifiIface createIfaceIfPossible(WifiChipInfo[] chipInfos, int ifaceType,
            InterfaceDestroyedListener destroyedListener, Looper looper) {
        if (DBG) {
            Log.d(TAG, "createIfaceIfPossible: chipInfos=" + Arrays.deepToString(chipInfos)
                    + ", ifaceType=" + ifaceType);
        }
        synchronized (mLock) {
            IfaceCreationData bestIfaceCreationProposal = null;
            for (WifiChipInfo chipInfo: chipInfos) {
                for (IWifiChip.ChipMode chipMode: chipInfo.availableModes) {
                    for (IWifiChip.ChipIfaceCombination chipIfaceCombo : chipMode
                            .availableCombinations) {
                        int[][] expandedIfaceCombos = expandIfaceCombos(chipIfaceCombo);
                        if (DBG) {
                            Log.d(TAG, chipIfaceCombo + " expands to "
                                    + Arrays.deepToString(expandedIfaceCombos));
                        }

                        for (int[] expandedIfaceCombo: expandedIfaceCombos) {
                            IfaceCreationData currentProposal = canIfaceComboSupportRequest(
                                    chipInfo, chipMode, expandedIfaceCombo, ifaceType);
                            if (compareIfaceCreationData(currentProposal,
                                    bestIfaceCreationProposal)) {
                                if (DBG) Log.d(TAG, "new proposal accepted");
                                bestIfaceCreationProposal = currentProposal;
                            }
                        }
                    }
                }
            }

            if (bestIfaceCreationProposal != null) {
                IWifiIface iface = executeChipReconfiguration(bestIfaceCreationProposal, ifaceType);
                if (iface != null) {
                    InterfaceCacheEntry cacheEntry = new InterfaceCacheEntry();

                    cacheEntry.chip = bestIfaceCreationProposal.chipInfo.chip;
                    cacheEntry.chipId = bestIfaceCreationProposal.chipInfo.chipId;
                    cacheEntry.name = getName(iface);
                    cacheEntry.type = ifaceType;
                    if (destroyedListener != null) {
                        cacheEntry.destroyedListeners.add(
                                new InterfaceDestroyedListenerProxy(destroyedListener,
                                        looper == null ? Looper.myLooper() : looper));
                    }

                    if (DBG) Log.d(TAG, "createIfaceIfPossible: added cacheEntry=" + cacheEntry);
                    mInterfaceInfoCache.put(cacheEntry.name, cacheEntry);
                    return iface;
                }
            }
        }

        return null;
    }

    /**
     * Performs chip reconfiguration per the input:
     * - Removes the specified interfaces
     * - Reconfigures the chip to the new chip mode (if necessary)
     * - Creates the new interface
     *
     * Returns the newly created interface or a null on any error.
     */
    private IWifiIface executeChipReconfiguration(IfaceCreationData ifaceCreationData,
            int ifaceType) {
        if (DBG) {
            Log.d(TAG, "executeChipReconfiguration: ifaceCreationData=" + ifaceCreationData
                    + ", ifaceType=" + ifaceType);
        }
        synchronized (mLock) {
            try {
                // is this a mode change?
                boolean isModeConfigNeeded = !ifaceCreationData.chipInfo.currentModeIdValid
                        || ifaceCreationData.chipInfo.currentModeId != ifaceCreationData.chipModeId;
                if (DBG) Log.d(TAG, "isModeConfigNeeded=" + isModeConfigNeeded);

                // first delete interfaces/change modes
                if (isModeConfigNeeded) {
                    // remove all interfaces pre mode-change
                    // TODO: is this necessary? note that even if we don't want to explicitly
                    // remove the interfaces we do need to call the onDeleted callbacks - which
                    // this does
                    for (WifiIfaceInfo[] ifaceInfos: ifaceCreationData.chipInfo.ifaces) {
                        for (WifiIfaceInfo ifaceInfo: ifaceInfos) {
                            removeIfaceInternal(ifaceInfo.iface); // ignore return value
                        }
                    }

                    WifiStatus status = ifaceCreationData.chipInfo.chip.configureChip(
                            ifaceCreationData.chipModeId);
                    if (status.code != WifiStatusCode.SUCCESS) {
                        Log.e(TAG, "executeChipReconfiguration: configureChip error: "
                                + statusString(status));
                        return null;
                    }
                } else {
                    // remove all interfaces on the delete list
                    for (WifiIfaceInfo ifaceInfo: ifaceCreationData.interfacesToBeRemovedFirst) {
                        removeIfaceInternal(ifaceInfo.iface); // ignore return value
                    }
                }

                // create new interface
                Mutable<WifiStatus> statusResp = new Mutable<>();
                Mutable<IWifiIface> ifaceResp = new Mutable<>();
                switch (ifaceType) {
                    case IfaceType.STA:
                        ifaceCreationData.chipInfo.chip.createStaIface(
                                (WifiStatus status, IWifiStaIface iface) -> {
                                    statusResp.value = status;
                                    ifaceResp.value = iface;
                                });
                        break;
                    case IfaceType.AP:
                        ifaceCreationData.chipInfo.chip.createApIface(
                                (WifiStatus status, IWifiApIface iface) -> {
                                    statusResp.value = status;
                                    ifaceResp.value = iface;
                                });
                        break;
                    case IfaceType.P2P:
                        ifaceCreationData.chipInfo.chip.createP2pIface(
                                (WifiStatus status, IWifiP2pIface iface) -> {
                                    statusResp.value = status;
                                    ifaceResp.value = iface;
                                });
                        break;
                    case IfaceType.NAN:
                        ifaceCreationData.chipInfo.chip.createNanIface(
                                (WifiStatus status, IWifiNanIface iface) -> {
                                    statusResp.value = status;
                                    ifaceResp.value = iface;
                                });
                        break;
                }

                if (statusResp.value.code != WifiStatusCode.SUCCESS) {
                    Log.e(TAG, "executeChipReconfiguration: failed to create interface ifaceType="
                            + ifaceType + ": " + statusString(statusResp.value));
                    return null;
                }

                return ifaceResp.value;
            } catch (RemoteException e) {
                Log.e(TAG, "executeChipReconfiguration exception: " + e);
                return null;
            }
        }
    }

                    WifiStatus status = ifaceCreationData.chipInfo.chip.configureChip(
                            ifaceCreationData.chipModeId);

这下面应该也和WiFi启动的流程一样,是加载驱动。区别应该是下面的switch-case

 

hardware/interfaces/wifi/1.1/default/wifi_chip.cpp

createApIface

Return<void> WifiChip::createApIface(createApIface_cb hidl_status_cb) {
  return validateAndCall(this,
                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
                         &WifiChip::createApIfaceInternal,
                         hidl_status_cb);
}

std::pair<WifiStatus, sp<IWifiApIface>> WifiChip::createApIfaceInternal() {
  if (current_mode_id_ != kApChipModeId || ap_iface_.get()) {
    return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
  }
  std::string ifname = legacy_hal_.lock()->getApIfaceName();
  ap_iface_ = new WifiApIface(ifname, legacy_hal_);
  for (const auto& callback : event_cb_handler_.getCallbacks()) {
    if (!callback->onIfaceAdded(IfaceType::AP, ifname).isOk()) {
      LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
    }
  }
  return {createWifiStatus(WifiStatusCode::SUCCESS), ap_iface_};
}

 

wifi.cpp
Wifi::Wifi()
    : legacy_hal_(new legacy_hal::WifiLegacyHal()),
      mode_controller_(new mode_controller::WifiModeController()),
      run_state_(RunState::STOPPED) {}

WifiStatus Wifi::startInternal() {
  if (run_state_ == RunState::STARTED) {
    return createWifiStatus(WifiStatusCode::SUCCESS);
  } else if (run_state_ == RunState::STOPPING) {
    return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE,
                            "HAL is stopping");
  }
  WifiStatus wifi_status = initializeLegacyHal();
  if (wifi_status.code == WifiStatusCode::SUCCESS) {
    // Create the chip instance once the HAL is started.
    chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_);
    run_state_ = RunState::STARTED;
    for (const auto& callback : event_cb_handler_.getCallbacks()) {
      if (!callback->onStart().isOk()) {
        LOG(ERROR) << "Failed to invoke onStart callback";
      };
    }
    LOG(INFO) << "Wifi HAL started";
  } else {
    for (const auto& callback : event_cb_handler_.getCallbacks()) {
      if (!callback->onFailure(wifi_status).isOk()) {
        LOG(ERROR) << "Failed to invoke onFailure callback";
      }
    }
    LOG(ERROR) << "Wifi HAL start failed";
  }
  return wifi_status;
}


wifi_legacy_hal.h
std::string WifiLegacyHal::getApIfaceName() {
  // Fake name. This interface does not exist in legacy HAL
  // API's.
  return "ap0";
}

wifi_ap_iface.h
WifiApIface::WifiApIface(
    const std::string& ifname,
    const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
    : ifname_(ifname), legacy_hal_(legacy_hal), is_valid_(true) {}

 

1.2 setupDriverForSoftApMode

    /**
    * Setup driver for softAp mode via wificond.
    * @return An IApInterface as wificond Ap interface binder handler.
    * Returns null on failure.
    */
    public IApInterface setupDriverForSoftApMode() {
        Log.d(TAG, "Setting up driver for soft ap mode");
        mWificond = mWifiInjector.makeWificond();
        if (mWificond == null) {
            Log.e(TAG, "Failed to get reference to wificond");
            return null;
        }

        IApInterface apInterface = null;
        try {
            apInterface = mWificond.createApInterface();
        } catch (RemoteException e1) {
            Log.e(TAG, "Failed to get IApInterface due to remote exception");
            return null;
        }

        if (apInterface == null) {
            Log.e(TAG, "Could not get IApInterface instance from wificond");
            return null;
        }
        Binder.allowBlocking(apInterface.asBinder());

        // Refresh Handlers
        mApInterface = apInterface;

        return apInterface;
    }

/system/connectivity/wificond/server.cpp

Status Server::createApInterface(sp<IApInterface>* created_interface) {
  InterfaceInfo interface;
  if (!SetupInterface(&interface)) {
    return Status::ok();  // Logging was done internally
  }

  unique_ptr<ApInterfaceImpl> ap_interface(new ApInterfaceImpl(
      interface.name,
      interface.index,
      netlink_utils_,
      if_tool_.get(),
      hostapd_manager_.get()));
  *created_interface = ap_interface->GetBinder();
  ap_interfaces_.push_back(std::move(ap_interface));
  BroadcastApInterfaceReady(ap_interfaces_.back()->GetBinder());

  return Status::ok();
}

bool Server::SetupInterface(InterfaceInfo* interface) {
  if (!ap_interfaces_.empty() || !client_interfaces_.empty()) {
    // In the future we may support multiple interfaces at once.  However,
    // today, we support just one.
    LOG(ERROR) << "Cannot create AP interface when other interfaces exist";
    return false;
  }

  if (!RefreshWiphyIndex()) {
    return false;
  }

  netlink_utils_->SubscribeRegDomainChange(
          wiphy_index_,
          std::bind(&Server::OnRegDomainChanged,
          this,
          _1));

  interfaces_.clear();
  if (!netlink_utils_->GetInterfaces(wiphy_index_, &interfaces_)) {
    LOG(ERROR) << "Failed to get interfaces info from kernel";
    return false;
  }

  for (const auto& iface : interfaces_) {
    // Some kernel/driver uses station type for p2p interface.
    // In that case we can only rely on hard-coded name to exclude
    // p2p interface from station interfaces.
    // Currently NAN interfaces also use station type.
    // We should blacklist NAN interfaces as well.
    if (iface.name != "p2p0" &&
        !android::base::StartsWith(iface.name, "aware_data")) {
      *interface = iface;
      return true;
    }
  }


ap_interface_impl.cpp
ApInterfaceImpl::ApInterfaceImpl(const string& interface_name,
                                 uint32_t interface_index,
                                 NetlinkUtils* netlink_utils,
                                 InterfaceTool* if_tool,
                                 HostapdManager* hostapd_manager)
    : interface_name_(interface_name),
      interface_index_(interface_index),
      netlink_utils_(netlink_utils),
      if_tool_(if_tool),
      hostapd_manager_(hostapd_manager),
      binder_(new ApInterfaceBinder(this)),
      number_of_associated_stations_(0) {
  // This log keeps compiler happy.
  LOG(DEBUG) << "Created ap interface " << interface_name_
             << " with index " << interface_index_;

  netlink_utils_->SubscribeStationEvent(
      interface_index_,
      std::bind(&ApInterfaceImpl::OnStationEvent,
                this,
                _1, _2));
}

 

1.3 SoftApManager.start

            mSoftApManager = mWifiInjector.makeSoftApManager(mNwService,
                                                             new SoftApListener(),
                                                             apInterface,
                                                             config.getWifiConfiguration());
            mSoftApManager.start();
    /**
     * Create a SoftApManager.
     * @param nmService NetworkManagementService allowing SoftApManager to listen for interface
     * changes
     * @param listener listener for SoftApManager
     * @param apInterface network interface to start hostapd against
     * @param config softAp WifiConfiguration
     * @return an instance of SoftApManager
     */
    public SoftApManager makeSoftApManager(INetworkManagementService nmService,
                                           SoftApManager.Listener listener,
                                           IApInterface apInterface,
                                           WifiConfiguration config) {
        return new SoftApManager(mWifiServiceHandlerThread.getLooper(),
                                 mWifiNative, mCountryCode.getCountryCode(),
                                 listener, apInterface, nmService,
                                 mWifiApConfigStore, config, mWifiMetrics);
    }

 

    /**
     * Start soft AP with the supplied config.
     */
    public void start() {
        mStateMachine.sendMessage(SoftApStateMachine.CMD_START, mApConfig);
    }

SoftApManager也是一个状态机

        SoftApStateMachine(Looper looper) {
            super(TAG, looper);

            addState(mIdleState);
            addState(mStartedState);

            setInitialState(mIdleState);
            start();
        }

IdleState处理CMD_START消息

        private class IdleState extends State {
            @Override
            public void enter() {
                mDeathRecipient.unlinkToDeath();
                unregisterObserver();
            }

            @Override
            public boolean processMessage(Message message) {
                switch (message.what) {
                    case CMD_START:
                        updateApState(WifiManager.WIFI_AP_STATE_ENABLING, 0);
                        if (!mDeathRecipient.linkToDeath(mApInterface.asBinder())) {
                            mDeathRecipient.unlinkToDeath();
                            updateApState(WifiManager.WIFI_AP_STATE_FAILED,
                                    WifiManager.SAP_START_FAILURE_GENERAL);
                            mWifiMetrics.incrementSoftApStartResult(
                                    false, WifiManager.SAP_START_FAILURE_GENERAL);
                            break;
                        }

                        try {
                            mNetworkObserver = new NetworkObserver(mApInterface.getInterfaceName());
                            mNwService.registerObserver(mNetworkObserver);
                        } catch (RemoteException e) {
                            mDeathRecipient.unlinkToDeath();
                            unregisterObserver();
                            updateApState(WifiManager.WIFI_AP_STATE_FAILED,
                                          WifiManager.SAP_START_FAILURE_GENERAL);
                            mWifiMetrics.incrementSoftApStartResult(
                                    false, WifiManager.SAP_START_FAILURE_GENERAL);
                            break;
                        }

                        int result = startSoftAp((WifiConfiguration) message.obj);
                        if (result != SUCCESS) {
                            int failureReason = WifiManager.SAP_START_FAILURE_GENERAL;
                            if (result == ERROR_NO_CHANNEL) {
                                failureReason = WifiManager.SAP_START_FAILURE_NO_CHANNEL;
                            }
                            mDeathRecipient.unlinkToDeath();
                            unregisterObserver();
                            updateApState(WifiManager.WIFI_AP_STATE_FAILED, failureReason);
                            mWifiMetrics.incrementSoftApStartResult(false, failureReason);
                            break;
                        }

                        transitionTo(mStartedState);
                        break;

startSoftAp

    /**
     * Start a soft AP instance with the given configuration.
     * @param config AP configuration
     * @return integer result code
     */
    private int startSoftAp(WifiConfiguration config) {
        if (config == null || config.SSID == null) {
            Log.e(TAG, "Unable to start soft AP without valid configuration");
            return ERROR_GENERIC;
        }

        // Make a copy of configuration for updating AP band and channel.
        WifiConfiguration localConfig = new WifiConfiguration(config);

        int result = ApConfigUtil.updateApChannelConfig(
                mWifiNative, mCountryCode,
                mWifiApConfigStore.getAllowed2GChannel(), localConfig);
        if (result != SUCCESS) {
            Log.e(TAG, "Failed to update AP band and channel");
            return result;
        }

        // Setup country code if it is provided.
        if (mCountryCode != null) {
            // Country code is mandatory for 5GHz band, return an error if failed to set
            // country code when AP is configured for 5GHz band.
            if (!mWifiNative.setCountryCodeHal(mCountryCode.toUpperCase(Locale.ROOT))
                    && config.apBand == WifiConfiguration.AP_BAND_5GHZ) {
                Log.e(TAG, "Failed to set country code, required for setting up "
                        + "soft ap in 5GHz");
                return ERROR_GENERIC;
            }
        }

        int encryptionType = getIApInterfaceEncryptionType(localConfig);

        if (localConfig.hiddenSSID) {
            Log.d(TAG, "SoftAP is a hidden network");
        }

        try {
            // Note that localConfig.SSID is intended to be either a hex string or "double quoted".
            // However, it seems that whatever is handing us these configurations does not obey
            // this convention.
            boolean success = mApInterface.writeHostapdConfig(
                    localConfig.SSID.getBytes(StandardCharsets.UTF_8), localConfig.hiddenSSID,
                    localConfig.apChannel, encryptionType,
                    (localConfig.preSharedKey != null)
                            ? localConfig.preSharedKey.getBytes(StandardCharsets.UTF_8)
                            : new byte[0]);
            if (!success) {
                Log.e(TAG, "Failed to write hostapd configuration");
                return ERROR_GENERIC;
            }

            success = mApInterface.startHostapd();
            if (!success) {
                Log.e(TAG, "Failed to start hostapd.");
                return ERROR_GENERIC;
            }
        } catch (RemoteException e) {
            Log.e(TAG, "Exception in starting soft AP: " + e);
        }

        Log.d(TAG, "Soft AP is started");

        return SUCCESS;
    }

ap_interface_binder.cpp

binder::Status ApInterfaceBinder::writeHostapdConfig(
    const std::vector<uint8_t>& ssid,
    bool is_hidden,
    int32_t channel,
    int32_t binder_encryption_type,
    const std::vector<uint8_t>& passphrase,
    bool* out_success) {
  *out_success = false;
  if (!impl_) {
    LOG(WARNING) << "Cannot set config on dead ApInterface.";
    return binder::Status::ok();
  }

  HostapdManager::EncryptionType encryption_type;
  switch (binder_encryption_type) {
    case IApInterface::ENCRYPTION_TYPE_NONE:
      encryption_type = HostapdManager::EncryptionType::kOpen;
      break;
    case IApInterface::ENCRYPTION_TYPE_WPA:
      encryption_type = HostapdManager::EncryptionType::kWpa;
      break;
    case IApInterface::ENCRYPTION_TYPE_WPA2:
      encryption_type = HostapdManager::EncryptionType::kWpa2;
      break;
    default:
      LOG(ERROR) << "Unknown encryption type: " << binder_encryption_type;
      return binder::Status::ok();
  }

  *out_success = impl_->WriteHostapdConfig(
      ssid, is_hidden, channel, encryption_type, passphrase);

  return binder::Status::ok();
}

 

ap_interface_impl.cpp

bool ApInterfaceImpl::WriteHostapdConfig(const vector<uint8_t>& ssid,
                                         bool is_hidden,
                                         int32_t channel,
                                         EncryptionType encryption_type,
                                         const vector<uint8_t>& passphrase) {
  string config = hostapd_manager_->CreateHostapdConfig(
      interface_name_, ssid, is_hidden, channel, encryption_type, passphrase);

  if (config.empty()) {
    return false;
  }

  return hostapd_manager_->WriteHostapdConfig(config);
}

hostapd_manager.cpp

bool HostapdManager::WriteHostapdConfig(const string& config) {
  // Remove hostapd.conf because its file owner might be system
  // in previous OS and chmod fails in that case.
  RemoveFileIfExists(kHostapdConfigFilePath);
  if (!WriteStringToFile(config, kHostapdConfigFilePath,
                         S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
                         AID_WIFI, AID_WIFI)) {
    int error = errno;
    LOG(ERROR) << "Cannot write hostapd config to \""
               << kHostapdConfigFilePath << "\": " << strerror(error);
    struct stat st;
    int result = stat(kHostapdConfigFilePath, &st);
    if (result == 0) {
      LOG(ERROR) << "hostapd config file uid: "<< st.st_uid << ", gid: " << st.st_gid
                 << ", mode: " << st.st_mode;
    } else {
      LOG(ERROR) << "Error calling stat() on hostapd config file: " << strerror(errno);
    }
    return false;
  }
  return true;
}

startHostapd

ap_interface_binder.cpp
binder::Status ApInterfaceBinder::startHostapd(bool* out_success) {
  *out_success = false;
  if (!impl_) {
    LOG(WARNING) << "Cannot start hostapd on dead ApInterface.";
    return binder::Status::ok();
  }
  *out_success = impl_->StartHostapd();
  return binder::Status::ok();
}



ap_interface_impl.cpp
bool ApInterfaceImpl::StartHostapd() {
  return hostapd_manager_->StartHostapd();
}


hostapd_manager.cpp
const char kHostapdServiceName[] = "hostapd";

bool HostapdManager::StartHostapd() {
  if (property_set("ctl.start", kHostapdServiceName) != 0) {
    LOG(ERROR) << "Failed to start SoftAP";
    return false;
  }

  LOG(DEBUG) << "SoftAP started successfully";
  return true;
}



和supplicant类似通过ctl.start将hostapd进程启动起来。

 

2. 总结

 

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值