Trước khi bắt đầu một luồng logic, ứng dụng phải yêu cầu quyền phát âm thanh bằng cách sử dụng các thuộc tính âm thanh giống như được dùng cho luồng logic của ứng dụng. Mặc dù bạn nên gửi yêu cầu tiêu điểm như vậy, nhưng hệ thống không thực thi yêu cầu này. Một số ứng dụng có thể bỏ qua việc gửi yêu cầu một cách rõ ràng để thực hiện các hành vi cụ thể (ví dụ: để chủ ý phát âm thanh trong cuộc gọi điện thoại).
Vì lý do này, bạn nên coi tiêu điểm là một cách để gián tiếp kiểm soát và giải quyết xung đột phát, chứ không phải là cơ chế điều khiển âm thanh chính; xe không được phụ thuộc vào hệ thống tiêu điểm để vận hành hệ thống con âm thanh.
Lượt tương tác với tiêu điểm
Để hỗ trợ nhu cầu của AAOS, các yêu cầu về quyền phát âm thanh được xử lý dựa trên các lượt tương tác được xác định trước giữa CarAudioContext
của yêu cầu và lượt tương tác của chủ thể có quyền phát hiện hiện tại. Có 3 loại tương tác: độc quyền, từ chối và đồng thời.
Hoạt động tương tác độc quyền
Trong các lượt tương tác độc quyền, mỗi lần chỉ có một ứng dụng được phép giữ tiêu điểm.
Do đó, yêu cầu tiêu điểm sắp tới sẽ được cấp tiêu điểm trong khi chủ thể tiêu điểm hiện tại mất tiêu điểm. Ví dụ: khi người dùng khởi động một ứng dụng nhạc mới trong khi nhạc đang phát trong một ứng dụng hiện có. Vì cả hai đều đang phát nội dung đa phương tiện, nên mỗi lần chỉ có một trong hai ứng dụng được giữ tiêu điểm. Do đó, yêu cầu tiêu điểm của ứng dụng mới bắt đầu sẽ trả về bằng AUDIOFOCUS_REQUEST_GRANTED
và ứng dụng hiện đang phát nhạc sẽ nhận được sự kiện thay đổi tiêu điểm với trạng thái mất tương ứng với loại yêu cầu đã được thực hiện. Đây là mô hình tương tác thường thấy nhất với Android.
Từ chối tương tác
Với các lượt tương tác từ chối, yêu cầu đến luôn bị từ chối. Cố gắng phát nhạc trong khi đang có cuộc gọi là một ví dụ về tương tác bị từ chối. Trong trường hợp này, nếu trình quay số hiện đang giữ quyền phát âm thanh cho một cuộc gọi và một ứng dụng thứ hai yêu cầu quyền phát âm thanh để phát nhạc, thì ứng dụng nhạc sẽ nhận được AUDIOFOCUS_REQUEST_FAILED
để phản hồi yêu cầu của ứng dụng đó. Vì yêu cầu tiêu điểm bị từ chối, nên không có loại tiêu điểm nào bị mất được gửi đến chủ sở hữu tiêu điểm hiện tại.
Tương tác đồng thời
Điểm độc đáo nhất của AAOS là các lượt tương tác đồng thời. Điều này cho phép các ứng dụng yêu cầu quyền phát âm thanh trong ô tô giữ quyền phát đồng thời với các ứng dụng khác. Để một lượt tương tác đồng thời diễn ra, bạn phải đáp ứng các điều kiện sau. Các:
- Yêu cầu tiêu điểm sắp tới phải yêu cầu
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
. - Trình giữ tiêu điểm hiện tại không
setPauseWhenDucked(true)
. - Chủ sở hữu tiêu điểm hiện tại không chọn nhận sự kiện duck.
Nếu đáp ứng các tiêu chí này, thì yêu cầu tiêu điểm sẽ trả về bằng AUDIOFOCUS_REQUEST_GRANTED
trong khi chủ sở hữu tiêu điểm hiện tại không có thay đổi nào về tiêu điểm. Tuy nhiên, nếu chủ thể tiêu điểm hiện tại chọn nhận sự kiện nhấn để ẩn hoặc tạm dừng khi bị nhấn để ẩn, thì chủ thể tiêu điểm hiện tại sẽ mất tiêu điểm giống như khi có một lượt tương tác độc quyền.
Xử lý các luồng đồng thời
Mặc dù hoạt động tương tác đồng thời có nhiều ứng dụng hữu ích, nhưng nhà sản xuất thiết bị gốc (OEM) phải chú ý đến việc kết hợp và giảm âm ở cấp phần cứng trên các thiết bị đầu ra. Do đó, bạn nên chỉ định CarAudioContext
đến cùng một thiết bị đầu ra với CarAudioContext
mà chúng không thể phát đồng thời. Bằng cách có các thiết bị đầu ra riêng biệt cho các luồng đồng thời, điều này cho phép HAL loại bỏ một trong các luồng trước khi kết hợp các luồng đó với nhau hoặc định tuyến các luồng thực tế đến các loa khác nhau trong xe. Nếu các luồng logic được kết hợp trong Android, thì mức tăng của các luồng này sẽ không bị thay đổi và được phân phối trong cùng một luồng thực.
Ví dụ: khi chỉ đường và nội dung nghe nhìn được phân phối đồng thời, mức tăng cho luồng nội dung nghe nhìn có thể tạm thời giảm (được giảm) để có thể nghe rõ hơn hướng dẫn chỉ đường. Ngoài ra, luồng chỉ đường có thể được định tuyến đến loa bên người lái trong khi nội dung nghe nhìn tiếp tục phát trong phần còn lại của cabin.
Ma trận tương tác
Bảng dưới đây cho thấy ma trận tương tác do CarAudioService
xác định.
Các hàng đại diện cho CarAudioContext
của chủ sở hữu tiêu điểm hiện tại và các cột đại diện cho yêu cầu sắp tới.
Hãy xem xét một ví dụ, trong đó ứng dụng đa phương tiện âm nhạc hiện đang giữ tiêu điểm và ứng dụng điều hướng yêu cầu tiêu điểm, ma trận cho thấy hai lượt tương tác có thể phát đồng thời, giả sử các tiêu chí khác cho Tương tác đồng thời được đáp ứng.
Do các lượt tương tác đồng thời, có thể có nhiều trình giữ tiêu điểm. Trong trường hợp này, yêu cầu tiêu điểm sắp tới sẽ được so sánh với từng chủ sở hữu tiêu điểm hiện tại trước khi quyết định loại tương tác sẽ áp dụng. Trong trường hợp này, hoạt động tương tác bảo thủ nhất sẽ thắng (từ chối, sau đó là độc quyền và cuối cùng là đồng thời).
Trong bảng sau, các hoạt động tương tác với tiêu điểm giữa CarAudioContext cho một yêu cầu tiêu điểm sắp tới (cột) và ngữ cảnh của các chủ sở hữu tiêu điểm hiện có (hàng) được cung cấp. Mỗi ô đại diện cho loại tương tác dự kiến cho hai ngữ cảnh.
Hình 1. Tương tác với quyền phát âm thanh
Chỉ đường trong khi gọi điện
Trong Android 11, chúng tôi đã ra mắt một chế độ cài đặt mới cho phép người dùng thay đổi hành vi tương tác giữa tính năng chỉ đường và cuộc gọi điện thoại. Khi được đặt, android.car.KEY_AUDIO_FOCUS_NAVIGATION_REJECTED_DURING_CALL
sẽ thay đổi hoạt động tương tác giữa các yêu cầu tiêu điểm NAVIGATION
sắp tới và các chủ sở hữu tiêu điểm CALL
hiện tại từ tương tranh thành từ chối.
Vì vậy, nếu không muốn hướng dẫn chỉ đường làm gián đoạn cuộc gọi, người dùng có thể bật chế độ cài đặt này. Giá trị này được duy trì cho người dùng và có thể được đặt một cách linh động để các yêu cầu tiêu điểm tiếp theo tuân theo giá trị cài đặt mới.
Quyền phát âm thanh có thể trì hoãn
Trong Android 11, AAOS đã thêm tính năng hỗ trợ yêu cầu tiêu điểm âm thanh có thể trì hoãn. Điều này cho phép các yêu cầu tiêu điểm không tạm thời bị trì hoãn khi tương tác với các chủ sở hữu tiêu điểm hiện tại thường dẫn đến việc bị từ chối. Khi một thay đổi về tiêu điểm dẫn đến trạng thái mà yêu cầu bị trì hoãn có thể lấy tiêu điểm, yêu cầu sẽ được cấp.
Quy tắc đối với yêu cầu quyền phát âm thanh bị trì hoãn
- Chỉ yêu cầu không tạm thời – như đã đề cập trước đó, bạn chỉ có thể thực hiện yêu cầu bị trì hoãn cho các nguồn không tạm thời. Điều này là để tránh phát âm thanh tạm thời sau khi âm thanh đó không còn liên quan nữa.
- Chỉ có thể trì hoãn một yêu cầu tại một thời điểm – Nếu một yêu cầu có thể trì hoãn được thực hiện trong khi đã có một yêu cầu bị trì hoãn, thì yêu cầu bị trì hoãn ban đầu sẽ nhận được một sự kiện thay đổi
AUDIOFOCUS_LOSS
và yêu cầu mới sẽ nhận được phản hồi đồng bộ củaAUDIOFOCUS_REQUEST_DELAYED
. - Yêu cầu có thể trì hoãn phải có
OnAudioFocusChangeListener
. Sau khi một yêu cầu bị trì hoãn, trình nghe sẽ được dùng để thông báo cho người yêu cầu khi yêu cầu đó cuối cùng được cấp (AUDIOFOCUS_GAIN
) hoặc nếu yêu cầu đó bị từ chối sau này (AUDIOFOCUS_LOSS
).
Yêu cầu tiêu điểm có thể trì hoãn
Để tạo một yêu cầu có thể bị trì hoãn, hãy sử dụng AudioFocusRequest.Builder#setAcceptsDelayedFocusGain
:
mMediaWithDelayedFocusListener = new MediaWithDelayedFocusListener(); mDelayedFocusRequest = new AudioFocusRequest .Builder(AudioManager.AUDIOFOCUS_GAIN) .setAudioAttributes(mMusicAudioAttrib) .setOnAudioFocusChangeListener(mMediaWithDelayedFocusListener) .setForceDucking(false) .setWillPauseWhenDucked(false) .setAcceptsDelayedFocusGain(true) .build();
Sau đó, khi thực hiện yêu cầu, hãy xử lý phản hồi AUDIOFOCUS_REQUEST_DELAYED
:
int delayedFocusRequestResults = mAudioManager.requestAudioFocus(mDelayedFocusRequest); if (delayedFocusRequestResults == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { // start audio playback return; } if (delayedFocusRequestResults == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) { // audio playback delayed to audio focus listener return; }
Khi yêu cầu bị trì hoãn, trình nghe tiêu điểm sẽ chịu trách nhiệm xử lý các thay đổi về tiêu điểm:
private final class MediaWithDelayedFocusListener implements OnAudioFocusChangeListener { @Override public void onAudioFocusChange(int focusChange) { synchronized (mLock) { switch (focusChange) { case AudioManager.AUDIOFOCUS_GAIN: … // Start focus playback case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: … // Pause media transiently case AudioManager.AUDIOFOCUS_LOSS: … // Stop media
Quản lý tiêu điểm nhiều vùng
Đối với những xe có nhiều vùng âm thanh, tiêu điểm âm thanh được quản lý độc lập cho từng vùng. Do đó, yêu cầu đối với một vùng không tính đến nội dung đang giữ tiêu điểm trong các vùng khác, cũng không khiến trình giữ tiêu điểm trong các vùng khác mất tiêu điểm. Nhờ đó, bạn có thể quản lý tiêu điểm của khoang chính riêng biệt với hệ thống giải trí cho hàng ghế sau, nhờ đó tránh làm gián đoạn quá trình phát âm thanh ở một khu vực do các thay đổi về tiêu điểm ở khu vực khác.
Đối với tất cả các ứng dụng, CarAudioService
sẽ tự động xử lý việc quản lý tiêu điểm. Vùng âm thanh của yêu cầu lấy tiêu điểm được xác định dựa trên UserId
hoặc UID
liên kết. Để biết thông tin chi tiết, hãy xem phần Điều hướng âm thanh.
Yêu cầu âm thanh từ nhiều vùng đồng thời
Nếu muốn phát âm thanh đồng thời ở nhiều vùng, ứng dụng phải yêu cầu quyền phát trung tâm cho từng vùng bằng cách đưa AUDIOFOCUS_EXTRA_REQUEST_ZONE_ID
vào gói:
// Create attribute with bundle and AUDIOFOCUS_EXTRA_REQUEST_ZONE_ID Bundle bundle = new Bundle(); bundle.putInt(CarAudioManager.AUDIOFOCUS_EXTRA_REQUEST_ZONE_ID, zoneId); AudioAttributes attributesWithZone = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_MEDIA) .addBundle(bundle) .build(); // Create focus request using built attributesWithZone
Tham số gói này cho phép người yêu cầu ghi đè các mối liên kết vùng âm thanh tự động để sử dụng mã vùng được chỉ định. Do đó, ứng dụng có thể đưa ra các yêu cầu riêng biệt cho các vùng âm thanh khác nhau.
Quyền phát âm thanh HAL
Kể từ Android 11, HAL hiện được bật để thay mặt cho các luồng bên ngoài yêu cầu tiêu điểm. Mặc dù không bắt buộc, nhưng bạn nên sử dụng các API này để cho phép âm thanh bên ngoài tham gia tốt hơn vào hệ sinh thái Android và mang lại trải nghiệm người dùng mượt mà hơn.
Xin lưu ý rằng HAL vẫn chịu trách nhiệm thực hiện lệnh gọi cuối cùng về âm thanh nào sẽ được ưu tiên. Ở mức độ này, âm thanh khẩn cấp và âm thanh quan trọng về an toàn phải được phát bất kể HAL có được cấp quyền phát âm thanh hay không và phải tiếp tục phát khi thích hợp ngay cả khi HAL mất quyền phát âm thanh. Điều này cũng đúng với mọi âm thanh theo yêu cầu của quy định.
Tương tự như vậy, HAL vẫn phải chủ động tắt tiếng các luồng Android khi thích hợp khi phát âm thanh khẩn cấp hoặc âm thanh quan trọng về an toàn để đảm bảo người dùng nghe được rõ ràng.
AudioControl@2.0
Phiên bản 2.0 của AudioControl HAL giới thiệu một số API mới:
API | Mục đích |
---|---|
IAudioControl#registerFocusListener |
Đăng ký một thực thể của IFocusListener với AudioControl HAL.
Trình nghe này cho phép HAL yêu cầu và từ bỏ quyền phát âm thanh. HAl dự kiến sẽ cung cấp một thực thể ICloseHandle để Android sử dụng nhằm huỷ đăng ký trình nghe.
|
IAudioControl#onAudioFocusChange |
Thông báo cho HAL về các thay đổi về trạng thái để tập trung vào các yêu cầu do HAL đưa ra thông qua IFocusListener . Trong đó có cả phản hồi cho các yêu cầu tiêu điểm ban đầu.
|
IFocusListener#requestAudioFocus |
Thay mặt HAL yêu cầu tiêu điểm cho một mục đích sử dụng, mã nhận dạng vùng và loại lợi tức tiêu điểm được chỉ định. |
IFocusListener#abandonAudioFocus |
Bỏ qua các yêu cầu tiêu điểm HAL hiện có cho mục đích sử dụng và mã vùng đã chỉ định. |
HAL có thể có nhiều yêu cầu lấy tiêu điểm cùng một lúc, nhưng chỉ được giới hạn ở một yêu cầu cho mỗi lần sử dụng và ghép nối mã vùng. Xin lưu ý rằng Android giả định HAL ngay lập tức bắt đầu phát âm thanh cho một lần sử dụng sau khi yêu cầu được thực hiện và tiếp tục làm như vậy cho đến khi từ bỏ tiêu điểm.
Ngoài registerFocusListener
, tất cả các yêu cầu này đều là oneway
để đảm bảo rằng Android không trì hoãn HAL trong khi xử lý yêu cầu lấy tiêu điểm. HAL không được chờ lấy tiêu điểm trước khi phát âm thanh quan trọng về an toàn. HAL không bắt buộc phải theo dõi và phản hồi các thay đổi về tiêu điểm âm thanh thông qua IAudioControl#onAudioFocusChange
, mặc dù bạn nên làm như vậy khi thích hợp.