Android 14 CarAudioService
温馨提示:这篇文章已超过386天没有更新,请注意相关的内容是否还可用!
文章目录
- 新功能
- AudioMirring
- oemCarService
新功能
- AudioMirring
简单的说就是两个bus输出的是同一个音频数据。
(图片来源网络,侵删)构建的流程是: 一个输入src的bus,和两个输出dst的bus。 通过setParamter 设置到hal。 hal解析这些参数,将输入bus
的音频数据拷贝输出到两个dst的bus。
- CarOemService
可以外部注册对应的carAudioFocusService、CarAudioVolumeService、CarAudioDuckingService.
分别为焦点请求,音量设置、音频闪避。
也就是oem 根据自己的需要去控制这三个方面的音频功能。
当有定义这三个service的时候,相应的处理会调用到对应的服务。 调用过程是基于binder 的 是需要IPC调用。
这一部处理是在java层处理。
- 对于按键的处理
新增了CarInputService, 可以通过监听不同的InputService 来处理按键。 补齐了12上面无法多屏幕按键控制。
这个按键需要OEM 自己定义 通过vhal hal 上报到CarInputService。 然后audio这边去监听相关的按键事件。
vehicle hal中可以携带三个参数 是int类型的数组
第一个参数 是按键事件的代码 1001 - 1007
第二个是屏幕 可以主屏副屏等等。音量调节的时候 可以从这个display ID 获取zoneID。
AudioMirring
- 如何配置mirror的区域
- mirror的工作原理
首先在配置文件中添加的配置为, 在carAudioService 中进行标签的解析,然后设置mirror的device。
-
基本的原理:
在CarService 这一层是构造类似下面这样的keyvalue序列,然后这个序列通过AudioManager的setParameters给到hal。
mirroring_src=bus_1000;mirroring_dest=bus_10,bus_20.
而上述的keyValue 序列是要求hal层 实现所有写入到mirroring_src bus的数据 都要拷贝到bus_10 和bus_20进行输出。其中bus_10 和 bus_20是需要在zondID 中进行定义的,是已经有的输出设备。
详细来说: 首先解析xml中mirroringDevice,这个device 同时也需要在audio_policy_configuration.xml中定义。 跟正常的device address一样。在CarService 中
- 判断是不是支持mirror(通过判断mirroringDevice是不是至少有一个存在),支持的话,构造一个mix,将这个mix添加到audioPolicy当中。
- 构造mix,这个mix 的device是mirroringDevice,attribute是music。现有只支持music类型共享。mix添加到audiopolicy 说明 后续的音频
数据通过mix线程都会写到mirror的device address。
- 构造parameter 参数列表(怎么构建的?)外部的接口是
enableMirrorForAudioZones,传递的参数是需要mirror的zone id列表。carAudioService 中会经过一系列的判断确认zoneID可用时,
通过zoneId来获取USAGE_MEDIA的DeviceAddress。
然后将mirrorDevice 和 获取到的DeviceAddress 组成paramter传递给hal。
-
Hal 层的实现
在有paramete的情况下。解析获取mirror src dst的address。 但不是打开的src的address,而是打开dst的address。
然后将数据分别写入到这两个地址中。mirror的src相当于一个中转的地址。
oemCarService
- oemCarService的作用
使用一个app的service 替换原生的focusrequest、duck和volume。
private OemCarAudioFocusResult evaluateFocusRequestLocked(FocusEntry replacedCurrentEntry, AudioFocusInfo audioFocusInfo) { return isExternalFocusEnabled() ? evaluateFocusRequestExternallyLocked(audioFocusInfo, replacedCurrentEntry) : evaluateFocusRequestInternallyLocked(audioFocusInfo, replacedCurrentEntry); }- 如何启用
配置应用的的名字。比如想用 test的这个com.android.car.oemcarservice.testapp.OemCarServiceImpl
将名字config 到xml,然后编译这个应用 push到system/priv-app目录底下。
String componentName = res.getString(R.string.config_oemCarService); Intent intent = (new Intent()) .setComponent(ComponentName.unflattenFromString(mComponentName)); Slogf.i(TAG, "Binding to Oem Service with intent: %s", intent); mHandlerThread = CarServiceUtils.getHandlerThread("car_oem_service"); mHandler = handler == null ? new Handler(mHandlerThread.getLooper()) : handler; mIsOemServiceBound = mContext.bindServiceAsUser(intent, mCarOemServiceConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.SYSTEM);private boolean isExternalFocusEnabled() { CarOemProxyService proxy = CarLocalServices.getService(CarOemProxyService.class); if (!proxy.isOemServiceEnabled()) { return false; } if (!proxy.isOemServiceReady()) { logFocusEvent("Focus was called but OEM service is not yet ready."); return false; } return proxy.getCarOemAudioFocusService() != null; }-
如何调用
bindServiceAsUser的作用是什么?https://bbs.huaweicloud.com/blogs/325746
-
客户端服务端都继承.stub.
-
服务端实现具体的AIDL接口,主要是下面的这些接口。
IOemCarAudioFocusService getOemAudioFocusService(); IOemCarAudioVolumeService getOemAudioVolumeService(); IOemCarAudioDuckingService getOemAudioDuckingService(); -
在配置config中国oemCarService 后,现有的实现是packages/services/Car/tests/OemCarServiceTestApp/src/com/android/car/oemcarservice/testapp/OemCarServiceImpl.java。
-
客户端获取服务, 通过package的名字构造一个intent,然后bindServiceAsUser。发送intent
在onServiceConnected 通过binder获取到远程的mOemCarService。外部通过getService
的方式获取CarOemProxyService的服务。 然后通过这个服务调用HIDL的接口。
CarOemProxyService proxy = CarLocalServices.getService(CarOemProxyService.class); public void onServiceConnected(ComponentName componentName, IBinder iBinder) { Slogf.i(TAG, "onServiceConnected: %s, %s", componentName, iBinder); synchronized (mLock) { if (mOemCarService == IOemCarService.Stub.asInterface(iBinder)) { return; // already connected. } Slogf.i(TAG, "car oem service binder changed, was %s now: %s", mOemCarService, iBinder); mOemCarService = IOemCarService.Stub.asInterface(iBinder); Slogf.i(TAG, "**CarOemService connected**"); mIsOemServiceConnected = true; mLock.notifyAll(); } }- 如何配置
-
在config.xml 中配置componet name
com.android.car.oemcarservice.testapp/com.android.car.oemcarservice.testapp.OemCarServiceImpl
componet name 根据app的package和service name一起组成的。
形式为package name/service name 这两个名字可以从源码的AndroidManifest.xml中获取到。
-
编译carService 和 test app push 到system/priv_app即可。
com.android.car.oemcarservice.testapp/com.android.car.oemcarservice.testapp.OemCarServiceImpl
-
- 如何配置
-
-
- 如何启用
- oemCarService的作用
-
- mirror的工作原理
- 如何配置mirror的区域
- 对于按键的处理
- CarOemService
- AudioMirring
