Android 14 CarAudioService

2024-03-01 1891阅读

温馨提示:这篇文章已超过386天没有更新,请注意相关的内容是否还可用!

文章目录

      • 新功能
      • AudioMirring
      • oemCarService

        新功能

        • AudioMirring

          简单的说就是两个bus输出的是同一个音频数据。

          Android 14 CarAudioService
          (图片来源网络,侵删)

          构建的流程是: 一个输入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 中

                    1. 判断是不是支持mirror(通过判断mirroringDevice是不是至少有一个存在),支持的话,构造一个mix,将这个mix添加到audioPolicy当中。
                    2. 构造mix,这个mix 的device是mirroringDevice,attribute是music。现有只支持music类型共享。mix添加到audiopolicy 说明 后续的音频

                      数据通过mix线程都会写到mirror的device address。

                    3. 构造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();
                                          }
                                      }
                              
                              • 如何配置
                                1. 在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中获取到。

                                2. 编译carService 和 test app push 到system/priv_app即可。

                                    
                                   com.android.car.oemcarservice.testapp/com.android.car.oemcarservice.testapp.OemCarServiceImpl
                                
                                    
                                    
                                    
                                        
                                        
                                    
                                
                                
VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]