Android P WLAN 從框架層到HAL層


上一節講到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()方法調用了SupplicantManagerStartSupplicant()方法(細心一點你會發現這里的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()分別調用了HalDeviceManagerisSupported()和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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM