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

Dữ liệu đầ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ị. Dữ liệu đầu vào âm thanh cũng có thể bắt nguồ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ể đều muốn "ghi" cùng một đầu vào âm thanh. Chúng có thể đang thực hiện nhiều tác vụ. Ví dụ: một số ứng dụng nhận được âm thanh có thể là "ghi âm", chẳng hạn như một 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" như Trợ lý Google hoặc 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 đầu vào âm thanh. Trong suốt trang này, chúng tôi sử dụng thuật ngữ "capture" bất kể ứng dụng đang ghi hay chỉ đang nghe.

Nếu hai hoặc nhiều ứng dụng muốn thu âm thanh cùng lúc, có thể đã xảy ra sự cố khi cung cấp tín hiệu âm thanh từ cùng một nguồn cho 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 đang ghi hoặc nghe âm thanh, thì ứng dụng của bạn có thể tạo đố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 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 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 đã bị chấm dứt và ứng dụng mới đã ghi lại dữ liệu đầu vào.

Thêm một thay đổi nữa trong 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ể thu thập 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 thu thập, ứng dụng đó vẫn tiếp tục chạy nhưng bị tắt tiếng, ngay cả khi đó là ứng dụng duy nhất ghi âm tại thời điểm đó.

Hành vi trên Android 10

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

Android 10 áp dụng một giao thức ưu tiên có thể chuyển đổi luồng âm thanh đầu vào giữa các ứng dụng 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 nhận được đầu vào âm thanh, thì ứng dụng thu âm trước đó sẽ tiếp tục chạy nhưng sẽ nhận được khoảng 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. Dưới đây là phần giải thích về các trường hợp chia sẻ.

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à giải phóng tâm điểm, trong khi giao thứ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 thập âm thanh.

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

  • Ứ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ị. Những thiết bị 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 "phụ thuộc vào quyền riêng tư": CAMCORDER hoặc VOICE_COMMUNICATION.

Dưới đây là các quy tắc ưu tiên cho việc sử dụng và chia sẻ đầu vào âm thanh:

  • Ứng dụng đặc quyền sẽ có mức độ ưu tiên cao hơn ứng dụng thông thường.
  • Ứng dụng cho thấy giao diện người dùng ở nền trước được ưu tiên hơn so với ứng dụng ở chế độ nền.
  • Các ứng dụng ghi âm từ một nguồn tôn trọng quyền riêng tư sẽ có mức độ ưu tiên cao hơn so với các ứng dụng không có mức độ ưu tiên đó.
  • 2 ứng dụng thông thường không thể ghi âm cùng một lúc.
  • Trong một số trường hợp, ứng dụng có đặ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 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.

Chia sẻ tình huống

Khi 2 ứ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ể bị tắt tiế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à 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ạy ở nền trước hay nền sau) trừ phi một ứng dụng khác sử dụng nguồn âm thanh tôn trọng quyền riêng tư đang thu âm.

  • Ứ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ị ở đầu màn hình.

Lưu ý rằng cả hai ứng dụng đều chỉ nhận được âm thanh khi Trợ lý ở chế độ nền và ứng dụng còn lại hiện không thu âm từ một nguồn âm thanh tôn trọng 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ụ nằm ở trên cùng, thì cả dịch vụ và ứng dụng đều sẽ nhận được đầ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 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 xem như trường hợp hai ứng dụng thông thường dưới đây.

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

Khi 2 ứ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 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 không có ứng dụng nào có giao diện người dùng, thì ứng dụng bắt đầu thu â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ư, ứng dụng đó sẽ nhận được âm thanh và ứng dụng còn lại sẽ bị tắt tiếng ngay cả khi có 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 lại gần đây nhất sẽ nhận được âm thanh và ứng dụng còn lại sẽ nhận âm thanh im lặng.

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

Lệnh gọi thoại sẽ được kích hoạt nếu chế độ âm thanh mà 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 trên Android 11

Android 11 (API cấp 30) tuân thủ giao thức ưu tiên của Android 10 như mô tả ở trên. Thư viện này cũng cung cấp các phương thức mới trong AudioRecord, MediaRecorderAAudioStream, cho phép 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 bao gồm:

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 ở chế độ riêng tư theo mặc định nhưng UNPROCESSED thì không.

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

Khi một số ứng dụng ghi âm đồng thời, chỉ một hoặc hai ứng dụng ở trạng thái "đang hoạt động" (nhận âm thanh); các ứng dụng khác bị tắt tiếng (nhận được â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 đườ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 thành tai nghe Bluetooth đi kèm).
  • 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 đang bật. Mọi quá trình 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 hoạt động, 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:

  • Chụp ảnh ở chế độ im lặng hoặc không bị tắt tiếng
  • Đã thay đổi thiết bị
  • Đã thay đổi quá trình xử lý trước
  • Các thuộc tính của 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 nhận được âm thanh và có sự 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ề ứng dụng 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 xử lý trước đang hoạt động. 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ách 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 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 theo định dạng bắt buộc mà getClientFormat() trả về. Khung này tự động thực hiện việc chuyển đổi định dạng lại, kênh và định dạng cần thiết từ định dạng được dùng trên 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 bản ghi đang hoạt động.

Bạn có thể xem thông tin chung về 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().