探索hidl-gen的使用以及以wifi enable为实例

0. 前言

之前在上一个文档【Android R wifi 状态机消息处理机制以及状态切换流程分析】中提到,当打开wifi时,会启动vendor hal 以及wpasupplicant。但是没有继续追下去,因为再往后就设计到hardware层。

//WifiNative.java
public String setupInterfaceForClientInScanMode(
        @NonNull InterfaceCallback interfaceCallback) {
    synchronized (mLock) {
        //启动vendor HAL
        if (!startHal()) {
            Log.e(TAG, "Failed to start Hal");
            mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal();
            return null;
        }
//WifiNative.java
/** 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;
    }
}
//WifiVendorHal.java
/**
 * Bring up the HIDL Vendor HAL.
 * @return true on success, false otherwise.
 */
public boolean startVendorHal() {
    synchronized (sLock) {
        if (!mHalDeviceManager.start()) {
            mLog.err("Failed to start vendor HAL").flush();
            return false;
        }
        mLog.info("Vendor Hal started successfully").flush();
        return true;
    }
}


//HalDeviceManager.java
    /**
     * 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");
        initIWifiIfNecessary();
        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();
                            if (triedCount != 0) {
                                Log.d(TAG, "start IWifi succeeded after trying "
                                         + triedCount + " times");
                            }
                            return true;
                        } else if (status.code == WifiStatusCode.ERROR_NOT_AVAILABLE) {
                            // Should retry. Hal might still be stopping.
                            Log.e(TAG, "Cannot start IWifi: " + statusString(status)
                                    + ", Retrying...");
                            try {
                                Thread.sleep(START_HAL_RETRY_INTERVAL_MS);
                            } catch (InterruptedException ignore) {
                                // no-op
                            }
                            triedCount++;
                        } else {
                            // Should not retry on other failures.
                            Log.e(TAG, "Cannot start IWifi: " + statusString(status));
                            return false;
                        }
                    }
                    Log.e(TAG, "Cannot start IWifi after trying " + triedCount + " times");
                    return false;
                }
            } catch (RemoteException e) {
                Log.e(TAG, "startWifi exception: " + e);
                return false;
            }
        }
    }

最后执行的是mWifi.start。

private IWifi mWifi;

//在看一下导包
import android.hardware.wifi.V1_0.IWifi; //就是这个
import android.hardware.wifi.V1_0.IWifiApIface;
import android.hardware.wifi.V1_0.IWifiChip;
import android.hardware.wifi.V1_0.IWifiChipEventCallback;
import android.hardware.wifi.V1_0.IWifiEventCallback;
import android.hardware.wifi.V1_0.IWifiIface;
import android.hardware.wifi.V1_0.IWifiNanIface;
import android.hardware.wifi.V1_0.IWifiP2pIface;
import android.hardware.wifi.V1_0.IWifiRttController;
import android.hardware.wifi.V1_0.IWifiStaIface;
import android.hardware.wifi.V1_0.IfaceType;
import android.hardware.wifi.V1_0.WifiDebugRingBufferStatus;
import android.hardware.wifi.V1_0.WifiStatus;
import android.hardware.wifi.V1_0.WifiStatusCode;

到了这个地方,就可以全局搜代码find -iname IWifi.*,所以IWifi对应的服务端就是hardware/interface下面的IWifi.java。

hidl的功能就是将c++语言中的api 提供统一的接口给Java层调用。

那IWifi.java对应的c++文件在哪里呢?

1. hidl-gen工具

1.1 工具介绍

系统定义的所有的.hal接口,都是通过hidl-gen工具转换成对应的代码。hidl-gen源码路径:system/tools/hidl,是在ubuntu上可执行的二进制文件。

使用方法:hidl-gen -o output-path -L language (-r interface-root) fqname

例子:

hidl-gen -o hardware/interfaces/wifi/1.0/ -Lc++-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.wifi@1.0

参数说明:

  • -L: 语言类型,包括c++, c++-headers, c++-sources, export-header, c++-impl, java, java-constants, vts, makefile, androidbp, androidbp-impl, hash等。hidl-gen可根据传入的语言类型产生不同的文件。
  • fqname: 完全限定名称的输入文件。比如android.hardware.wifi@1.0,要求在源码目录下必须有hardware/interfaces/ wifi/1.0/目录。对于单个文件来说,格式如下:package@version::fileName,比如android.hardware.wifi@1.0::types.Feature。对于目录来说。格式如下package@version,比如android.hardware.wifi@1.0。
  • -r: 格式package:path,可选,对fqname对应的文件来说,用来指定包名和文件所在的目录到Android系统源码根目录的路径。如果没有制定,前缀默认是:android.hardware,目录是Android源码的根目录。
  • -o:存放hidl-gen产生的中间文件的路径。

可以使用hidl-gen 查看帮助:

1.2 准备工作

  1. 整一套源码,Android O或者Android P的
  2. 保证全套代码已经全编译,原生代码全编译命令
  3. hidl-gen工具已经安装,安装命令:make hidl-gen

2. 解析hal


就会在相应的目录下生成out目录


当然也可以生成Android.bp、hash、headers等等,你会发现其实生成的是一模一样的,以hash为例:

cat hardware/interface/current.txt


我们在生成一下:hidl-gen -o ./ -L hash -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.wifi@1.0


你可以对比看看,发现生成的和全编时生成的是一样的,没毛病。

那现在IWifi.java对应的服务端到底是哪个呢?

3. hidl对应的服务端

我们使用hidl-gen手动生成的Wifi.cpp有5个,但是你查看时,会发现这5个文件函数都是空实现。


结合hidl是framework和vendor的桥梁,所以实现应该是由vendor实现的。我们可以搜到的1.4 wifi hal版本中有默认的实现,有一个defult目录

看一下Android.mk

###
### android.hardware.wifi static library
###
include $(CLEAR_VARS)
LOCAL_MODULE := android.hardware.wifi@1.0-service-lib
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_PROPRIETARY_MODULE := true
LOCAL_CPPFLAGS := -Wall -Werror -Wextra

# Allow implicit fallthroughs in wifi_legacy_hal.cpp until they are fixed.
LOCAL_CFLAGS += -Wno-error=implicit-fallthrough
LOCAL_SRC_FILES := 
    hidl_struct_util.cpp 
    hidl_sync_util.cpp 
    ringbuffer.cpp 
    wifi.cpp 
    wifi_ap_iface.cpp 
    wifi_chip.cpp 
    wifi_feature_flags.cpp 
    wifi_iface_util.cpp 
    wifi_legacy_hal.cpp 
    wifi_legacy_hal_stubs.cpp 
    wifi_mode_controller.cpp 
    wifi_nan_iface.cpp 
    wifi_p2p_iface.cpp 
    wifi_rtt_controller.cpp 
    wifi_sta_iface.cpp 
    wifi_status_util.cpp
LOCAL_SHARED_LIBRARIES := 
    libbase 
    libcutils 
    libhidlbase 
    liblog 
    libnl 
    libutils 
    libwifi-hal 
    libwifi-system-iface 
    android.hardware.wifi@1.0 
    android.hardware.wifi@1.1 
    android.hardware.wifi@1.2 
    android.hardware.wifi@1.3 
    android.hardware.wifi@1.4
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
include $(BUILD_STATIC_LIBRARY)

###
### android.hardware.wifi daemon
###
include $(CLEAR_VARS)
LOCAL_MODULE := android.hardware.wifi@1.0-service
LOCAL_VINTF_FRAGMENTS := android.hardware.wifi@1.0-service.xml
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_PROPRIETARY_MODULE := true
LOCAL_CPPFLAGS := -Wall -Werror -Wextra
ifeq ($(TARGET_ARCH),arm)
    LOCAL_CPPFLAGS += -DARCH_ARM_32
endif

LOCAL_SRC_FILES := 
    service.cpp
LOCAL_SHARED_LIBRARIES := 
    libbase 
    libcutils 
    libhidlbase 
    liblog 
    libnl 
    libutils 
    libhwbinder 
    libwifi-hal 
    libwifi-system-iface 
    android.hardware.wifi@1.0 
    android.hardware.wifi@1.1 
    android.hardware.wifi@1.2 
    android.hardware.wifi@1.3 
    android.hardware.wifi@1.4
LOCAL_STATIC_LIBRARIES := 
    android.hardware.wifi@1.0-service-lib
LOCAL_INIT_RC := android.hardware.wifi@1.0-service.rc
include $(BUILD_EXECUTABLE)

###
### android.hardware.wifi daemon
###
include $(CLEAR_VARS)
LOCAL_MODULE := android.hardware.wifi@1.0-service-lazy
LOCAL_VINTF_FRAGMENTS := android.hardware.wifi@1.0-service.xml
LOCAL_OVERRIDES_MODULES := android.hardware.wifi@1.0-service
LOCAL_CFLAGS := -DLAZY_SERVICE
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_PROPRIETARY_MODULE := true
LOCAL_CPPFLAGS := -Wall -Werror -Wextra
LOCAL_SRC_FILES := 
    service.cpp
LOCAL_SHARED_LIBRARIES := 
    libbase 
    libcutils 
    libhidlbase 
    liblog 
    libnl 
    libutils 
    libwifi-hal 
    libwifi-system-iface 
    android.hardware.wifi@1.0 
    android.hardware.wifi@1.1 
    android.hardware.wifi@1.2 
    android.hardware.wifi@1.3 
    android.hardware.wifi@1.4
LOCAL_STATIC_LIBRARIES := 
    android.hardware.wifi@1.0-service-lib
LOCAL_INIT_RC := android.hardware.wifi@1.0-service-lazy.rc
include $(BUILD_EXECUTABLE)

###
### android.hardware.wifi unit tests.
###
include $(CLEAR_VARS)
LOCAL_MODULE := android.hardware.wifi@1.0-service-tests
LOCAL_PROPRIETARY_MODULE := true
LOCAL_CPPFLAGS := -Wall -Werror -Wextra
LOCAL_SRC_FILES := 
    tests/hidl_struct_util_unit_tests.cpp 
    tests/main.cpp 
    tests/mock_interface_tool.cpp 
    tests/mock_wifi_feature_flags.cpp 
    tests/mock_wifi_iface_util.cpp 
    tests/mock_wifi_legacy_hal.cpp 
    tests/mock_wifi_mode_controller.cpp 
    tests/ringbuffer_unit_tests.cpp 
    tests/wifi_nan_iface_unit_tests.cpp 
    tests/wifi_chip_unit_tests.cpp 
    tests/wifi_iface_util_unit_tests.cpp
LOCAL_STATIC_LIBRARIES := 
    libgmock 
    libgtest 
    android.hardware.wifi@1.0 
    android.hardware.wifi@1.1 
    android.hardware.wifi@1.2 
    android.hardware.wifi@1.3 
    android.hardware.wifi@1.4 
    android.hardware.wifi@1.0-service-lib
LOCAL_SHARED_LIBRARIES := 
    libbase 
    libcutils 
    libhidlbase 
    liblog 
    libnl 
    libutils 
    libwifi-hal 
    libwifi-system-iface
include $(BUILD_NATIVE_TEST)

到这儿就很明显了,就是这儿进行了配置,加载了1.0/1.1/1.2/1.3/1.4的库,编译生成了android.hardware.wifi@1.0-service

那么对应的服务端就是这个default目录下面的wifi.cpp

4. 以qcom平台为例


平台的boradconfig.mk中会定义这个宏控制,比如高通

wifi_initialize就对应着以下的log

07-27 11:41:42.247 I/WifiHAL (  850): Initializing wifi
07-27 11:41:42.247 I/CLD80211(  850): android.hardware.wifi@1.0-service: initialized exit socket pair
07-27 11:41:42.247 I/CLD80211(  850): android.hardware.wifi@1.0-service: nlctrl family id: 16 group: host_logs mcast_id: 20
07-27 11:41:42.247 I/CLD80211(  850): android.hardware.wifi@1.0-service: nlctrl family id: 16 group: fw_logs mcast_id: 21
07-27 11:41:42.247 I/CLD80211(  850): android.hardware.wifi@1.0-service: nlctrl family id: 16 group: per_pkt_stats mcast_id: 22
07-27 11:41:42.247 I/CLD80211(  850): android.hardware.wifi@1.0-service: nlctrl family id: 16 group: diag_events mcast_id: 23
07-27 11:41:42.248 I/CLD80211(  850): android.hardware.wifi@1.0-service: nlctrl family id: 16 group: fatal_events mcast_id: 24
07-27 11:41:42.248 I/CLD80211(  850): android.hardware.wifi@1.0-service: nlctrl family id: 16 group: oem_msgs mcast_id: 25
07-27 11:41:42.248 V/WifiHAL (  850): WifiVendorCommand 0x7ff681bb60 created vendor_id:0x1374 subcmd:38
07-27 11:41:42.248 V/WifiHAL (  850): Got a Wi-Fi HAL module message from Driver
07-27 11:41:42.248 V/WifiHAL (  850): Supported feature set : 44e9bddf
07-27 11:41:42.248 V/WifiHAL (  850): WifiVendorCommand 0x7ff681bd38 created vendor_id:0x1374 subcmd:55

07-27 11:41:42.248 V/WifiHAL (  850): Got a Wi-Fi HAL module message from Driver
07-27 11:41:42.248 V/WifiHAL (  850): WifiVendorCommand 0xb400007cd29235f0 created vendor_id:0x1374 subcmd:76
07-27 11:41:42.248 V/WifiHAL (  850): create: mVendor_id = 4980, Subcmd = 76.

07-27 11:41:42.248 V/WifiHAL (  850): WifiVendorCommand 0xb400007cd29235f0 created vendor_id:0x1374 subcmd:61
07-27 11:41:42.248 V/WifiHAL (  850): create: mVendor_id = 4980, Subcmd = 61.
uffer_size:384
07-27 11:41:42.249 V/WifiHAL (  850): handleResponse: WLAN Firmware version : FW:3.2.2.0.474.0 HW:HW_VERSION=400c0000. 
07-27 11:41:42.249 V/WifiHAL (  850): wifi_initialize: hardware version type 2
07-27 11:41:42.249 V/WifiHAL (  850): WifiVendorCommand 0x7ff681bd38 created vendor_id:0x1374 subcmd:84
07-27 11:41:42.249 V/WifiHAL (  850): Got a Wi-Fi HAL module message from Driver
07-27 11:41:42.249 V/WifiHAL (  850): Max BUS size Supported: 1848
07-27 11:41:42.249 E/WifiHAL (  850): wifi_get_capabilities: GSCAN is not supported by driver
07-27 11:41:42.249 E/WifiHAL (  850): Failed to get wifi Capabilities, error: -3
07-27 11:41:42.249 V/WifiHAL (  850): Initializing Gscan Event Handlers
07-27 11:41:42.249 V/WifiHAL (  850): WifiVendorCommand 0xb400007d0291efd0 created vendor_id:0x1374 subcmd:174
07-27 11:41:42.249 V/WifiHAL (  850): Added event handler 0x7ec332aaf0 for vendor 0x1374, subcmd 0xae and arg 0xb400007d0291efd0
07-27 11:41:42.249 D/WifiHAL (  850): wlan_service_read_sys_param: /proc/sys/net/ipv4/tcp_limit_output_bytes 262144
07-27 11:41:42.249 D/WifiHAL (  850): wlan_service_read_sys_param: /proc/sys/net/ipv4/tcp_adv_win_scale 1
07-27 11:41:42.249 V/WifiHAL (  850): Initialized Wifi HAL Successfully; vendor cmd = 103 Supported features : 44e9bddf
07-27 11:41:42.249 I/LOWI-9.0.0.38( 1306): [LOWI-Scan] WipsGetSupportedChannels: return err = 0 num_2g_ch = 13 num_5g_ch = 25 num_6g_ch = 0
07-27 11:41:42.249 I/LOWI-9.0.0.38( 1306): [LOWIWifiDriverUtils] set the band mask from wiphy 3
07-27 11:41:42.249 V/WifiHAL (  850): support_nan_ext_cmd is 1
07-27 11:41:42.249 D/android.hardware.wifi@1.0-service(  850): Starting legacy HAL event loop
07-27 11:41:42.250 I/android.hardware.wifi@1.0-service(  850): Adding interface handle for wifi-aware0
07-27 11:41:42.250 I/android.hardware.wifi@1.0-service(  850): Adding interface handle for wlan0
07-27 11:41:42.250 I/android.hardware.wifi@1.0-service(  850): Adding interface handle for p2p0
07-27 11:41:42.250 D/android.hardware.wifi@1.0-service(  850): Legacy HAL start complete
07-27 11:41:42.250 W/android.hardware.wifi@1.0-service(  850): No active wlan interfaces in use! Using default
07-27 11:41:42.250 V/WifiHAL (  850): WifiVendorCommand 0xb400007cb292fef0 created vendor_id:0x1374 subcmd:165
07-27 11:41:42.250 V/WifiHAL (  850): WifiVendorCommand 0xb400007cd29235f0 created vendor_id:0x1374 subcmd:165
07-27 11:41:42.250 V/WifiHAL (  850): Added event handler 0x7ec332aaf0 for vendor 0x1374, subcmd 0xa5 and arg 0xb400007cd29235f0
07-27 11:41:42.250 V/WifiHAL (  850): WifiVendorCommand 0xb400007cd2924cb0 created vendor_id:0x1374 subcmd:61
07-27 11:41:42.250 V/WifiHAL (  850): create: mVendor_id = 4980, Subcmd = 61.
07-27 11:41:42.250 V/WifiHAL (  850): handleResponse: WLAN Driver version : 5.2.022.2J 
07-27 11:41:42.250 V/WifiHAL (  850): WifiVendorCommand 0xb400007cd2924cb0 created vendor_id:0x1374 subcmd:61
07-27 11:41:42.250 V/WifiHAL (  850): create: mVendor_id = 4980, Subcmd = 61.
07-27 11:41:42.250 V/WifiHAL (  850): handleResponse: WLAN Firmware version : FW:3.2.2.0.474.0 HW:HW_VERSION=400c0000. 
07-27 11:41:42.250 W/android.hardware.wifi@1.0-service(  850): No active wlan interfaces in use! Using default
07-27 11:41:42.252 I/android.hardware.wifi@1.0-service(  850): Configured chip in mode 3
07-27 11:41:42.252 W/android.hardware.wifi@1.0-service(  850): No active wlan interfaces in use! Using default
07-27 11:41:42.252 I/CLD80211( 1306): lowi-server: initialized exit socket pair

这边可以对着log,继续追下去。我们继续回到开始的地方。

5. createStaIface

到了IWifiChip.configureChip后会,按照之前讲解的使用hidl-gen来解析找到服务端,这里不演示了。

服务端为hardware/interfaces/wifi/1.4/default/wifi_chip.cpp


我们用opengropk搜一下


我们的项目并没有使用这个宏,那wifi驱动到底在何处被加载的?

我们项目是在init.target.rc里加载驱动的。

总结

此篇主要就是使用hidl-gen工具来查询hal对应的服务端c++代码,以及wifi enable的从framework到HAL,再到驱动的一个逻辑流程。(R版本)

剑气纵横三万里

“为什么要努力?” “想去的地方很远,想要的东西很贵,喜欢的人很优秀,父母的白发,朋友的约定,周围人的嘲笑,以及,天生傲骨。”

留下你的评论

*评论支持代码高亮<pre class="prettyprint linenums">代码</pre>

相关推荐