Âm thanh ô tô

Android Automotive OS (AAOS) xây dựng dựa trên ngăn xếp âm thanh cốt lõi của Android để hỗ trợ các trường hợp sử dụng hoạt động như hệ thống thông tin giải trí trên xe. AAOS chịu trách nhiệm về âm thanh thông tin giải trí (chẳng hạn như nội dung đa phương tiện, chỉ đường và thông tin liên lạc) nhưng không trực tiếp chịu trách nhiệm về tiếng chuông và cảnh báo yêu cầu nghiêm ngặt về tính sẵn có và thời gian. Mặc dù AAOS cung cấp các tín hiệu và các cơ chế giúp xe quản lý âm thanh, nhưng cuối cùng thì việc đó là do xe để thực hiện cuộc gọi về những âm thanh sẽ được phát cho người lái xe và cho hành khách, đảm bảo âm thanh quan trọng về an toàn và âm thanh theo quy định đều được áp dụng phù hợp đã nghe thấy mà không bị gián đoạn.

Vì Android quản lý trải nghiệm nội dung nghe nhìn trên xe, các nguồn nội dung nghe nhìn bên ngoài chẳng hạn như bộ dò đài sẽ được biểu thị bằng các ứng dụng có thể xử lý âm thanh và sự kiện chính về nội dung nghe nhìn cho nguồn.

Android 11 có những thay đổi sau đây đối với âm thanh liên quan đến ô tô hỗ trợ:

Âm thanh và luồng nội dung trên Android

Hệ thống âm thanh trên ô tô xử lý những âm thanh và luồng sau:

Sơ đồ cấu trúc tập trung vào luồng

Hình 1. Sơ đồ cấu trúc tập trung vào luồng

Android quản lý âm thanh đến từ các ứng dụng Android, kiểm soát các ứng dụng đó và định tuyến âm thanh của họ đến thiết bị đầu ra tại HAL dựa trên loại âm thanh:

  • Luồng logic, còn gọi là nguồn trong âm thanh cốt lõi đều được gắn thẻ Thuộc tính âm thanh.
  • Luồng thực tế, còn gọi là thiết bị trong âm thanh chính không có thông tin ngữ cảnh sau khi kết hợp.

Để đảm bảo độ tin cậy, âm thanh bên ngoài (âm thanh độc lập chẳng hạn như chuông cảnh báo dây an toàn) được quản lý bên ngoài Android, bên dưới HAL hoặc thậm chí trong phần cứng riêng biệt. Trình triển khai hệ thống phải cung cấp một trình kết hợp chấp nhận một hoặc nhiều luồng đầu vào âm thanh từ Android rồi kết hợp các luồng đó theo cách phù hợp với các nguồn âm thanh bên ngoài mà chiếc xe.

Việc triển khai HAL và bộ trộn bên ngoài chịu trách nhiệm đảm bảo Những âm thanh bên ngoài có tính an toàn cao sẽ được nghe thấy và để phối trong âm thanh do Android cung cấp và định tuyến chúng đến loa phù hợp.

Âm thanh trên Android

Ứng dụng có thể có một hoặc nhiều người chơi tương tác thông qua phiên bản Android tiêu chuẩn API (ví dụ: AudioManager để điều khiển tiêu điểm hoặc MediaPlayer để phát trực tuyến) để phát ra một hoặc nhiều luồng dữ liệu âm thanh logic. Dữ liệu này có thể là đơn kênh đơn kênh hoặc âm thanh vòm 7.1 nhưng được định tuyến và xử lý như một nguồn duy nhất. Luồng ứng dụng được liên kết với AudioAttributes nhằm đưa ra gợi ý cho hệ thống về cách thể hiện âm thanh.

Các luồng logic được gửi qua AudioService và được định tuyến đến một (và một) trong số các luồng đầu ra vật lý sẵn có, mỗi luồng là đầu ra của bộ trộn trong AudioFlinger. Sau khi đã trộn các thuộc tính âm thanh với luồng thực, chúng không còn khả dụng.

Sau đó, mỗi luồng vật lý sẽ được phân phối đến HAL âm thanh để kết xuất trên phần cứng. Trong ứng dụng dành cho ô tô, phần cứng kết xuất có thể là bộ mã hoá và giải mã cục bộ (tương tự như thiết bị di động) hoặc bộ xử lý từ xa trên màn hình chính của xe mạng. Dù bằng cách nào, nhiệm vụ của việc triển khai HAL âm thanh là cung cấp dữ liệu mẫu thực tế và làm cho dữ liệu đó có âm thanh.

Luồng bên ngoài

Các luồng âm thanh không được định tuyến qua Android (để chứng nhận hoặc về thời gian) có thể được gửi trực tiếp tới bộ trộn bên ngoài. Kể từ Android 11, HAL giờ có thể yêu cầu tiêu điểm cho những âm thanh bên ngoài này để thông báo cho Android để ứng dụng có thể thực hiện các hành động thích hợp như tạm dừng nội dung nghe nhìn hoặc ngăn để người khác không thể tập trung.

Nếu luồng bên ngoài là nguồn nội dung nghe nhìn sẽ tương tác với âm thanh môi trường mà Android đang tạo (ví dụ: dừng phát MP3 khi đã bật bộ điều chỉnh bên ngoài), thì những luồng bên ngoài đó sẽ được biểu thị bằng Ứng dụng Android. Một ứng dụng như vậy sẽ yêu cầu quyền phát âm thanh thay mặt cho nguồn nội dung đa phương tiện thay vì HAL và sẽ phản hồi thông báo lấy tiêu điểm bằng cách bắt đầu/dừng nguồn bên ngoài khi cần thiết để phù hợp với tiêu điểm Android . Ứng dụng này cũng chịu trách nhiệm xử lý các sự kiện chính đối với nội dung đa phương tiện như phát/tạm dừng. Một cơ chế được đề xuất để điều khiển các thiết bị bên ngoài đó là HwAudioSource.

Thiết bị đầu ra

Ở cấp độ HAL âm thanh, loại thiết bị AUDIO_DEVICE_OUT_BUS cung cấp thiết bị đầu ra chung để sử dụng trong hệ thống âm thanh của xe. Xe buýt thiết bị hỗ trợ các cổng có thể định địa chỉ (trong đó mỗi cổng là điểm cuối cho một luồng thực) và dự kiến sẽ là loại thiết bị đầu ra duy nhất được hỗ trợ trong một chiếc xe.

Quá trình triển khai hệ thống có thể sử dụng một cổng bus cho tất cả âm thanh Android, trong trong trường hợp này, Android kết hợp mọi thứ với nhau và phân phối dưới dạng một luồng. Ngoài ra, HAL có thể cung cấp một cổng bus cho mỗi CarAudioContext để cho phép phân phối đồng thời bất kỳ loại âm thanh nào. Điều này giúp HAL có thể để trộn và giảm bớt các âm thanh theo ý muốn.

Việc chỉ định ngữ cảnh âm thanh cho các thiết bị đầu ra được thực hiện thông qua car_audio_configuration.xml.

Đầu vào micrô

Khi ghi âm, HAL âm thanh nhận được openInputStream lệnh gọi bao gồm đối số AudioSource cho biết cách đầu vào micrô cần được xử lý.

Nguồn VOICE_RECOGNITION (cụ thể là Trợ lý Google) mong đợi một luồng micrô âm thanh nổi hiệu ứng loại bỏ tiếng vọng (nếu có) nhưng không có quy trình xử lý nào khác được áp dụng cho hiệu ứng này. Trợ lý dự kiến sẽ thực hiện việc tạo tia sáng.

Đầu vào micrô đa kênh

Để ghi âm từ một thiết bị có nhiều kênh (âm thanh nổi), hãy sử dụng mặt nạ chỉ mục kênh thay vì mặt nạ chỉ mục vị trí (chẳng hạn như CHANNEL_IN_LEFT). Ví dụ:

final AudioFormat audioFormat = new AudioFormat.Builder()
    .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
    .setSampleRate(44100)
    .setChannelIndexMask(0xf /* 4 channels, 0..3 */)
    .build();
final AudioRecord audioRecord = new AudioRecord.Builder()
    .setAudioFormat(audioFormat)
    .build();
audioRecord.setPreferredDevice(someAudioDeviceInfo);

Khi cả setChannelMasksetChannelIndexMask được đặt, AudioRecord chỉ sử dụng giá trị được đặt bởi setChannelMask (tối đa 2 kênh).

Chụp đồng thời

Kể từ Android 10, khung Android hỗ trợ việc lấy đồng thời thông tin đầu vào, nhưng có các hạn chế nhằm bảo vệ quyền riêng tư của người dùng. Là một phần các hạn chế này, các nguồn ảo như AUDIO_SOURCE_FM_TUNER bị bỏ qua và do đó được phép được ghi đồng thời với đầu vào thông thường (chẳng hạn như micrô). HwAudioSources cũng không được coi là một phần của hoạt động đồng thời hạn chế chụp.

Các ứng dụng được thiết kế để hoạt động với AUDIO_DEVICE_IN_BUS thiết bị hoặc với thiết bị AUDIO_DEVICE_IN_FM_TUNER phụ phải dựa vào nền tảng một cách rõ ràng xác định các thiết bị đó và sử dụng AudioRecord.setPreferredDevice() bỏ qua logic lựa chọn nguồn mặc định của Android.

Mức sử dụng âm thanh

AAOS chủ yếu sử dụng AudioAttributes.AttributeUsages để định tuyến, điều chỉnh âm lượng và quản lý tiêu điểm. Cách sử dụng là đại diện cho "lý do" luồng đang được phát. Do đó, tất cả các luồng và yêu cầu quyền phát âm thanh phải chỉ định cách sử dụng cho tính năng phát âm thanh. Thời gian không được thiết lập cụ thể khi tạo đối tượng AudioAttributes, việc sử dụng sẽ mặc định là USAGE_UNKNOWN. Mặc dù hiện tại chúng tôi xử lý là USAGE_MEDIA, nên bạn không nên dựa vào hành vi này cho nội dung nghe nhìn video.

Mức sử dụng hệ thống

Android 11 đã ra mắt các cách sử dụng hệ thống. Các trường hợp sử dụng này hoạt động tương tự như cách sử dụng đã thiết lập trước đây, ngoại trừ việc chúng yêu cầu API hệ thống để sử dụng cũng như android.permission.MODIFY_AUDIO_ROUTING. Gói thuê bao mới cách sử dụng hệ thống là:

  • USAGE_EMERGENCY
  • USAGE_SAFETY
  • USAGE_VEHICLE_STATUS
  • USAGE_ANNOUNCEMENT

Để tạo AudioAttributes bằng hoạt động sử dụng hệ thống, hãy sử dụng AudioAttributes.Builder#setSystemUsage thay vì setUsage. Gọi phương thức này bằng một mức sử dụng ngoài hệ thống sẽ dẫn đến việc gửi IllegalArgumentException. Ngoài ra, nếu cả việc sử dụng và sử dụng hệ thống đã được thiết lập trên một trình tạo, thì trình tạo này sẽ gửi một IllegalArgumentException khi tạo bản dựng.

Để kiểm tra xem mục đích sử dụng liên kết với AudioAttributes hãy gọi AudioAttributes#getSystemUsage. Hàm này sẽ trả về mức sử dụng hệ thống hoặc mức sử dụng được liên kết.

Ngữ cảnh âm thanh

Để đơn giản hoá cấu hình của âm thanh AAOS, chúng tôi đã nhóm các trường hợp sử dụng tương tự nhau vào CarAudioContext. Những ngữ cảnh âm thanh này được sử dụng xuyên suốt CarAudioService để xác định chế độ định tuyến, nhóm âm lượng và quyền phát âm thanh Google Cloud.

Bối cảnh âm thanh trong Android 11 là:

Bối cảnh âm thanh ô tô Cách sử dụng thuộc tính được liên kết
MUSIC UNKNOWN, GAME, MEDIA
NAVIGATION ASSISTANCE_NAVIGATION_GUIDANCE
VOICE_COMMAND ASSISTANT, ASSISTANCE_ACCESSIBILITY
CALL_RING NOTIFICATION_RINGTONE
CALL VOICE_COMMUNICATION, VOICE_COMMUNICATION_SIGNALING
ALARM ALARM
NOTIFICATION NOTIFICATION, NOTIFICATION_*
SYSTEM_SOUND ASSISTANCE_SONIFICATION
EMERGENCY EMERGENCY
SAFETY SAFETY
VEHICLE_STATUS VEHICLE_STATUS
ANNOUNCEMENT ANNOUNCEMENT

Liên kết giữa bối cảnh âm thanh và cách sử dụng âm thanh. Các hàng được đánh dấu là dành cho người dùng mới mức sử dụng hệ thống.

Âm thanh nhiều vùng

Ô tô xuất hiện một loạt các trường hợp sử dụng mới liên quan đến người dùng đồng thời tương tác với nền tảng và tìm cách sử dụng các phương tiện riêng biệt. Cho ví dụ: người lái xe có thể phát nhạc trong cabin khi hành khách ở ghế sau đang xem một video trên YouTube trên màn hình sau. Tính năng Âm thanh nhiều vùng sẽ bật bằng cách cho phép nhiều nguồn âm thanh phát đồng thời qua nhiều khu vực của chiếc xe.

Tính năng Âm thanh nhiều vùng kể từ Android 10 cho phép OEM định cấu hình âm thanh thành các vùng riêng biệt. Mỗi khu vực là một tập hợp các thiết bị trong xe với các nhóm âm lượng riêng, cấu hình định tuyến cho ngữ cảnh và tiêu điểm Google Cloud. Bằng cách này, bạn có thể định cấu hình cabin chính là một âm thanh trong khi giắc cắm tai nghe trên màn hình sau được định cấu hình thành khu vực thứ hai.

Các vùng này được xác định là một phần của car_audio_configuration.xml. Sau đó, CarAudioService đọc cấu hình và giúp AudioService định tuyến luồng âm thanh dựa trên vùng được liên kết. Mỗi vùng vẫn xác định quy tắc định tuyến dựa trên ngữ cảnh và uid ứng dụng. Khi người chơi đã tạo, CarAudioService sẽ xác định người chơi ở vùng nào liên kết với thiết bị nào, sau đó dựa vào việc sử dụng thiết bị nào mà AudioFlinger sẽ định tuyến âm thanh đến.

Tiêu điểm cũng được duy trì độc lập cho từng vùng âm thanh. Điều này cho phép các ứng dụng khác nhau để tạo âm thanh độc lập mà không cần can thiệp vào nhau trong khi khiến các ứng dụng vẫn tuân theo các thay đổi trong tập trung trong vùng của họ. CarZonesAudioFocus ở trong CarAudioService chịu trách nhiệm quản lý tiêu điểm của mỗi vùng.

Định cấu hình âm thanh nhiều vùng

Hình 2. Định cấu hình âm thanh nhiều vùng

Lớp trừu tượng phần cứng (HAL) cho âm thanh

Việc triển khai âm thanh trên ô tô dựa trên lớp trừu tượng phần cứng (HAL) cho âm thanh Android tiêu chuẩn, bao gồm:

  • IDevice.hal. Tạo các luồng đầu vào và đầu ra, xử lý âm lượng chính và tắt tiếng, đồng thời sử dụng:
    • createAudioPatch. Để tạo các bản vá bên ngoài giữa các thiết bị.
    • IDevice.setAudioPortConfig() để cung cấp âm lượng cho mỗi luồng thực.
  • IStream.hal. Cùng với các biến thể đầu vào và đầu ra, quản lý việc truyền trực tuyến mẫu âm thanh đến và đi từ phần cứng.

Các loại thiết bị trên ô tô

Những loại thiết bị sau đây phù hợp với nền tảng ô tô.

Loại thiết bị Mô tả
AUDIO_DEVICE_OUT_BUS Đầu ra chính từ Android (đây là cách tất cả âm thanh từ Android giao đến xe). Được dùng làm địa chỉ để phân biệt các luồng cho từng ngữ cảnh.
AUDIO_DEVICE_OUT_TELEPHONY_TX Dùng cho âm thanh được định tuyến đến sóng vô tuyến di động để truyền.
AUDIO_DEVICE_IN_BUS Dùng cho dữ liệu đầu vào không được phân loại theo cách khác.
AUDIO_DEVICE_IN_FM_TUNER Chỉ dùng để phát sóng vô tuyến.
AUDIO_DEVICE_IN_TV_TUNER Dùng cho thiết bị TV nếu có.
AUDIO_DEVICE_IN_LINE Dùng cho giắc đầu vào AUX.
AUDIO_DEVICE_IN_BLUETOOTH_A2DP Đã nhận nhạc qua Bluetooth.
AUDIO_DEVICE_IN_TELEPHONY_RX Dùng cho âm thanh nhận được từ hệ thống phát thanh di động liên kết với điện thoại .

Định cấu hình thiết bị âm thanh

Thiết bị âm thanh mà Android phải được xác định trong /audio_policy_configuration.xml, bao gồm các thành phần sau:

  • tên mô-đun. Hỗ trợ "chính" (dùng cho các trường hợp sử dụng trong ô tô), "A2DP", "remote_submix" và "USB". Tên mô-đun và âm thanh tương ứng trình điều khiển cần được biên dịch thành audio.primary.$(variant).so.
  • devicePorts. Chứa danh sách mã mô tả thiết bị cho tất cả đầu vào và đầu ra thiết bị (bao gồm cả thiết bị được gắn cố định và thiết bị có thể tháo rời) có thể được truy cập từ mô-đun này.
    • Đối với mỗi thiết bị đầu ra, bạn có thể xác định bộ điều khiển khuếch đại bao gồm các giá trị tối thiểu/tối đa/mặc định/bước tính bằng milibel (1 millibel = 1/100 dB = 1/1000 bel).
    • Bạn có thể sử dụng thuộc tính địa chỉ trên thực thể devicePort để tìm thiết bị của bạn, ngay cả khi có nhiều thiết bị có cùng loại thiết bị với AUDIO_DEVICE_OUT_BUS.
  • MixPorts. Chứa danh sách tất cả các luồng đầu ra và đầu vào được hiển thị bởi lớp trừu tượng phần cứng (HAL) âm thanh. Mỗi thực thể MixPort có thể được coi là một luồng thực để Android AudioService.
  • tuyến đường. Xác định danh sách các kết nối có thể có giữa đầu vào và đầu ra trên nhiều thiết bị hoặc giữa luồng và thiết bị.

Ví dụ sau đây xác định một thiết bị đầu ra bus0_phone_out trong đó tất cả Các luồng âm thanh trên Android được trộn bằng Mixer_bus0_phone_out. Tuyến đường này sẽ lấy luồng đầu ra mixer_bus0_phone_out đến thiết bị bus0_phone_out

<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
    <modules>
        <module name="primary" halVersion="3.0">
            <attachedDevices>
                <item>bus0_phone_out</item>
<defaultOutputDevice>bus0_phone_out</defaultOutputDevice>
            <mixPorts>
                <mixPort name="mixport_bus0_phone_out"
                         role="source"
                         flags="AUDIO_OUTPUT_FLAG_PRIMARY">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                            samplingRates="48000"
                            channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                </mixPort>
            </mixPorts>
            <devicePorts>
                <devicePort tagName="bus0_phone_out"
                            role="sink"
                            type="AUDIO_DEVICE_OUT_BUS"
                            address="BUS00_PHONE">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                            samplingRates="48000"
                            channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                    <gains>
                        <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
                                minValueMB="-8400"
                                maxValueMB="4000"
                                defaultValueMB="0"
                                stepValueMB="100"/>
                    </gains>
                </devicePort>
            </devicePorts>
            <routes>
                <route type="mix" sink="bus0_phone_out"
                       sources="mixport_bus0_phone_out"/>
            </routes>
        </module>
    </modules>
</audioPolicyConfiguration>