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已经启动成功了。

 

每个属性都有一个名称和值,他们都是字符串格式。属性被大量使用在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.<服务名>“属性中 。客户端应用程序可以轮询那个属性值,以确定结果。

猜你喜欢

转载自www.cnblogs.com/nextbug/p/12303634.html
今日推荐