Chia sẻ đầu vào âm thanh

Đầu vào âm thanh thường đến từ micrô tích hợp, micrô bên ngoài hoặc giao diện âm thanh được gắn vào thiết bị. Nguồn âm thanh đầu vào cũng có thể là cuộc trò chuyện qua điện thoại.

Đôi khi, hai hoặc nhiều ứng dụng có thể cùng muốn "ghi lại" cùng một đầu vào âm thanh. Có thể họ đang thực hiện các nhiệm vụ khác nhau. Ví dụ: một số ứng dụng nhận âm thanh có thể đang "ghi âm", chẳng hạn như một ứng dụng ghi âm đơn giản, trong khi các ứng dụng khác có thể đang "nghe", chẳng hạn như Trợ lý Google hoặc một dịch vụ hỗ trợ tiếp cận phản hồi các lệnh thoại.

Trong cả hai trường hợp, các ứng dụng này đều muốn nhận dữ liệu đầu vào âm thanh. Trên toàn bộ trang này, chúng tôi sử dụng thuật ngữ "ghi lại" bất kể ứng dụng đang ghi âm hay chỉ nghe.

Nếu hai hoặc nhiều ứng dụng muốn ghi lại âm thanh cùng một lúc, thì có thể xảy ra vấn đề khi truyền tín hiệu âm thanh từ cùng một nguồn đến tất cả các ứng dụng đó. Trang này mô tả cách hệ thống Android chia sẻ dữ liệu đầu vào âm thanh giữa nhiều ứng dụng ghi lại âm thanh.

Hành vi trước Android 10

Trước Android 10, chỉ có một ứng dụng có thể ghi lại luồng âm thanh đầu vào tại một thời điểm. Nếu một ứng dụng nào đó đang ghi âm hoặc nghe âm thanh, ứng dụng của bạn có thể tạo một đối tượng AudioRecord, nhưng hệ thống sẽ trả về lỗi khi bạn gọi AudioRecord.startRecording() và quá trình ghi sẽ không bắt đầu.

Một trường hợp ngoại lệ đối với quy tắc này là khi một ứng dụng đặc quyền (chẳng hạn như Trợ lý Google hoặc một dịch vụ hỗ trợ tiếp cận) có quyền android.permission.CAPTURE_AUDIO_HOTWORD và sử dụng nguồn âm thanh thuộc loại HOTWORD. Trong trường hợp này, một ứng dụng khác có thể bắt đầu ghi. Khi đó, ứng dụng có đặc quyền đã bị chấm dứt và ứng dụng mới đã ghi nhận dữ liệu đầu vào.

Một thay đổi khác được thêm vào Android 9: chỉ những ứng dụng chạy ở nền trước (hoặc dịch vụ trên nền trước) mới có thể ghi lại dữ liệu đầu vào âm thanh. Khi một ứng dụng không có dịch vụ trên nền trước hoặc thành phần giao diện người dùng trên nền trước bắt đầu ghi lại, ứng dụng đó sẽ tiếp tục chạy nhưng không nhận được âm thanh, ngay cả khi đó là ứng dụng duy nhất ghi lại âm thanh tại thời điểm đó.

Hành vi của Android 10

Hành vi trước Android 10 là "ưu tiên theo thứ tự nộp đơn". Sau khi một ứng dụng bắt đầu thu thập dữ liệu âm thanh, không có ứng dụng nào khác có thể truy cập vào đầu vào âm thanh cho đến khi ứng dụng đang thu thập dữ liệu âm thanh dừng.

Android 10 áp dụng một sơ đồ ưu tiên có thể chuyển đổi luồng âm thanh đầu vào giữa các ứng dụng trong khi chúng đang chạy. Trong hầu hết các trường hợp, nếu một ứng dụng mới thu nhận dữ liệu đầu vào âm thanh, thì ứng dụng đang ghi âm trước đó sẽ tiếp tục chạy nhưng không nhận được âm thanh. Trong một số trường hợp, hệ thống có thể tiếp tục truyền âm thanh đến cả hai ứng dụng. Dưới đây là nội dung giải thích về các trường hợp chia sẻ.

Cơ chế này tương tự như cách tiêu điểm âm thanh xử lý nhiều ứng dụng tranh giành quyền sử dụng đầu ra âm thanh. Tuy nhiên, quyền phát âm thanh được quản lý bằng các yêu cầu theo chương trình để giành và giải phóng quyền phát, trong khi sơ đồ chuyển đổi đầu vào được mô tả ở đây dựa trên chính sách ưu tiên được áp dụng tự động bất cứ khi nào một ứng dụng mới bắt đầu ghi lại âm thanh.

Để ghi lại âm thanh, Android phân biệt 2 loại ứng dụng:

  • Người dùng cài đặt các ứng dụng "thông thường".
  • Các ứng dụng "đặc quyền" được cài đặt sẵn trên thiết bị. Các dịch vụ này bao gồm Trợ lý Google và tất cả các dịch vụ hỗ trợ tiếp cận.

Ngoài ra, ứng dụng sẽ được xử lý theo cách khác nếu sử dụng nguồn âm thanh "nhạy cảm về quyền riêng tư": CAMCORDER hoặc VOICE_COMMUNICATION.

Sau đây là các quy tắc ưu tiên để sử dụng và chia sẻ đầu vào âm thanh:

  • Các ứng dụng ưu tiên có mức độ ưu tiên cao hơn các ứng dụng thông thường.
  • Các ứng dụng có giao diện người dùng hiển thị ở nền trước có mức độ ưu tiên cao hơn các ứng dụng nền.
  • Những ứng dụng ghi lại âm thanh từ một nguồn nhạy cảm về quyền riêng tư sẽ có mức độ ưu tiên cao hơn so với những ứng dụng không ghi lại âm thanh từ nguồn đó.
  • Hai ứng dụng thông thường không bao giờ có thể ghi lại âm thanh cùng một lúc.
  • Trong một số trường hợp, một ứng dụng đặc quyền có thể chia sẻ dữ liệu đầu vào âm thanh với một ứng dụng khác.
  • Nếu 2 ứng dụng nền có cùng mức độ ưu tiên đang ghi lại âm thanh, thì ứng dụng được bắt đầu sau cùng sẽ có mức độ ưu tiên cao hơn.

Các trường hợp chia sẻ

Khi hai ứng dụng đang cố gắng ghi lại âm thanh, cả hai ứng dụng đều có thể nhận được tín hiệu đầu vào hoặc một trong hai ứng dụng có thể nhận được tín hiệu im lặng.

Có 4 trường hợp chính:

  • Trợ lý + ứng dụng thông thường
  • Dịch vụ hỗ trợ tiếp cận + ứng dụng thông thường
  • Hai ứng dụng thông thường
  • Cuộc gọi thoại + ứng dụng thông thường

Trợ lý + ứng dụng thông thường

Trợ lý là một ứng dụng đặc quyền vì được cài đặt sẵn và giữ vai trò RoleManager.ROLE_ASSISTANT. Mọi ứng dụng được cài đặt sẵn khác có vai trò này đều được xử lý tương tự.

Android chia sẻ âm thanh đầu vào theo các quy tắc sau:

  • Trợ lý có thể nhận âm thanh (bất kể ở nền trước hay nền sau) trừ phi một ứng dụng khác đang dùng nguồn âm thanh nhạy cảm về quyền riêng tư đã ghi lại.

  • Ứng dụng sẽ nhận được âm thanh trừ phi Trợ lý có một thành phần giao diện người dùng hiển thị ở trên cùng của màn hình.

Xin lưu ý rằng cả hai ứng dụng chỉ nhận được âm thanh khi Trợ lý ở chế độ nền và ứng dụng kia không ghi lại từ một nguồn âm thanh nhạy cảm về quyền riêng tư.

Dịch vụ hỗ trợ tiếp cận + ứng dụng thông thường

AccessibilityService yêu cầu một khai báo nghiêm ngặt.

Android chia sẻ âm thanh đầu vào theo các quy tắc sau:

  • Nếu giao diện người dùng của dịch vụ ở trên cùng, cả dịch vụ và ứng dụng đều nhận được dữ liệu đầu vào âm thanh. Hành vi này cung cấp các chức năng như điều khiển cuộc gọi thoại hoặc ghi hình bằng lệnh thoại.

  • Nếu dịch vụ không ở trên cùng, trường hợp này sẽ được xử lý như trường hợp hai ứng dụng thông thường bên dưới.

Hai ứng dụng thông thường

Khi hai ứng dụng ghi hình đồng thời, chỉ một ứng dụng nhận được âm thanh và ứng dụng còn lại nhận được âm thanh im lặng.

Android chia sẻ âm thanh đầu vào theo các quy tắc sau:

  • Nếu cả hai ứng dụng đều không nhạy cảm về quyền riêng tư, thì ứng dụng có giao diện người dùng ở trên cùng sẽ nhận được âm thanh. Nếu không có ứng dụng nào có giao diện người dùng, thì ứng dụng bắt đầu ghi gần đây nhất sẽ nhận được âm thanh.
  • Nếu một trong các ứng dụng đó nhạy cảm về quyền riêng tư, thì ứng dụng đó sẽ nhận được âm thanh và ứng dụng còn lại sẽ không nhận được âm thanh, ngay cả khi ứng dụng đó có giao diện người dùng ở trên cùng hoặc bắt đầu ghi gần đây hơn.
  • Nếu cả hai ứng dụng đều nhạy cảm với quyền riêng tư, thì ứng dụng bắt đầu ghi gần đây nhất sẽ nhận được âm thanh và ứng dụng còn lại sẽ không nhận được âm thanh.

Cuộc gọi thoại + ứng dụng thông thường

Cuộc gọi thoại đang hoạt động nếu chế độ âm thanh do AudioManager.getMode() trả về là MODE_IN_CALL hoặc MODE_IN_COMMUNICATION.

Android chia sẻ âm thanh đầu vào theo các quy tắc sau:

Hành vi của Android 11

Android 11 (API cấp 30) tuân theo sơ đồ mức độ ưu tiên của Android 10 như mô tả ở trên. API này cũng cung cấp các phương thức mới trong AudioRecord, MediaRecorderAAudioStream để bật và tắt khả năng ghi lại âm thanh đồng thời, bất kể trường hợp sử dụng đã chọn.

Các phương thức mới là:

Khi setPrivacySensitive()true, trường hợp sử dụng chụp là riêng tư và ngay cả Trợ lý có đặc quyền cũng không thể chụp đồng thời. Chế độ cài đặt này sẽ thay thế hành vi mặc định tuỳ thuộc vào nguồn âm thanh. Ví dụ: VOICE_COMMUNICATION theo mặc định là riêng tư nhưng UNPROCESSED thì không.

Các thay đổi về cấu hình

Khi một số ứng dụng ghi lại âm thanh cùng lúc, chỉ có một hoặc hai ứng dụng "đang hoạt động" (nhận âm thanh); các ứng dụng khác bị tắt tiếng (nhận tín hiệu im lặng). Khi các ứng dụng đang hoạt động thay đổi, khung âm thanh có thể định cấu hình lại các đường dẫn âm thanh theo những quy tắc sau:

  • Thiết bị đầu vào âm thanh cho mỗi ứng dụng đang hoạt động có thể thay đổi (ví dụ: từ micrô tích hợp sang tai nghe Bluetooth được gắn).
  • Quá trình tiền xử lý liên kết với ứng dụng đang hoạt động có mức độ ưu tiên cao nhất sẽ được bật. Tất cả các bước xử lý trước khác đều bị bỏ qua.

Vì một ứng dụng đang hoạt động có thể bị tắt tiếng khi một ứng dụng có mức độ ưu tiên cao hơn trở nên hoạt động, bạn có thể đăng ký một AudioManager.AudioRecordingCallback trên đối tượng AudioRecord hoặc MediaRecorder để được thông báo khi cấu hình thay đổi. Những thay đổi có thể xảy ra là:

  • Chụp ở chế độ im lặng hoặc không im lặng
  • Thiết bị đã thay đổi
  • Đã thay đổi quy trình tiền xử lý
  • Thuộc tính luồng đã thay đổi (tốc độ lấy mẫu, mặt nạ kênh, định dạng mẫu)

Bạn phải gọi AudioRecord.registerAudioRecordingCallback() trước khi bắt đầu quá trình chụp. Lệnh gọi lại chỉ được thực thi khi ứng dụng đang nhận âm thanh và có sự thay đổi.

Phương thức onRecordingConfigChanged() trả về một AudioRecordingConfiguration chứa trạng thái ghi âm hiện tại. Hãy sử dụng các phương thức sau để tìm hiểu về thay đổi:

isClientSilenced()
Trả về giá trị true nếu âm thanh trả về cho ứng dụng hiện đang bị tắt tiếng do chính sách ghi hình.
getAudioDevice()
Trả về thiết bị âm thanh đang hoạt động.
getEffects()
Trả về hiệu ứng tiền xử lý đang hoạt động. Xin lưu ý rằng hiệu ứng đang hoạt động có thể không giống với hiệu ứng do getClientEffects() trả về nếu ứng dụng đó không phải là ứng dụng đang hoạt động có mức độ ưu tiên cao nhất.
getFormat()
Trả về các thuộc tính của luồng. Xin lưu ý rằng dữ liệu âm thanh thực tế mà máy khách nhận được luôn tuân thủ định dạng bắt buộc do getClientFormat() trả về. Khung này tự động thực hiện việc lấy mẫu lại, chuyển đổi kênh và định dạng cần thiết từ định dạng được dùng tại giao diện phần cứng sang định dạng do máy khách chỉ định.
AudioRecord.getActiveRecordingConfiguration().
Trả về cấu hình ghi hình đang hoạt động.

Bạn có thể xem tổng quan về tất cả các bản ghi âm đang hoạt động trên thiết bị bằng cách gọi AudioManager.getActiveRecordingConfigurations().