Android RIL 中 HIDL 和 AIDL 的区别

20 阅读5分钟

1. 历史背景

时期语言Android 版本说明
Android 7.0 - 12HIDL (HAL Interface Definition Language)Nougat - S首个现代 HAL 接口语言
Android 13+AIDL (Android Interface Definition Language)T 及以后统一的 IPC 接口语言
过渡期两者共存S/T兼容性层支持 HIDL 驱动

2. 核心架构差异

2.1 接口定义方式

HIDL(旧)- .hal 文件:

hardware_interfaces/radio/1.4/IRadio.hal
package android.hardware.radio@1.4;

interface IRadio {
    oneway dial(int32_t serial, Dial dialInfo);
    oneway hangupConnection(int32_t serial, uint32_t gsmCallNumber);
    oneway setResponseFunctions(IRadioResponse radioResponse, IRadioIndication radioIndication);
}

AIDL(新)- .aidl 文件:

hardware_interfaces/radio/aidl/android/hardware/radio/voice/IRadioVoice.aidl
package android.hardware.radio.voice;

interface IRadioVoice {
    oneway void dial(in int serial, in Dial dialInfo);
    oneway void hangupConnection(in int serial, in int gsmCallNumber);
    void setResponseFunctions(in IRadioVoiceResponse radioVoiceResponse,
                              in IRadioVoiceIndication radioVoiceIndication);
}

2.2 接口颗粒度

HIDL:单体接口

  • 一个 IRadio 接口包含所有功能(voice, data, network, messaging, sim, config)
  • 版本号递增:1.0 → 1.1 → 1.2 → ... → 1.6
hardware_interfaces/radio/1.0/IRadio.hal    (2000+ 行)
    ├─ Voice 功能
    ├─ Data 功能
    ├─ Network 功能
    ├─ Messaging 功能
    ├─ SIM 功能
    └─ Config 功能

AIDL:模块化接口

  • 按功能域分离成多个接口
  • 每个模块独立版本控制
hardware_interfaces/radio/aidl/android/hardware/radio/
├─ voice/IRadioVoice.aidl
├─ data/IRadioData.aidl
├─ network/IRadioNetwork.aidl
├─ messaging/IRadioMessaging.aidl
├─ sim/IRadioSim.aidl
├─ modem/IRadioModem.aidl
└─ config/IRadioConfig.aidl

3. 响应和指示机制

3.1 HIDL 响应流程

Framework (Java)
    │
    ├─ setResponseFunctions(IRadioResponse, IRadioIndication)
    │
RIL (JNI/C++)
    │
    ├─ IRadio@1.4::dial()
    │
    └─ IRadioResponse@1.4::dialResponse()
       IRadioIndication@1.4::callStateChanged()

响应和指示通过同一对接口处理:

44:60:hardware_interfaces/radio/1.0/IRadio.hal
interface IRadio {
    setResponseFunctions(IRadioResponse radioResponse, IRadioIndication radioIndication);
    oneway dial(int32_t serial, Dial dialInfo);
    // ...
}

interface IRadioResponse {
    dialResponse(RadioResponseInfo info);
}

interface IRadioIndication {
    callStateChanged(RadioIndicationType type);
}

3.2 AIDL 响应流程

Framework (Java)
    │
    ├─ setResponseFunctions(IRadioVoiceResponse, IRadioVoiceIndication)
    │
RIL (C++)
    │
    ├─ IRadioVoice::dial()
    │
    └─ IRadioVoiceResponse::dialResponse()
       IRadioVoiceIndication::callStateChanged()

AIDL 采用分离的响应接口

hardware_interfaces/radio/aidl/android/hardware/radio/voice/IRadioVoice.aidl
interface IRadioVoice {
    void setResponseFunctions(in IRadioVoiceResponse radioVoiceResponse,
                              in IRadioVoiceIndication radioVoiceIndication);
    oneway void dial(in int serial, in Dial dialInfo);
}

interface IRadioVoiceResponse {
    oneway void dialResponse(in RadioResponseInfo info);
}

interface IRadioVoiceIndication {
    oneway void callStateChanged(in RadioIndicationType type);
}

4. 数据结构定义

4.1 HIDL - 复杂的继承体系

hardware_interfaces/radio/1.0/types.hal
struct Dial {
    string address;
    Clir clir;
    vec<UusInfo> uusInfo;
};

struct RadioResponseInfo {
    RadioResponseType type;
    int32_t serial;
    RadioError error;
};

HIDL 支持联合(union)和层级继承。

4.2 AIDL - 扁平的数据结构

hardware_interfaces/radio/aidl/android/hardware/radio/voice/Dial.aidl
package android.hardware.radio.voice;
parcelable Dial {
    String address;
    int clir;
    UusInfo[] uusInfo;
}

hardware_interfaces/radio/aidl/android/hardware/radio/RadioResponseInfo.aidl
package android.hardware.radio;
parcelable RadioResponseInfo {
    RadioResponseType type;
    int serial;
    RadioError error;
}

AIDL 使用 parcelable 而非 struct

5. RIL Java 层的适配

RIL 框架通过代理类适配两种接口:

53:100:frameworks_opt_telephony/src/java/com/android/internal/telephony/RadioServiceProxy.java
/**
 * A holder for IRadio services.
 * Use getHidl to get the HIDL IRadio service or getAidl to get the corresponding AIDL service.
 */
public abstract class RadioServiceProxy {
    boolean mIsAidl;                                    // 标志:是否为 AIDL
    HalVersion mHalVersion = RIL.RADIO_HAL_VERSION_UNKNOWN;
    volatile android.hardware.radio.V1_4.IRadio mRadioProxy = null;

    /**
     * Set IRadio as the HIDL implementation for RadioServiceProxy
     */
    public void setHidl(HalVersion halVersion, android.hardware.radio.V1_4.IRadio radio) {
        mHalVersion = halVersion;
        mRadioProxy = radio;
        mIsAidl = false;
    }

    /**
     * Set IRadio as the AIDL implementation for RadioServiceProxy
     */
    public void setAidl(android.hardware.radio.IRadio radioAidl) {
        mAidlRadioProxy = radioAidl;
        mIsAidl = true;
    }

    public boolean isAidl() {
        return mIsAidl;
    }
}

6. 兼容性层:libradiocompat

Android 13 引入了兼容性层,允许在 AIDL 框架中使用旧的 HIDL HAL 实现。

6.1 架构

         Framework (AIDL)
               │
     ┌─────────┴─────────┐
     │                   │
  AIDL HAL          libradiocompat
  (Native)          (Converter)
                        │
                   HIDL HAL (Legacy)

6.2 数据结构转换

libradiocompat 提供了双向转换函数:

19:45:hardware_interfaces/radio/aidl/compat/libradiocompat/commonStructs.cpp
namespace android::hardware::radio::compat {

// HIDL to AIDL conversion
aidl::RadioResponseInfo toAidl(const V1_0::RadioResponseInfo& info) {
    return {
            .type = toAidl(info.type),
            .serial = info.serial,
            .error = toAidl(info.error),
    };
}

// AIDL to HIDL conversion
V1_0::RadioCapability toHidl(const aidl::RadioCapability& capa) {
    return {
            .session = capa.session,
            .phase = static_cast<V1_0::RadioCapabilityPhase>(capa.phase),
            .raf = toHidlBitfield<V1_0::RadioAccessFamily>(capa.raf),
            .logicalModemUuid = capa.logicalModemUuid,
            .status = static_cast<V1_0::RadioCapabilityStatus>(capa.status),
    };
}

}

6.3 集合转换

支持向量和数组的自动转换:

23:56:hardware_interfaces/radio/aidl/compat/libradiocompat/collections.h
template <typename T>
auto toAidl(const hidl_vec<T>& inp) {
    std::vector<decltype(toAidl(T{}))> out(inp.size());
    for (size_t i = 0; i < inp.size(); i++) {
        out[i] = toAidl(inp[i]);
    }
    return out;
}

template <typename T>
auto toHidl(const std::vector<T>& inp) {
    hidl_vec<decltype(toHidl(T{}))> out(inp.size());
    for (size_t i = 0; i < inp.size(); i++) {
        out[i] = toHidl(inp[i]);
    }
    return out;
}

7. 关键差异对比表

特性HIDLAIDL
引入时间Android 7.0 (Nougat)Android 13 (Tiramisu)
定义文件.hal.aidl
接口粒度单体(IRadio 包含所有)模块化(IRadioVoice, IRadioData 等)
版本管理整体版本(1.0-1.6)按模块版本(各模块独立)
类型系统复杂继承体系简洁的 parcelable 类型
代码生成HIDL 编译器AIDL 编译器
二进制兼容性使用 HIDL 运行时使用 Binder
兼容性支持原生支持 HIDL通过 libradiocompat
性能特征针对 HAL 优化通用 IPC 优化

8. 版本管理对比

HIDL 版本演进:

android.hardware.radio@1.0::IRadio
    ├─ dial()
    ├─ hangupConnection()
    └─ ...

android.hardware.radio@1.1::IRadio extends @1.0::IRadio
    └─ setCarrierInfoForImsiEncryption()  (新增)

android.hardware.radio@1.2::IRadio extends @1.1::IRadio
    └─ startNetworkScan()                 (新增)

...

android.hardware.radio@1.6::IRadio extends @1.5::IRadio
    └─ setSimCardPower()                  (新增)

AIDL 模块化版本:

android.hardware.radio.voice@1::IRadioVoice
    ├─ dial()
    ├─ hangupConnection()
    └─ ...

android.hardware.radio.data@1::IRadioData
    ├─ setupDataCall()
    ├─ deactivateDataCall()
    └─ ...

android.hardware.radio.sim@1::IRadioSim
    ├─ getIccCardStatus()
    ├─ supplyIccPin()
    └─ ...

9. 实际通信流程

9.1 HIDL 请求/响应

┌─────────────────┐
│ RIL (Java/JNI)  │
└────────┬────────┘
         │ 1. mRadioProxy.dial(serial, dialInfo)
         ▼
┌─────────────────────────────────┐
│ HIDL Service (radio@1.4::IRadio)│ (Native HAL)
└────────┬────────────────────────┘
         │ 2. 内部处理
         │ 3. 调用响应回调
         ▼
┌──────────────────────────────────┐
│ HIDL Callback (IRadioResponse)    │
└────────┬─────────────────────────┘
         │ 4. response->dialResponse(responseInfo)
         ▼
┌─────────────────────┐
│ RIL Callback Handler│
└─────────────────────┘

9.2 AIDL 请求/响应

┌─────────────────┐
│ RIL (Java/JNI)  │
└────────┬────────┘
         │ 1. mRadioProxy.dial(serial, dialInfo)
         ▼
┌─────────────────────────────────┐
│ AIDL Service (IRadioVoice)       │ (Native HAL or Compat Layer)
└────────┬────────────────────────┘
         │ 2. 内部处理
         │ 3. 调用响应回调
         ▼
┌──────────────────────────────────┐
│ AIDL Callback (IRadioVoiceResponse)
└────────┬─────────────────────────┘
         │ 4. response->dialResponse(responseInfo)
         ▼
┌─────────────────────┐
│ RIL Callback Handler│
└─────────────────────┘

10. 构建系统差异

HIDL 编译:

hidl_interface {
    name: "android.hardware.radio",
    root: "android.hardware",
    srcs: [
        "1.4/IRadio.hal",
        "1.4/IRadioResponse.hal",
        "1.4/IRadioIndication.hal",
        "1.4/types.hal",
    ],
    interfaces: [
        "android.hardware.base@1.0",
    ],
}

AIDL 编译:

aidl_interface {
    name: "android.hardware.radio",
    vendor_available: true,
    srcs: [
        "android/hardware/radio/voice/*.aidl",
        "android/hardware/radio/data/*.aidl",
        "android/hardware/radio/network/*.aidl",
        "android/hardware/radio/sim/*.aidl",
        "android/hardware/radio/modem/*.aidl",
        "android/hardware/radio/messaging/*.aidl",
    ],
    stability: "vintf",
    backend: {
        cpp: { enabled: true; },
        java: { enabled: true; },
    },
    versions_with_info: [
        { version: "1"; },
        { version: "2"; },
        { version: "3"; },
    ],
    frozen: true,
}

11. 性能和稳定性考量

方面HIDLAIDL
内存占用较小(C++ 优化)相同或稍大
IPC 延迟优化的 Binder 使用标准 Binder 延迟
类型安全强类型检查强类型检查
向后兼容通过继承链通过版本管理
热修复困难(版本锁定)更容易(模块独立)

12. 迁移建议

从 HIDL 迁移到 AIDL 的好处:

  1. 模块化 - 各功能模块独立演进
  2. 统一 IPC - 不再有特殊的 HAL IPC 机制
  3. 灵活版本管理 - 每个模块独立版本
  4. 更好的工具 - 统一使用 AIDL 工具链
  5. 长期支持 - AIDL 是未来方向

兼容性策略:

  • Android 13-14:HIDL 和 AIDL 并存,通过 libradiocompat 支持旧 HAL
  • Android 15+:可能逐步淘汰 HIDL 支持

总结来说,HIDL 是针对 HAL 的专用接口语言,而 AIDL 是通用的系统服务接口语言。RIL 从 HIDL 迁移到 AIDL 反映了 Android 系统架构向更统一、模块化方向的演进。

有任何关于 HIDL/AIDL 在 RIL 中的实现细节的问题吗?