上一節講到WifiNative.java中setupInterfaceForClientMode()調用的幾個方法:
startHal()
startSupplicant()
WificondControl.setupInterfaceForClientMode()
SupplicantStaIfaceHal.setupIface()
WifiMonitor.startMonitoring()
下面逐一展開進行分析,這里要涉及aidl-cpp通信這一概念,也就是說客戶端是Java文件而服務是cpp文件。
繼續上一節的startSupplicant(),我們找到server.cpp文件
路徑:system/connectivity/wificond/server.cpp
//
Status Server::enableSupplicant(bool* success) {
*success = supplicant_manager_->StartSupplicant();
return Status::ok();
}
// 初始化
Server::Server(unique_ptr<InterfaceTool> if_tool,
unique_ptr<SupplicantManager> supplicant_manager,
unique_ptr<HostapdManager> hostapd_manager,
NetlinkUtils* netlink_utils,
ScanUtils* scan_utils)
: if_tool_(std::move(if_tool)),
supplicant_manager_(std::move(supplicant_manager)),
hostapd_manager_(std::move(hostapd_manager)),
netlink_utils_(netlink_utils),
scan_utils_(scan_utils) {
}
//引入
using android::wifi_system::SupplicantManager;
很明顯,server.cpp里的enableSupplicant()方法調用了SupplicantManager的StartSupplicant()方法(細心一點你會發現這里的StartSupplicant()首部是大寫的,按照書寫規范來講,明顯不是java文件)
using android::wifi_system::SupplicantManager;
對應文件:frameworks/opt/net/wifi/libwifi_system/supplicant_manager.cpp
//
const char kSupplicantInitProperty[] = "init.svc.wpa_supplicant";
const char kSupplicantServiceName[] = "wpa_supplicant";
bool SupplicantManager::StartSupplicant() {
char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
int count = 200; /* wait at most 20 seconds for completion */
const prop_info* pi;
unsigned serial = 0;
/* Check whether already running */
//查詢名稱為“init.svc.wpa_supplicant”的屬性信息,返回狀態
if (property_get(kSupplicantInitProperty, supp_status, NULL) && strcmp(supp_status, "running") == 0) { return true; } /* * Get a reference to the status property, so we can distinguish * the case where it goes stopped => running => stopped (i.e., * it start up, but fails right away) from the case in which * it starts in the stopped state and never manages to start * running at all. */
//獲得屬性狀態的引用
pi = __system_property_find(kSupplicantInitProperty); if (pi != NULL) { serial = __system_property_serial(pi); } //啟動名稱為"wpa_supplicant"的屬性服務 property_set("ctl.start", kSupplicantServiceName); sched_yield(); ... }
每個屬性都有一個名稱和值,他們都是字符串格式。屬性被大量使用在Android系統中,用來記錄系統設置或進程之間的信息交換。屬性是在整個系統中全局可見的。每個進程可以get/set屬性。
在系統初始化時,Android將分配一個共享內存區來存儲的屬性。這些是由“init”守護進程完成的,其源代碼位於:device/system/init。“init”守護進程將啟動一個屬性服務。
屬性服務在“init”守護進程中運行。每一個客戶端想要設置屬性時,必須連接屬性服務,再向其發送信息。屬性服務將會在共享內存區中修改和創建屬性。任何客戶端想獲得屬性信息,可以從共享內存直接讀取。這提高了讀取性能。客戶端應用程序可以調用libcutils中的API函數以GET/SET屬性信息。libcutils的源代碼位於:device/libs/cutils。API函數是:
int property_get(const char *key, char *value, const char *default_value);
int property_set(const char *key, const char *value);
而libcutils又調用libc中的 __system_property_xxx 函數獲得共享內存中的屬性。libc的源代碼位於:device/system/bionic。
屬性服務調用libc中的__system_property_init函數來初始化屬性系統的共享內存。當啟動屬性服務時,將從以下文件中加載默認屬性:
/default.prop
/system/build.prop
/system/default.prop
/data/local.prop
屬性將會以上述順序加載。后加載的屬性將覆蓋原先的值。這些屬性加載之后,最后加載的屬性會被保持在/data/property中。
特別屬性如果屬性名稱以“ro.”開頭,那么這個屬性被視為只讀屬性。一旦設置,屬性值不能改變。
如果屬性名稱以“persist.”開頭,當設置這個屬性時,其值也將寫入/data/property。
如果屬性名稱以“net.”開頭,當設置這個屬性時,“net.change”屬性將會自動設置,以加入到最后修改的屬性名。(這是很巧妙的。 netresolve模塊的使用這個屬性來追蹤在net.*屬性上的任何變化。)
屬性“ ctl.start ”和“ ctl.stop ”是用來啟動和停止服務。
每一項服務必須在/init.rc中定義.系統啟動時,與init守護進程將解析init.rc和啟動屬性服務。一旦收到設置“ ctl.start ”屬性的請求,屬性服務將使用該屬性值作為服務名找到該服務,啟動該服務。這項服務的啟動結果將會放入“ init.svc.<服務名>“屬性中 。客戶端應用程序可以輪詢那個屬性值,以確定結果。
下面看startHal()方法
/** Helper method invoked to start supplicant if there were no ifaces */ private boolean startHal() { synchronized (mLock) { if (!mIfaceMgr.hasAnyIface()) { if (mWifiVendorHal.isVendorHalSupported()) { if (!mWifiVendorHal.startVendorHal()) { Log.e(TAG, "Failed to start vendor HAL"); return false; } } else { Log.i(TAG, "Vendor Hal not supported, ignoring start."); } } return true; } }
isVendorHalSupported()和startVendorHal()分別調用了HalDeviceManager的isSupported()和start()方法。
路徑:frameworks/opt/net/wifi/service/java/com/android/server/wifi/HalDeviceManager.java
/**
* Returns whether the vendor HAL is supported on this device or not.
*/
public boolean isSupported() {
return isSupportedInternal();
}
/**
* Uses the IServiceManager to query if the vendor HAL is present in the VINTF for the device
* or not.
* @return true if supported, false otherwise.
*/
private boolean isSupportedInternal() {
if (VDBG) Log.d(TAG, "isSupportedInternal");
...
try {
return (mServiceManager.getTransport(IWifi.kInterfaceName, HAL_INSTANCE_NAME)
!= IServiceManager.Transport.EMPTY);
} catch (RemoteException e) {
Log.wtf(TAG, "Exception while operating on IServiceManager: " + e);
return false;
}
}
}
//引入
import android.hidl.manager.V1_0.IServiceManager;
/**
* Attempts to start Wi-Fi (using HIDL). Returns the success (true) or failure (false) or
* the start operation. Will also dispatch any registered ManagerStatusCallback.onStart() on
* success.
*
* Note: direct call to HIDL.
*/
public boolean start() {
return startWifi();
}
private boolean startWifi() {
if (VDBG) Log.d(TAG, "startWifi");
synchronized (mLock) {
try {
if (mWifi == null) {
Log.w(TAG, "startWifi called but mWifi is null!?");
return false;
} else {
int triedCount = 0;
while (triedCount <= START_HAL_RETRY_TIMES) {
WifiStatus status = mWifi.start();
if (status.code == WifiStatusCode.SUCCESS) {
initIWifiChipDebugListeners();
managerStatusListenerDispatch();
...
...
//引入
import android.hardware.wifi.V1_0.IWifi;
路徑:system/libhidl/transport/manager/1.0/IServiceManager.hal
/** * Get the transport of a service. * * @param fqName Fully-qualified interface name. * @param name Instance name. Same as in IServiceManager::add * * @return transport Transport of service if known. */ getTransport(string fqName, string name) generates (Transport transport);
對應實現
路徑:system/hwservicemanager/ServiceManager.cpp
Return<ServiceManager::Transport> ServiceManager::getTransport(const hidl_string& fqName, const hidl_string& name) { using ::android::hardware::getTransport; pid_t pid = IPCThreadState::self()->getCallingPid(); if (!mAcl.canGet(fqName, pid)) { return Transport::EMPTY; } switch (getTransport(fqName, name)) { case vintf::Transport::HWBINDER: return Transport::HWBINDER; case vintf::Transport::PASSTHROUGH: return Transport::PASSTHROUGH; case vintf::Transport::EMPTY: default: return Transport::EMPTY; } }
路徑:hardware/interfaces/wifi/1.0/IWifi.hal
/** * Perform any setup that is required to make use of the module. If the module * is already started then this must be a noop. * Must trigger |IWifiEventCallback.onStart| on success. * * @return status WifiStatus of the operation. * Possible status codes: * |WifiStatusCode.SUCCESS|, * |WifiStatusCode.NOT_AVAILABLE|, * |WifiStatusCode.UNKNOWN| */ @entry @callflow(next={"registerEventCallback", "start", "stop", "getChip"}) start() generates (WifiStatus status);
對應實現
路徑:hardware/interfaces/wifi/1.2/default/wifi.cpp
Return<void> Wifi::start(start_cb hidl_status_cb) { return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::startInternal, hidl_status_cb); } //引用 using hidl_return_util::validateAndCall;
路徑:hardware/interfaces/wifi/1.2/default/hidl_return_util.h
// Use for HIDL methods which return instance of WifiStatus and a single return // value. template <typename ObjT, typename WorkFuncT, typename ReturnT, typename... Args> Return<void> validateAndCall( ObjT* obj, WifiStatusCode status_code_if_invalid, WorkFuncT&& work, const std::function<void(const WifiStatus&, ReturnT)>& hidl_cb, Args&&... args) { const auto lock = hidl_sync_util::acquireGlobalLock(); if (obj->isValid()) { const auto& ret_pair = (obj->*work)(std::forward<Args>(args)...); const WifiStatus& status = std::get<0>(ret_pair); const auto& ret_value = std::get<1>(ret_pair); hidl_cb(status, ret_value); } else { hidl_cb(createWifiStatus(status_code_if_invalid), typename std::remove_reference<ReturnT>::type()); } return Void(); } // Use for HIDL methods which return instance of WifiStatus and 2 return // values. template <typename ObjT, typename WorkFuncT, typename ReturnT1, typename ReturnT2, typename... Args> Return<void> validateAndCall( ObjT* obj, WifiStatusCode status_code_if_invalid, WorkFuncT&& work, const std::function<void(const WifiStatus&, ReturnT1, ReturnT2)>& hidl_cb, Args&&... args) { const auto lock = hidl_sync_util::acquireGlobalLock(); if (obj->isValid()) { const auto& ret_tuple = (obj->*work)(std::forward<Args>(args)...); const WifiStatus& status = std::get<0>(ret_tuple); const auto& ret_value1 = std::get<1>(ret_tuple); const auto& ret_value2 = std::get<2>(ret_tuple); hidl_cb(status, ret_value1, ret_value2); } else { hidl_cb(createWifiStatus(status_code_if_invalid), typename std::remove_reference<ReturnT1>::type(), typename std::remove_reference<ReturnT2>::type()); } return Void(); }
下面看WificondControl.setupInterfaceForClientMode()方法
/** * Setup interface for client mode via wificond. * @return An IClientInterface as wificond client interface binder handler. * Returns null on failure. */ public IClientInterface setupInterfaceForClientMode(@NonNull String ifaceName) { ... IClientInterface clientInterface = null; try { clientInterface = mWificond.createClientInterface(ifaceName); } catch (RemoteException e1) { Log.e(TAG, "Failed to get IClientInterface due to remote exception"); return null; } ... Binder.allowBlocking(clientInterface.asBinder()); // Refresh Handlers mClientInterfaces.put(ifaceName, clientInterface); try { IWifiScannerImpl wificondScanner = clientInterface.getWifiScannerImpl(); if (wificondScanner == null) { Log.e(TAG, "Failed to get WificondScannerImpl"); return null; } mWificondScanners.put(ifaceName, wificondScanner); Binder.allowBlocking(wificondScanner.asBinder()); ScanEventHandler scanEventHandler = new ScanEventHandler(ifaceName); mScanEventHandlers.put(ifaceName, scanEventHandler); wificondScanner.subscribeScanEvents(scanEventHandler); PnoScanEventHandler pnoScanEventHandler = new PnoScanEventHandler(ifaceName); mPnoScanEventHandlers.put(ifaceName, pnoScanEventHandler); wificondScanner.subscribePnoScanEvents(pnoScanEventHandler); } catch (RemoteException e) { Log.e(TAG, "Failed to refresh wificond scanner due to remote exception"); } return clientInterface; }
路徑:system/connectivity/wificond/server.cpp
Status Server::createClientInterface(const std::string& iface_name, sp<IClientInterface>* created_interface) { InterfaceInfo interface; if (!SetupInterface(iface_name, &interface)) { return Status::ok(); // Logging was done internally } unique_ptr<ClientInterfaceImpl> client_interface(new ClientInterfaceImpl( wiphy_index_, interface.name, interface.index, interface.mac_address, if_tool_.get(), netlink_utils_, scan_utils_)); *created_interface = client_interface->GetBinder(); BroadcastClientInterfaceReady(client_interface->GetBinder()); client_interfaces_[iface_name] = std::move(client_interface); return Status::ok(); }
GetBinder()
路徑:system/connectivity/wificond/client_interface_impl.cpp
sp<android::net::wifi::IClientInterface> ClientInterfaceImpl::GetBinder() const { return binder_; } //初始化 binder_(new ClientInterfaceBinder(this))
路徑:system/connectivity/wificond/client_interface_binder.cpp
WifiMonitor.startMonitoring():這一步主要是在WifiMonitor中建立與wpa_supplicant通信的socket通道、創建一個線程接收底層事件並分發處理。這里會創建兩個socket通道與wpa_s通信,一個用於下發指令,另一個用於接收事件。成功后WifiMonitor會向WifiStateMachine發送一個代表socket通信建立成功的消息:SUP_CONNECTION_EVENT;收到這個消息就表示Wifi已經啟動成功了。
wpa_supplicant分析
鏈接:https://www.cnblogs.com/oracleloyal/p/5328897.html