在 Android 8.0 中绕过 hwbinder 实现跨模块对 audio HAL 调用

移动开发 waitig 1015℃ 百度已收录 0评论

在 Android 8.0 中绕过 hwbinder 实现跨模块对 audio HAL 调用

Qidi 2017.10.20 (Markdown & Haroopad)


【需求描述】

  Audio 模块中专门为 TV 产品添加了一些代码,需要在 hdmi 的 HAL 代码中进行调用以完成某些功能。


【旧的实现】

  在 Android 7.1 中的做法是在 hdmi 的 HAL 层链接上 audio 的 .so 库,然后在代码里直接调用 audio 的函数接口实现相应的操作


【碰到的问题】

  audio 模块中为 TV 产品添加的代码中含有对音频设备节点的操作,而 Android 8.0 对权限的要求更加严格了,audio 的设备节点只可由 audio HAL 来进行操作。这一点可以从 system/sepolicy/public/hal_audio.te 文件中的如下语句看出:

# Only audio HAL may directly access the audio hardware
neverallow { halserverdomain -hal_audio_server } audio_device:chr_file *;

【解决方法】

  首先将 hdmi HAL 要调用的 audio 接口函数所在的 .so 链接到最基本的 lib.primay.amlogic.so 中(其它平台上这个 .so 文件的名字也可能是别的,比如 audio.primary.default.so)。
  然后在 hdmi HAL 里通过 AudioSystem::setParameters() 函数调用来向 audio HAL 发送一个自定义的音频参数,比如 tvAudio=44100(如果是调用其它模块的接口函数或对文件节点进行操作,那么应该使用其它模块对应的 service 对象,而不应该再是 AudioSystem)。示例代码如下:

static int tv_audio_open(char *sample_rate)
{
    ALOGD("Qidi - use AudioSystem::setParameters() to open amaudio function.");
    AudioParameter param = AudioParameter();
    String8 value = String8(sample_rate);
    String8 key = String8("tvAudio");
    param.add(key, value);
    String8 keyValuePairs = param.toString();
    if ( AudioSystem::setParameters(AUDIO_IO_HANDLE_NONE, keyValuePairs) == NO_ERROR ) {
        ALOGD("Qidi - tv_hal set amaudio parameter successfully.");
        return 0;
    }
    return -EINVAL;
}

static int tv_audio_close()
{
    ALOGD("Qidi - use AudioSystem::setParameters() to close amaudio function.");
    AudioParameter param = AudioParameter();
    String8 value = String8("off");
    String8 key = String8("tvAudio");
    param.add(key, value);
    String8 keyValuePairs = param.toString();
    if ( AudioSystem::setParameters(AUDIO_IO_HANDLE_NONE, keyValuePairs) == NO_ERROR ) {
        ALOGD("Qidi - tv_hal set amaudio parameter successfully.");
        return 0;
    } else {
        ALOGE("Qidi - tv_hal set amaudio parameter failed.");
        return -EINVAL;
    }
}

#define AUDIO_48k 48000

 static int tv_input_open_stream(struct tv_input_device *dev, int device_id,
                                 tv_stream_t *stream)
 {
     if ( dev ) {
         if (get_hdmi_stream(stream) != 0) {
             return -EINVAL;
         }
         if ( NORMAL_STREAM_ID == stream->stream_id ) {
             WriteSysfs(HDMI_ENABLE_SYSFS, HDMI_ENABLE);
            if (tv_audio_open(AUDIO_48k) == 0) {
                ALOGD("Qidi - tv_audio_open() is called successfully!\n");
                return 0;
            }
         }
     }
    ALOGE("Qidi - tv_hal set amaudio parameter failed.");
     return -EINVAL;
 }
 static int tv_input_close_stream(struct tv_input_device *dev, int device_id,
                                  int stream_id)
 {
     if ( dev ) {
         if ( NORMAL_STREAM_ID == stream_id ) {
            if (tv_audio_close() != 0)
                return -EINVAL;
             WriteSysfs(HDMI_ENABLE_SYSFS, HDMI_DISABLE);
             return 0;
         }
    ......
}

  最后在 audio HAL 中添加上对相应音频参数的处理逻辑即可。如下方代码所示:

#if 1
    // handle tvAudio invoke request from hdmi HAL in the method of
    // AudioSystem::setParameters()
    int sr_value = 0;
    char *end;
    ret = str_parms_get_str(parms, "tvAudio", value, sizeof(value));
    if (ret >= 0) {
        ALOGD("Qidi - %s() is handling tvAudio parameter: amaudio = %s",
            __FUNCTION__, value);
        if (strcmp(value, AUDIO_PARAMETER_VALUE_OFF) == 0) {
            tvAudioClose();
        } else {
            if (str_parms_get_int(parms, "tvAudio", &sr_value)) {
                ALOGE("Qidi - get tvAudio sample_rate failed!\n");
                return 0;
            }
            if (sr_value >= 8000 && sr_value <= 48000) {
                tvAudioOpen((unsigned int)sr_value,
                    CC_IN_USE_SPDIF_DEVICE, CC_OUT_USE_ALSA);
            } else
                ALOGE("Qidi - tvAudio sample_rate invalid!\n");
        }
    }
#endif

  通过这种方式,去操作音频设备节点的对象从原来的 hdmi HAL 变成了 audio HAL,规避了没有操作权限的问题。


本文由【waitig】发表在等英博客
本文固定链接:在 Android 8.0 中绕过 hwbinder 实现跨模块对 audio HAL 调用
欢迎关注本站官方公众号,每日都有干货分享!
等英博客官方公众号
点赞 (0)分享 (0)