Android13添加AudioControl接口

 

概述

AudioControl 模块是 Android Automotive 平台的一部分,它提供了对车载音频系统的控制接口。该模块负责管理音频路由、音量调节、音频焦点管理等功能,确保在车载环境中音频体验的流畅性和一致性。AudioControl 模块通常通过硬件抽象层(HAL)实现,与底层音频硬件通信,以执行各种音频操作。

模块架构

AudioControl 模块是基于 Android HAL 的一部分,其架构设计如下:

  • 应用层(Application Layer):车载应用程序通过 CarAudioManager 发起音频请求,例如播放媒体、语音助手等。
  • 框架层(Framework Layer):Android 框架通过 Car Audio Service 接受音频请求并将其传递到 Audio HAL。
  • 硬件抽象层(HAL)AudioControl 模块作为 HAL 的一部分,实现了 IAudioControl 接口,负责将来自框架的音频请求翻译成硬件可执行的操作。
  • 硬件层(Hardware Layer):音频硬件接收并执行 HAL 提供的指令,实现实际的音频输出和控制。

IAudioControl 接口

IAudioControl 接口是 AudioControl 模块的核心接口,它定义了一系列方法来控制和管理车载音频。该接口通常通过 AIDL(Android Interface Definition Language)或 HIDL(HAL Interface Definition Language)定义。以下是一些常见的方法:

  • onAudioFocusChange(int usage, int zoneId, int focusChange):处理音频焦点的变化。音频焦点用于管理不同音频源之间的优先级和混音策略。
  • onDevicesToMuteChange(MutingInfo[] mutingInfos):静音或取消静音特定音频设备,例如在导航提示或警报音播放时静音媒体音频。
  • onDevicesToDuckChange(DuckingInfo[] duckingInfos):在某些特定事件发生时(如导航提示、电话来电等),对特定音频设备(如音乐播放设备)进行音量降低的操作。
  • setBalanceTowardRight(float balance):设置左右声道的平衡。
  • setFadeTowardFront(float fade):设置前后声场的淡入淡出。

这些接口方法通常是 oneway 的,这意味着它们是异步的,不会阻塞调用线程。具体的实现由 HAL 驱动和车载音频硬件共同完成。

功能和特点

AudioControl 模块的功能特点包括:

  • 音频路由控制:根据音频类型和车载环境动态路由音频信号到正确的输出设备,例如将导航提示音发送到驾驶座的扬声器,而不是后座。
  • 音频焦点管理:管理多个音频源的焦点请求和冲突,以确保重要的音频内容不会被其他音频打断。
  • 设备静音和音量控制:提供对车载音频设备的静音和音量控制,以适应不同的驾驶场景和用户偏好。
  • 自定义音频策略:支持车载厂商和应用开发者定义和实现自定义音频策略,以满足特定车辆或市场的需求。

目录结构

hardware/interfaces/automotive/audiocontrol/
├── 1.0
├── 2.0
└── aidl
    ├── aidl_api
    │   └── android.hardware.automotive.audiocontrol
    │       ├── 1
    │       ├── 2
    │       └── current
    ├── android
    ├── Android.bp
    ├── default
    └── vts

Android13 使用的是 AIDL, 没有使用 1.02.0 版本的 HIDL

  • AIDL 文件定义IAudioControl.aidl 文件定义了 HAL 接口的规范,位于 hardware/interfaces/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/ 目录下。

添加接口

diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioControl.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioControl.aidl
index 0ffcd5e..8a5c294 100644
--- a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioControl.aidl
+++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioControl.aidl
@@ -183,4 +183,5 @@ interface IAudioControl {
      *                 interface.
      */
     oneway void registerGainCallback(in IAudioGainCallback callback);
+    oneway void setBalance(in int value);
 }
diff --git a/automotive/audiocontrol/aidl/default/AudioControl.cpp b/automotive/audiocontrol/aidl/default/AudioControl.cpp
index a121f8b..36074d0 100644
--- a/automotive/audiocontrol/aidl/default/AudioControl.cpp
+++ b/automotive/audiocontrol/aidl/default/AudioControl.cpp
@@ -214,6 +214,11 @@ binder_status_t AudioControl::dump(int fd, const char** args, uint32_t numArgs)
     }
 }
 
+ndk::ScopedAStatus AudioControl::setBalance(int in_value) {
+    LOG(DEBUG) << ": " << __func__ << "in_value: " << in_value;
+    // TODO: Implement setBalance
+    return ndk::ScopedAStatus::ok();
+}
+
 binder_status_t AudioControl::dumpsys(int fd) {
     if (mFocusListener == nullptr) {
         dprintf(fd, "No focus listener registered\n");
diff --git a/automotive/audiocontrol/aidl/default/AudioControl.h b/automotive/audiocontrol/aidl/default/AudioControl.h
index 16b80e8..bfe2780 100644
--- a/automotive/audiocontrol/aidl/default/AudioControl.h
+++ b/automotive/audiocontrol/aidl/default/AudioControl.h
@@ -54,6 +54,8 @@ class AudioControl : public BnAudioControl {
 
     binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
 
+    ndk::ScopedAStatus setBalance(int in_value) override;
+
   private:
     // This focus listener will only be used by this HAL instance to communicate with
     // a single instance of CarAudioService. As such, it doesn't have explicit serialization.

更新&编译

m android.hardware.automotive.audiocontrol-update-api
cd hardware/interfaces/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol
cp -rf current/* 2/
cd -
mmm hardware/interfaces/automotive/audiocontrol/aidl

报错

[  0% 9/1305] Verify hardware/interfaces/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/2 files have not been modified
FAILED: out/soong/.intermediates/hardware/interfaces/automotive/audiocontrol/aidl/android.hardware.automotive.audiocontrol-api/checkhash_2.timestamp
if [ $(cd 'hardware/interfaces/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/2' && { find ./ -name "*.aidl" -print0 | LC_ALL=C sort -z | xargs -0 sha1sum && echo 1; } | sha1sum | cut -d " " -f 1) = $(tail -1 'hardware/interfaces/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/2/.hash') ]; then touch out/soong/.intermediates/hardware/interfaces/automotive/audiocontrol/aidl/android.hardware.automotive.audiocontrol-api/checkhash_2.timestamp; else cat 'system/tools/aidl/build/message_check_integrity.txt' && exit 1; fi
###############################################################################
# ERROR: Modification detected of stable AIDL API file                        #
###############################################################################
Above AIDL file(s) has changed, resulting in a different hash. Hash values may
be checked at runtime to verify interface stability. If a device is shipped
with this change by ignoring this message, it has a high risk of breaking later
when a module using the interface is updated, e.g., Mainline modules.
13:59:48 ninja failed with: exit status 1

#### failed to build some targets (18 seconds) ####

解决方法

获取当前 apihash 并 更新到 .hash 文件,然后重新编译

cd 'hardware/interfaces/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/2' && { find ./ -name "*.aidl" -print0 | LC_ALL=C sort -z | xargs -0 sha1sum && echo 1; } | sha1sum | cut -d " " -f 1 > .hash
cd -
mmm hardware/interfaces/automotive/audiocontrol/aidl

上层使用接口添加

diff --git a/service/src/com/android/car/audio/hal/AudioControlWrapper.java b/service/src/com/android/car/audio/hal/AudioControlWrapper.java
index f819cf0..18cd2ce 100644
--- a/service/src/com/android/car/audio/hal/AudioControlWrapper.java
+++ b/service/src/com/android/car/audio/hal/AudioControlWrapper.java
@@ -120,6 +120,8 @@ public interface AudioControlWrapper {
      */
     void setBalanceTowardRight(float value);

+    void setBalance(int value);
+
     /**
      * Notifies HAL of changes in usages holding focus and the corresponding ducking changes for a
      * given zone.
diff --git a/service/src/com/android/car/audio/hal/AudioControlWrapperAidl.java b/service/src/com/android/car/audio/hal/AudioControlWrapperAidl.java
index e299fe8..a7c0190 100644
--- a/service/src/com/android/car/audio/hal/AudioControlWrapperAidl.java
+++ b/service/src/com/android/car/audio/hal/AudioControlWrapperAidl.java
@@ -197,6 +197,15 @@ public final class AudioControlWrapperAidl implements AudioControlWrapper, IBind
     }

     @Override
+    public void setBalance(int value) {
+        try {
+            mAudioControl.setBalance(value);
+        } catch (RemoteException e) {
+            Slogf.e(TAG, "setBalance with " + value + " failed", e);
+        }
+    }
+
+    @Override
     public void onDevicesToDuckChange(@NonNull List<CarDuckingInfo> carDuckingInfos) {
         Objects.requireNonNull(carDuckingInfos);
         DuckingInfo[] duckingInfos = new DuckingInfo[carDuckingInfos.size()];
diff --git a/service/src/com/android/car/audio/hal/AudioControlWrapperV1.java b/service/src/com/android/car/audio/hal/AudioControlWrapperV1.java
index d0be1cb..80a67a5 100644
--- a/service/src/com/android/car/audio/hal/AudioControlWrapperV1.java
+++ b/service/src/com/android/car/audio/hal/AudioControlWrapperV1.java
@@ -124,6 +124,11 @@ public final class AudioControlWrapperV1 implements AudioControlWrapper {
     }

     @Override
+    public void setBalance(int value) {
+        Slogf.e(TAG, "setBalance impl not use, the version");
+    }
+
+    @Override
     public void onDevicesToDuckChange(List<CarDuckingInfo> carDuckingInfos) {
         throw new UnsupportedOperationException("HAL ducking is unsupported for IAudioControl@1.0");
     }
diff --git a/service/src/com/android/car/audio/hal/AudioControlWrapperV2.java b/service/src/com/android/car/audio/hal/AudioControlWrapperV2.java
index a62f4b0..75473cb 100644
--- a/service/src/com/android/car/audio/hal/AudioControlWrapperV2.java
+++ b/service/src/com/android/car/audio/hal/AudioControlWrapperV2.java
@@ -157,6 +157,11 @@ public final class AudioControlWrapperV2 implements AudioControlWrapper {
     }

     @Override
+    public void setBalance(int value) {
+        Slogf.e(TAG, "setBalance impl not use, the version");
+    }
+
+    @Override
     public void onDevicesToDuckChange(List<CarDuckingInfo> carDuckingInfos) {
         throw new UnsupportedOperationException("HAL ducking is unsupported for IAudioControl@2.0");
     }