Định tuyến âm thanh

Trong Android 10, car_audio_configuration.xml sẽ thay thế car_volumes_groups.xmlIAudioControl.getBusForContext. Trong tệp cấu hình mới, danh sách các vùng được xác định. Mỗi vùng có một hoặc nhiều nhóm phương tiện với các thiết bị liên kết và mỗi thiết bị có các ngữ cảnh sẽ được định tuyến trong vùng đó. Tất cả ngữ cảnh đều phải được biểu thị trong mỗi vùng.

Định cấu hình định tuyến âm thanh

Các tệp chính sách âm thanh (thường nằm trong phân vùng của nhà cung cấp) đại diện cho cấu hình phần cứng âm thanh của bo mạch. Tất cả thiết bị được tham chiếu trong car_audio_configuration.xml phải được xác định trong audio_policy_configuration.xml.

Bật tính năng định tuyến AAOS

Để sử dụng tính năng định tuyến dựa trên AAOS, bạn phải đặt cờ audioUseDynamicRouting thành true:

<resources>
    <bool name="audioUseDynamicRouting">true</bool>
</resources>

Khi false, tính năng định tuyến và phần lớn CarAudioService sẽ bị tắt và hệ điều hành sẽ quay lại hành vi mặc định của AudioService.

Vùng chính

Theo mặc định, tất cả âm thanh sẽ được định tuyến đến vùng chính. Chỉ có thể có một vùng chính, được chỉ định trong cấu hình bằng thuộc tính isPrimary="true".

Cấu hình mẫu

Ví dụ: một xe có thể có hai vùng — vùng chính và hệ thống giải trí ở hàng ghế sau. Do đó, car_audio_configuration.xml có thể được xác định như sau:

<audioZoneConfiguration version="2.0">
       <zone name="primary zone" isPrimary="true">
           <volumeGroups>
               <group>
                   <device address="bus0_media_out">
                       <context context="music"/>
                       <context context="announcement"/>
                   </device>
                   <device address="bus3_call_ring_out">
                       <context context="call_ring"/>
                   </device>
                   <device address="bus6_notification_out">
                       <context context="notification"/>
                   </device>
                   <device address="bus7_system_sound_out">
                       <context context="system_sound"/>
                       <context context="emergency"/>
                       <context context="safety"/>
                       <context context="vehicle_status"/>
                   </device>
               </group>
               <group>
                   <device address="bus1_navigation_out">
                       <context context="navigation"/>
                   </device>
                   <device address="bus2_voice_command_out">
                       <context context="voice_command"/>
                   </device>
               </group>
               <group>
                   <device address="bus4_call_out">
                       <context context="call"/>
                   </device>
               </group>
               <group>
                   <device address="bus5_alarm_out">
                       <context context="alarm"/>
                   </device>
               </group>
           </volumeGroups>
       </zone>
        <zone name="rear seat zone" audioZoneId="1">
           <volumeGroups>
               <group>
                   <device address="bus100_rear_seat">
                       <context context="music"/>
                       <context context="navigation"/>
                       <context context="voice_command"/>
                       <context context="call_ring"/>
                       <context context="call"/>
                       <context context="alarm"/>
                       <context context="notification"/>
                       <context context="system_sound"/>
                       <context context="emergency"/>
                       <context context="safety"/>
                       <context context="vehicle_status"/>
                       <context context="announcement"/>
                   </device>
               </group>
           </volumeGroups>
    </zones>
</audioZoneConfiguration>

Ở đây, vùng chính đã tách riêng các ngữ cảnh cho các thiết bị khác nhau. Điều này cho phép HAL áp dụng các hiệu ứng xử lý hậu kỳ và kết hợp khác nhau trên mỗi đầu ra thiết bị bằng phần cứng của xe. Các thiết bị được sắp xếp thành 4 nhóm âm lượng: nội dung nghe nhìn, chỉ đường, cuộc gọi và chuông báo. Nếu hệ thống được định cấu hình thành useFixedVolume, thì các mức âm lượng cho mỗi nhóm sẽ được chuyển vào HAL để áp dụng cho đầu ra của các thiết bị này.

Đối với vùng phụ, kết quả dự kiến là thông qua một thiết bị đầu ra. Trong ví dụ này, tất cả các hoạt động sử dụng đều được định tuyến đến một thiết bị và nhóm phương tiện để đơn giản hoá mọi thứ.

Cấu hình âm thanh cho vùng người ngồi

Trong Android 11, car_audio_configuration.xml được mở rộng thêm để giới thiệu hai trường mới là audioZoneIdoccupantZoneId. Thứ nhất, bạn có thể sử dụng audioZoneId để kiểm soát việc quản lý vùng tốt hơn. Mặt khác, bạn có thể sử dụng occupantZoneId để định cấu hình tính năng định tuyến dựa trên mã nhận dạng người dùng.

Để sử dụng các trường mới này, bạn bắt buộc phải sử dụng phiên bản 2 của car_audio_configuration.xml. Xem lại cấu hình âm thanh ở trên nhưng sử dụng trường mới để liên kết mã nhận dạng khu vực người ngồi và mã nhận dạng khu vực âm thanh, cấu hình mới không có định nghĩa nhóm âm lượng có thể được thiết lập như sau:

<audioZoneConfiguration version="2.0">
       <zone name="primary zone" isPrimary="true" occupantZoneId="0">
         ...
       </zone>
       <zone name="rear seat zone" audioZoneId="1" occupantZoneId="1">
         ...
       </zone>
    </zones>
</audioZoneConfiguration>

Cấu hình ở trên xác định mối liên kết cho vùng chính với vùng người ngồi 0 và audioZoneId 1 với occupantZoneId 1. Nhìn chung, bạn có thể định cấu hình mọi mối liên kết giữa vùng người ngồi và vùng âm thanh, nhưng mối liên kết phải là một với một. Dưới đây là các quy tắc xác định hai trường mới:

  • audioZoneId cho múi giờ chính luôn bằng 0
  • Không được lặp lại số audioZoneIdoccupantZoneId
  • audioZoneIdoccupantZoneId chỉ có thể có mối liên kết một với một

Định tuyến thông qua UID của ứng dụng

Một loạt API ẩn đã được giới thiệu cho CarAudioManager trong phiên bản 10 để cho phép các ứng dụng truy vấn và đặt vùng âm thanh cũng như tiêu điểm.

int[] getAudioZoneIds();
int getZoneIdForUid(int uid);
boolean setZoneIdForUid(int zoneId, int uid);
boolean clearZoneIdForUid(int uid);

Các API ở trên cho phép ứng dụng của bên thứ nhất quản lý việc định tuyến âm thanh dựa trên UID của ứng dụng. Do đó, bạn cũng cần có cả mã nhận dạng vùng âm thanh và UID của ứng dụng. Khi có thông tin đó, bạn có thể thiết lập định tuyến âm thanh bằng cách sử dụng API CarAudioManager#setZoneIdForUid.

Thay đổi khu vực cho một ứng dụng

Theo mặc định, tất cả âm thanh sẽ được chuyển đến vùng chính. Để cập nhật một ứng dụng được định tuyến đến một vùng khác, hãy sử dụng CarAudioManager#setZoneIdForUid:

// Find zone to play
int zoneId = ...

// Find application's uid
Int uid = mContext.getPackageManager()
        .getApplicationInfo(mContext.getPackageName(), 0)
        .uid;

if (mCarAudioManager.setZoneIdForUid(zoneId, info.uid)) {
    Log.d(TAG, "Zone successfully updated");
} else {
    Log.d(TAG, "Failed to change zone");
}

N Lưu ý: Luồng và tiêu điểm không thể tự động chuyển đổi vùng. Do đó, bạn phải dừng phát và yêu cầu lại quyền lấy tiêu điểm để thay đổi vùng.

Định tuyến bằng Mã nhận dạng người dùng

Mặc dù tính năng định tuyến dựa trên UID của ứng dụng cho phép kiểm soát chi tiết việc định tuyến âm thanh của từng ứng dụng, nhưng tính năng này cũng yêu cầu định tuyến âm thanh cho từng ứng dụng trước khi ứng dụng thực sự yêu cầu quyền phát âm thanh và phát âm thanh. Để giảm thiểu vấn đề này và hỗ trợ thêm cho các ứng dụng bên thứ ba phát âm thanh mà không cần sửa đổi, CarAudioService sử dụng bản đồ vùng người ngồi trong ô tô và vùng âm thanh để xác định tuyến đường dựa trên mã nhận dạng người dùng. Bằng cách này, khi người dùng đăng nhập vào khu vực người ngồi, dịch vụ âm thanh trên ô tô sẽ được thông báo. Với tín hiệu này, tính năng quản lý và định tuyến tiêu điểm âm thanh sẽ tự động được định cấu hình cho tất cả các vùng âm thanh.

Bạn vẫn có thể sử dụng tính năng định tuyến dựa trên UID của ứng dụng nhưng phải thực hiện độc lập với tính năng định tuyến dựa trên mã nhận dạng người dùng. Điều này có nghĩa là nếu bạn xác định mối liên kết giữa vùng người ngồi và vùng âm thanh trên ô tô, thì tính năng định tuyến dựa trên UID sẽ bị tắt và việc cố gắng gọi CarAudioManager#setZoneidForUid sẽ gặp lỗi.

Mặc dù việc định tuyến âm thanh và quản lý tiêu điểm đã được đơn giản hoá bằng tính năng quản lý khu vực có người, nhưng người dùng vẫn phải được chỉ định cho một khu vực có người. Bạn có thể thực hiện việc này bằng cách sử dụng CarOccupantZoneManager#assignProfileUserToOccupantZone. API này yêu cầu quyền quản lý người dùng. Hiện tại, các nhà sản xuất thiết bị gốc (OEM) sẽ quản lý việc chỉ định người dùng cho khu vực người ngồi thông qua một số loại giao diện người dùng hệ thống. Sau khi hoàn tất, việc khởi chạy ứng dụng, định tuyến âm thanh, quản lý tiêu điểm sẽ tự động được định cấu hình cho người dùng.

Định tuyến bằng setPreferredDevice

Cùng với những thay đổi ở trên, Android 11 cũng có một API mới để truy vấn các thiết bị đầu ra liên kết với từng vùng, CarAudioManager#getOutputDeviceForUsage(int zoneId, int usage).

Bạn có thể dùng API này để truy vấn thiết bị đầu ra cho một vùng cụ thể và mức sử dụng thuộc tính âm thanh. Theo cách này, các ứng dụng của bên thứ nhất có thể định tuyến âm thanh đến các vùng khác nhau bằng cách sử dụng API setPreferredDevice của trình phát. API getOutputDeviceForUsage yêu cầu PERMISSION_CAR_CONTROL_AUDIO_SETTINGS và là một API hệ thống. Dưới đây là ví dụ về cách tìm thiết bị đa phương tiện cho một vùng cụ thể và định tuyến đến thiết bị đó bằng API setPreferredDevice.

audioZoneId = ... ;
mediaDeviceInfo = mCarAudioManager
            .getOutputDeviceForUsage(audioZoneId, AudioAttributes.USAGE_MEDIA);
…
mPlayer.setPreferredDevice(mediaDeviceInfo);