专栏首页程序猿的那点事Android HIDL机制学习

Android HIDL机制学习

前言:

在Android O之前,HAL是一个个的.so库,通过dlopen来进行打开,库和framework位于同一个进程。如下图所示:

在Android O之后,framework和hal运行于不同的进程,所有的HAL采用新的HIDL技术来完成。

一、HIDL简单介绍

HIDL是Android8.0新出的一个技能,以service和client的方式实现hal接口,目的是想使Android系统和BSP解绑,使系统升级更加方便。HIDL的使用方法一般是先提供.hal文件,然后使用hidl-gen工具生成 框架源文件和Android.bp编译工具文件,之后填充生成的源文件和定制Android.bp编译文件 官方介绍

二、以WiFi获取 MacAddress 为例看一下谷歌的实现

这是一个完整的 HIDL 接口的实现: /frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java

/**
 * Makes a callback to HIDL to getMacAddress from supplicant
 *
 * @param ifaceName Name of the interface.
 * @return string containing the MAC address, or null on a failed call
 */
public String getMacAddress(@NonNull String ifaceName) {
    return mSupplicantStaIfaceHal.getMacAddress(ifaceName);
}

/frameworks/opt/net/wifi/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java

/**
 * Makes a callback to HIDL to getMacAddress from supplicant
 *
 * @param ifaceName Name of the interface.
 * @return string containing the MAC address, or null on a failed call
 */
public String getMacAddress(@NonNull String ifaceName) {
    synchronized (mLock) {
        final String methodStr = "getMacAddress";
        ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
        if (iface == null) return null;
        Mutable<String> gotMac = new Mutable<>();
        try {
            iface.getMacAddress((SupplicantStatus status,
                    byte[/* 6 */] macAddr) -> {
                if (checkStatusAndLogFailure(status, methodStr)) {
                    gotMac.value = NativeUtil.macAddressFromByteArray(macAddr);
                }
            });
        } catch (RemoteException e) {
            handleRemoteException(e, methodStr);
        }
        return gotMac.value;
    }
}

/hardware/interfaces/wifi/supplicant/1.0/ISupplicantStaIface.hal

/**
 * Send driver command to get MAC address of the device.
 *
 * @return status Status of the operation.
 *         Possible status codes:
 *         |SupplicantStatusCode.SUCCESS|,
 *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
 *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
 * @return macAddr MAC address of the device.
 */
getMacAddress()
    generates (SupplicantStatus status, MacAddress macAddr);

/external/wpa_supplicant_8/wpa_supplicant/hidl/1.0/sta_iface.cpp

Return<void> StaIface::getMacAddress(getMacAddress_cb _hidl_cb)
{
	return validateAndCall(
	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
	    &StaIface::getMacAddressInternal, _hidl_cb);
}
StaIface::getMacAddressInternal()
{
	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
	std::vector<char> cmd(
	    kGetMacAddress, kGetMacAddress + sizeof(kGetMacAddress));
	char driver_cmd_reply_buf[4096] = {};
	int ret = wpa_drv_driver_cmd(
	    wpa_s, cmd.data(), driver_cmd_reply_buf,
	    sizeof(driver_cmd_reply_buf));
	// Reply is of the format: "Macaddr = XX:XX:XX:XX:XX:XX"
	std::string reply_str = driver_cmd_reply_buf;
	if (ret < 0 || reply_str.empty() ||
	    reply_str.find("=") == std::string::npos) {
		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
	}
	// Remove all whitespace first and then split using the delimiter "=".
	reply_str.erase(
	    remove_if(reply_str.begin(), reply_str.end(), isspace),
	    reply_str.end());
	std::string mac_addr_str =
	    reply_str.substr(reply_str.find("=") + 1, reply_str.size());
	std::array<uint8_t, 6> mac_addr;
	if (hwaddr_aton(mac_addr_str.c_str(), mac_addr.data())) {
		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
	}
	return {{SupplicantStatusCode::SUCCESS, ""}, mac_addr};
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • RTS与CTS协议学习

    RTS,CTS------请求发送/清除发送,用于半双工时的收发切换,属于辅助流控信号。半双工的意思是说,发的时候不收,收的时候不发。那么怎么区分收发呢?缺省时...

    用户7557625
  • Android蓝牙通话管理机制

    前言:最近遇到一个需求,就是在车载系统上写一个APP,需要控制手机上的通话。之前没有接触过蓝牙,所以稍微了解了一下。 首先手机连接汽车,手机就属于服务端,车载...

    用户7557625
  • WPA-PSK四次握手

    WPA2-PSK,AP/STA在4-wayshake前各自都知道密码(也就是用户连接某SSID输入的密码)

    用户7557625
  • Qt 模拟 HTTP 表单提交文字或文件到服务器

    传统通过 HTTP 表单的方式来上传文件在 Web 中实现是非常简单的,一个表单中加几个域填写上对应的内容提交就可以了,但如果通过 Qt 来实现就相对麻烦一点,...

    我与梦想有个约会
  • Objective-c 知识总结 -- 继承

    观察发现,它们属性和方法声明是相同的,都有 填充色(fillcolor)、尺寸+位置(bounds)、绘制方法;

    半纸渊
  • 我用Facebook开源神器Prophet,预测时间序列基于Python(代码+论文)

    Prophet是Facebook 开源一款基于 Python 和 R 语言的数据预测工具。Facebook 表示,Prophet 相比现有预测工具更加人性化,并...

    量化投资与机器学习微信公众号
  • Matlab上位机开发(三)波形显示(幅度和频率可调节)

    波形显示控件可以用于绘制各种波形,拖动控件到画布中即可,然后根据需要调整控件大小:

    Mculover666
  • Spring Data Mongodb 乐观锁

    提供@Version注解,用来标识版本,保存、删除等操作会验证version,不一致会抛出OptimisticLockingFailureException

    用户1177380
  • Chrome 浏览器垃圾回收机制与内存泄漏分析

    JavaScript 引擎会通过向下移动 ESP(记录当前执行状态的指针) 来销毁该函数保存在栈中的执行上下文。

    winty
  • 前端学习笔记03 js基础

    js基础( js嵌入方式、输出语句) 1 s现在的作用 1、验证表单(以前的网速慢) 2、页面特效 (PC端的网页效果) 3、移动端 (移动 web 和app)...

    企鹅号小编

扫码关注云+社区

领取腾讯云代金券