前言:之前在(七十一)Android O WiFi热点 开启流程梳理 梳理到了WifiStateMachine就没梳理得下去了,现在继续梳理下面流程。
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 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 to indicate the status and the associated wificond
* client interface binder handler (will be null on failure).
*/
public Pair 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 to indicate the status and the associated wificond
* AP interface binder handler (will be null on failure).
*/
public Pair 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
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 statusResp = new Mutable<>();
Mutable 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 WifiChip::createApIface(createApIface_cb hidl_status_cb) {
return validateAndCall(this,
WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
&WifiChip::createApIfaceInternal,
hidl_status_cb);
}
std::pair> 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)
: ifname_(ifname), legacy_hal_(legacy_hal), is_valid_(true) {}
/**
* 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* created_interface) {
InterfaceInfo interface;
if (!SetupInterface(&interface)) {
return Status::ok(); // Logging was done internally
}
unique_ptr 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));
}
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& ssid,
bool is_hidden,
int32_t channel,
int32_t binder_encryption_type,
const std::vector& 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& ssid,
bool is_hidden,
int32_t channel,
EncryptionType encryption_type,
const vector& 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进程启动起来。