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ị. Dữ liệu âm thanh đầu vào 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ể cùng muốn "ghi lại" một đầu vào âm thanh. Có thể họ đang thực hiện các nhiệm vụ khác. 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 giọng nói đơ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 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 âm thanh đầu vào. Trong suốt 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 thu â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ẻ đầu vào âm thanh giữa nhiều ứng dụng ghi âm.

Hành vi trước Android 10

Trước Android 10, mỗi lần chỉ có một ứng dụng có thể ghi lại luồng âm thanh đầu vào. Nếu một số ứng dụng đã ghi hoặc nghe âm thanh, thì ứng dụng của bạn có thể tạo đối tượng AudioRecord, như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 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 sẽ chấm dứt và ứng dụng mới sẽ thu thập dữ liệu đầu vào.

Một thay đổi nữa được thêm vào Android 9: chỉ những ứng dụng chạy ở nền trước (hoặc dịch vụ nền trước) mới có thể thu âm thanh đầu vào. Khi một ứng dụng không có dịch vụ 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 không ghi được âm thanh, ngay cả khi đó là ứng dụng duy nhất ghi âm vào thời điểm đó.

Hành vi của Android 10

Hành vi trước Android 10 là "ai đến trước thì được phục vụ trước". Sau khi một ứng dụng bắt đầu thu âm thanh, 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 thu âm thanh 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 thu nạp dữ liệu âm thanh đầu vào, thì ứng dụng đang thu nạp 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. Các trường hợp chia sẻ khác nhau được giải thích bên dưới.

Lược đồ này tương tự như cách tiêu điểm â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 để nhận và nhả quyền phát, trong khi lược đồ 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 thu âm thanh.

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

  • Người dùng cài đặt các ứng dụng "thông thường".
  • Ứng dụng "đặc quyền" được cài đặt trước trên thiết bị. Các dịch vụ này bao gồm Trợ lý Google và tất 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 ứng dụng đó 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 khi sử dụng và chia sẻ đầu vào âm thanh:

  • Ứng dụng đặc quyền có mức độ ưu tiên cao hơn ứng dụng thông thường.
  • Ứng dụng có giao diện người dùng trên nền trước hiển thị có mức độ ưu tiên cao hơn ứng dụng chạy trong nền.
  • Các ứng dụng thu âm thanh từ một nguồn nhạy cảm về quyền riêng tư có mức độ ưu tiên cao hơn các ứng dụng không thu âm thanh từ nguồn đó.
  • Hai ứng dụng thông thường không bao giờ có thể thu âm cùng một lúc.
  • Trong một số trường hợp, một ứng dụng có đặc quyền có thể chia sẻ dữ liệu âm thanh đầu vào với một ứng dụng khác.
  • Nếu hai ứng dụng nền có cùng mức độ ưu tiên đang thu âm thanh, thì ứng dụng 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 thu âm thanh, cả hai đề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 khác được cài đặt sẵn 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ể là ở nền trước hay nền sau) trừ phi một ứng dụng khác sử dụng nguồn âm thanh nhạy cảm về quyền riêng tư đang thu âm.

  • Ứng dụng 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ị ở đầu 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 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 yêu cầu 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, thì cả dịch vụ và ứng dụng đều nhận được dữ liệu âm thanh đầu vào. 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, thì trường hợp này sẽ được coi 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 đang ghi âm đồng thời, chỉ một ứng dụng nhận được âm thanh và ứng dụng còn lại sẽ không nhận được âm thanh.

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 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 có tính 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 âm 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ẽ 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 (cấp độ API 30) tuân theo lược đồ ưu tiên của Android 10 được mô tả ở trên. Thư viện này cũng cung cấp các phương thức mới trong AudioRecord, MediaRecorder và AAudioStream để bật và tắt khả 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() là true, trường hợp sử dụng chụp ảnh là riêng tư và ngay cả Trợ lý có đặc quyền cũng không thể chụp ảnh đồng thời. Chế độ cài đặt này sẽ ghi đè hành vi mặc định phụ thuộc vào nguồn âm thanh. Ví dụ: theo mặc định, VOICE_COMMUNICATION là riêng tư nhưng UNPROCESSED thì không.

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

Khi nhiều ứng dụng đang ghi âm đồng thời, chỉ một hoặc hai ứng dụng trong số đó "đang hoạt động" (nhận âm thanh); các ứng dụng khác bị tắt tiếng (nhận âm thanh 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 các 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 kết nối).
  • Quá 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. Tất cả các bước tiền xử lý 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 bắt đầu hoạt động, nên bạn có thể đăng ký AudioManager.AudioRecordingCallback 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à:

  • Tắt tiếng hoặc bật tiếng khi chụp ảnh
  • Đã 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. 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() trả về một AudioRecordingConfiguration chứa trạng thái thu â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 được trả về cho ứng dụng hiện đang bị tắt tiếng do chính sách thu thập.
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à ứng dụng 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 dùng tại giao diện phần cứng sang định dạng do ứng dụng chỉ định.
AudioRecord.getActiveRecordingConfiguration()
Trả về cấu hình ghi đang hoạt động.

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