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 đi kèm với thiết bị. Đầu vào âm thanh cũng có thể đến từ một cuộc trò chuyện qua điện thoại.

Đôi khi, hai hoặc nhiều ứng dụng có thể muốn "ghi" cùng một đầu vào âm thanh. Các vị trí này có thể đang thực hiện các nhiệm vụ khác nhau. Ví dụ: một số ứng dụng nhận được âm thanh có thể là "ghi âm", chẳng hạn như trình ghi âm giọng nói đơn giản, trong khi các ứng dụng khác có thể "lắng 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 lệnh thoại.

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

Nếu hai hoặc nhiều ứng dụng muốn ghi âm cùng lúc, có thể đã xảy ra sự cố khi phân phối 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ẻ đầu vào âm thanh giữa nhiều ứng dụng ghi âm.

Cách hoạt động trước Android 10

Trước Android 10, chỉ một ứng dụng mới có thể ghi lại luồng âm thanh đầu vào tại một thời điểm. Nếu một số ứng dụng đang ghi hoặc nghe âm thanh, thì ứng dụng của bạn có thể tạo đối tượng AudioRecord. Tuy nhiên, 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.

Có một ngoại lệ đối với quy tắc này là khi một ứng dụng đặc quyền (như Trợ lý Google hoặc 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 điều đó xảy ra, ứng dụng đặc quyền đã chấm dứt và ứng dụng mới đã thu thập dữ liệu đầu vào.

Một thay đổi nữa đã được thêm vào Android 9: chỉ các ứ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 âm thanh đầu vào. 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 âm, ứng dụng đó sẽ tiếp tục chạy nhưng bị im lặng, ngay cả khi đó là ứng dụng duy nhất ghi âm tại thời điểm đó.

Hành vi của Android 10

Hành vi trước Android 10 là "ưu tiên người đến trước". Sau khi một ứng dụng bắt đầu ghi âm, không ứ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 ghi âm dừng lại.

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

Giao thức này tương tự như cách quyền phát âm thanh xử lý nhiều ứng dụng cạnh tranh để 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 có lập trình để lấy và nhả tiêu điểm, trong khi lược đồ chuyển đổi đầu vào được mô tả ở đây dựa trên một chính sách ưu tiên được tự động áp dụng bất cứ khi nào một ứng dụng mới bắt đầu thu âm.

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

  • Các ứng dụng "thông thường" do người dùng cài đặt.
  • 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, một ứ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à quy tắc ưu tiên để sử dụng và chia sẻ âm thanh đầu vào:

  • Những ứng dụng ưu tiên có mức độ ưu tiên cao hơn những ứng dụng thông thường.
  • Ứng dụng có giao diện người dùng hiển thị trên nền trước có mức độ ưu tiên cao hơn ứng dụng nền.
  • Các ứng dụng ghi âm từ một nguồn nhạy cảm về quyền riêng tư có mức độ ưu tiên cao hơn so với các ứng dụng khác không làm như vậy.
  • Hai ứng dụng thông thường không bao giờ thu được â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ẻ đầu vào âm thanh với một ứng dụng khác.
  • Nếu 2 ứng dụng trong nền có cùng mức độ ưu tiên đang ghi âm, thì ứng dụng cuối cùng bắt đầu có mức độ ưu tiên cao hơn.

Tình huống chia sẻ

Khi hai ứng dụng đang cố gắng ghi âm, 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ể bị tắt tiếng.

Có bốn tình huống 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à có vai trò RoleManager.ROLE_ASSISTANT. Mọi ứng dụng 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ể ở chế độ nền trước hay nền) trừ phi một ứng dụng khác dùng nguồn âm thanh nhạy cảm về quyền riêng tư đã ghi âm.

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

Xin lưu ý rằng cả hai ứng dụng chỉ nhận được âm thanh khi Trợ lý hoạt động ở chế độ nền và ứng dụng còn lại không thu â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 đòi hỏi bạn phải thực hiện một nội dung 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ụ nằm ở trên cùng, thì cả dịch vụ và ứng dụng đều nhận được đầu vào âm thanh. Hành vi này cung cấp chức năng như điều khiển cuộc gọi thoại hoặc quay video bằng lệnh thoại.

  • Nếu dịch vụ không ở trên cùng, trường hợp này được xử lý giống 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 2 ứng dụng chụp đồng thời, chỉ một ứng dụng nhận được âm thanh còn ứng dụng còn lại chuyển sang chế độ im lặng.

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

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

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

Cuộc gọi thoại sẽ 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 thủ lược đồ mức độ ưu tiên của Android 10 được 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 tính năng ghi âm đồ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 sẽ ở chế độ 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 ghi đè hành vi mặc định phụ thuộc vào nguồn âm thanh. Ví dụ: VOICE_COMMUNICATION được đặt ở chế độ riêng tư theo mặc định nhưng UNPROCESSED thì không.

Thay đổi về cấu hình

Khi nhiều ứng dụng ghi âm cùng lúc, chỉ một hoặc hai ứng dụng "đang hoạt động" (nhận âm thanh); các ứng dụng còn lại bị tắt tiếng (nhận được khoảng 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 đi kèm).
  • Quy trình xử lý trước 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. Mọi quá trình xử lý trước khác sẽ 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 được kích hoạt, nên bạn có thể đăng ký AudioManager.AudioRecordCallback trên đối tượng AudioRecord hoặc MediaRecorder để nhận 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 tắt tiếng
  • Đã thay đổi thiết bị
  • Đã thay đổi quá trình xử lý trước
  • 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 chụp ảnh. Lệnh gọi lại chỉ được thực thi khi ứng dụng đang nhận âm thanh và có thay đổi xảy ra.

Phương thức onRecordingConfigChanged() sẽ 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 này:

isClientSilenced()
Trả về giá trị true nếu âm thanh trả về máy khách hiện đang bị tắt tiếng do chính sách ghi lại.
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. Lưu ý: 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ề thuộc tính luồng. Lưu ý rằng dữ liệu âm thanh thực tế mà ứng dụng nhận được luôn tuân theo định dạng bắt buộc do getClientFormat() trả về. Khung này sẽ 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 dùng ở 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 bản ghi đang hoạt động.

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