Tăng cường bảo mật âm thanh nền

Kể từ Android 17, khung âm thanh sẽ thực thi các quy định hạn chế đối với hoạt động tương tác âm thanh trong nền, bao gồm cả việc phát âm thanh, yêu cầu tiêu điểm âm thanh và API thay đổi âm lượng để đảm bảo rằng những thay đổi này được người dùng chủ ý bắt đầu.

Tất cả ứng dụng chạy trên Android 17 có các hoạt động tương tác âm thanh trong nền này đều phải có một hoạt động hiển thị hoặc phải đang chạy một dịch vụ trên nền trước không thuộc loại SHORT_SERVICE. Điều này áp dụng cho dù ứng dụng có nhắm đến API cấp 37 hay không.

Nếu một ứng dụng nhắm đến Android 17 (cấp độ API 37), thì sẽ có thêm một quy định hạn chế. Nếu đang chạy ở chế độ nền, thì ứng dụng phải chạy một dịch vụ nền trước có chức năng khi đang dùng (WIU). (Dịch vụ trên nền trước được cấp các chức năng WIU nếu được khởi động để phản hồi một thao tác do người dùng khởi tạo hoặc trong khi người dùng nhìn thấy ứng dụng.) Tuy nhiên, yêu cầu về chức năng WIU sẽ được miễn nếu ứng dụng đã được cấp quyền chuông báo chính xác và đang thực hiện thay đổi đối với các luồng âm thanh có thuộc tính USAGE_ALARM.

Nếu ứng dụng cố gắng gọi API âm thanh khi ứng dụng không ở trong một vòng đời hợp lệ, thì API phát âm thanh và thay đổi âm lượng sẽ không hoạt động mà không gửi ngoại lệ hoặc cung cấp thông báo lỗi. API tâm điểm âm thanh không thành công với mã kết quả AUDIOFOCUS_REQUEST_FAILED.

Lý do chúng tôi thực hiện thay đổi này

Mục đích của việc đưa ra các quy tắc hạn chế này là để giảm thiểu trải nghiệm âm thanh nền có lỗi không mong muốn. Một số ví dụ bao gồm:

  • Các ứng dụng phát âm thanh mà không có dịch vụ nền trước có thể bị treo. Khi ứng dụng cuối cùng cũng được huỷ đóng băng, ứng dụng sẽ tiếp tục phát âm thanh một cách bất ngờ, có thể là vài giờ sau đó.
  • Các ứng dụng phát âm thanh mà không có dịch vụ nền trước sẽ phải đối mặt với nhiều hạn chế về thời gian chạy, dẫn đến hiệu suất âm thanh không ổn định.
  • Quá trình phát bị tách khỏi vòng đời hoạt động, có thể dẫn đến phiên phát bị rò rỉ hoặc sự kiện lấy tiêu điểm bị rò rỉ, tiếp tục mà người dùng không thể dừng phát.

Nhà phát triển nên thử nghiệm ứng dụng và đưa ra ý kiến phản hồi về thay đổi hành vi nếu có bất kỳ trường hợp sử dụng âm thanh có chủ đích nào bị ảnh hưởng tiêu cực. Vui lòng báo cáo mọi vấn đề bằng trình theo dõi vấn đề về khả năng tương thích của ứng dụng Android 17 này.

Xác định các trường hợp sử dụng âm thanh nền bị ảnh hưởng

Kiểm tra việc triển khai phát âm thanh và xác định xem ứng dụng của bạn có ý định cung cấp chức năng tương tác âm thanh trong nền ngay cả trong các trường hợp có điều kiện hay không.

Nếu ứng dụng của bạn chỉ có ý định phát âm thanh hoặc sử dụng API âm thanh trong khi hiển thị một hoạt động mà người dùng có thể nhìn thấy, bao gồm cả việc sử dụng chế độ Hình trong hình (PiP), thì ứng dụng đó sẽ không chịu ảnh hưởng của bất kỳ thay đổi nào trong số này.

Nếu ứng dụng của bạn cung cấp chức năng VOIP (bao gồm cả ứng dụng gọi video), thì ứng dụng đó phải đáp ứng các yêu cầu được đưa ra cho việc phát (thường là thông qua việc sử dụng API viễn thông được đề xuất) để ghi âm thành công. Do đó, ứng dụng này không có khả năng bị ảnh hưởng.

Nếu ứng dụng của bạn dự định tiếp tục phát âm thanh khi màn hình tắt hoặc khi hoạt động của bạn không hiển thị (thường thấy nhất trong các ứng dụng phát trực tuyến nhạc hoặc ứng dụng podcast), thì ứng dụng của bạn được coi là cung cấp chức năng âm thanh nền và phải đáp ứng các yêu cầu mới.

Các trường hợp âm thanh nền có khả năng bị ảnh hưởng

Nếu ứng dụng của bạn không tuân theo mô hình tiếp tục tương tác âm thanh được bắt đầu khi ứng dụng đang mở hoặc để phản hồi một trình kích hoạt rõ ràng của người dùng, thì có khả năng chức năng của ứng dụng sẽ bị chặn mà không có thông báo.

Ví dụ: nếu ứng dụng của bạn khởi động một dịch vụ trên nền trước để phản hồi BOOT_COMPLETE và cố gắng tương tác với âm thanh, thì dịch vụ đó sẽ bị chặn.

Các phương pháp hay nhất về âm thanh nền để giảm thiểu tác động

  • Sử dụng thành phần MediaSessionService của thư viện Jetpack media3 để quản lý việc phát âm thanh trong nền.

    Nếu bạn làm như vậy, ứng dụng của bạn có thể sẽ không bị ảnh hưởng bởi việc tăng cường bảo mật trong nền do thư viện hỗ trợ quản lý vòng đời phát.

  • Nếu không sử dụng thư viện media3, bạn sẽ cần bắt đầu một mediaPlayback FGS theo cách thủ công. Luôn bắt đầu dịch vụ nền trước khi ứng dụng đang ở nền trước nếu có thể phát âm thanh trong nền.

    Ví dụ: nếu ứng dụng của bạn là một ứng dụng phát trực tuyến video thường chỉ chạy trên nền trước nhưng có một thành phần cho phép người dùng tiếp tục phát trong khi màn hình tắt, thì khi điều kiện kích hoạt phát do người dùng khởi tạo xảy ra, ứng dụng của bạn vẫn sẽ bắt đầu một dịch vụ nền trước.

    Việc này đảm bảo rằng dịch vụ nền trước được bắt đầu bằng các chức năng WIU.

  • Duy trì trạng thái hoạt động của mediaPlayback FGS trong thời gian xảy ra lỗi tạm thời dưới 10 phút.

    Nếu ứng dụng của bạn gặp lỗi tạm thời, chẳng hạn như vấn đề về việc lưu vào vùng đệm do hoạt động mạng hoặc có sự gián đoạn tạm thời dự kiến như AUDIOFOCUS_LOSS_TRANSIENT, thì ý định phát sẽ tiếp tục. Do đó, FGS của bạn sẽ vẫn hoạt động.

  • Dừng dịch vụ nền trước khi kết thúc quá trình phát và chỉ bắt đầu phát lại nếu người dùng tiếp tục phát một cách rõ ràng.

    Trong trường hợp có tín hiệu vĩnh viễn để kết thúc quá trình phát (ví dụ: nội dung đã hoàn tất mà không có tính năng tự động phát, AUDIOFOCUS_LOSS, sự kiện tạm dừng từ UMO hoặc sự kiện phím nội dung nghe nhìn) hoặc lỗi không thể khôi phục, ứng dụng của bạn sẽ ngừng tương tác âm thanh, dừng dịch vụ nền trước và kết thúc phiên phát nội dung nghe nhìn. Việc thực hiện tất cả những điều này tương ứng với quan niệm của người dùng về việc "hoàn tất" hoạt động tương tác âm thanh nền mong muốn. Sau khi thực hiện việc này, ứng dụng của bạn sẽ không còn khả năng tương tác âm thanh trong nền.

    Sau đó, nếu người dùng tiếp tục phát một cách rõ ràng, chẳng hạn như thông qua giao diện người dùng của ứng dụng hoặc thông qua nút phát của Đối tượng nội dung nghe nhìn chung, thì ý định bắt đầu phát âm thanh sẽ quay lại, dẫn đến một FGS mới bắt đầu.

  • Kiểm thử hành vi phát âm thanh bằng các lệnh shell adb.

Kiểm thử các thay đổi

Bạn có thể kiểm tra xem ứng dụng có tuân thủ hay không trên các ứng dụng chạy Android 17 trở lên (bắt đầu từ phiên bản thử nghiệm 3) bằng cách chạy lệnh ADB sau:

adb shell cmd audio set-enable-hardening <enable|disable|throw>

Lệnh này có các tuỳ chọn sau:

  • enable: Bật tất cả các quy định hạn chế về việc tăng cường bảo mật âm thanh cho mọi ứng dụng. Yêu cầu đối với dịch vụ nền trước WIU được áp dụng cho dù ứng dụng có nhắm đến Android 17 (cấp độ API 37) hay không. Ngoài ra, yêu cầu này được thực thi ngay cả khi ứng dụng đang thực hiện thay đổi đối với luồng chuông báo và có quyền đặt chuông báo chính xác.

  • disable: Tắt tất cả các quy định hạn chế về việc tăng cường bảo mật âm thanh.

  • throw: Bật tất cả các quy định hạn chế về tăng cường bảo mật âm thanh cho mọi ứng dụng, chẳng hạn như enable. Ngoài ra, cờ này cho phép các lỗi lớn, gửi IllegalStateException cho các hoạt động tương tác về âm lượng và tiêu điểm. Đối với việc phát âm thanh, phương thức ghi liên tục trả về một mã lỗi. Đối với các chế độ phát không có hoạt động ghi rõ ràng, ứng dụng sẽ gặp sự cố.

Sử dụng adb dumpsys audio hoặc logcat để xác định xem ứng dụng có gặp lỗi không thông báo do việc thực thi biện pháp tăng cường bảo mật âm thanh hay không. Nếu có, sẽ có một mục có tiền tố AudioHardening kèm theo tên gói của bạn. Nếu thông báo có chứa level: full, thì tức là ứng dụng của bạn đang chạy một dịch vụ nền trước, nhưng dịch vụ đó không có khả năng khi đang dùng. Nếu thông báo chứa level: partial, thì ứng dụng của bạn hoàn toàn không chạy dịch vụ nền trước.

Tìm hiểu về FGS có chức năng khi đang sử dụng

Nhìn chung, dịch vụ nền trước (FGS) phải được chạy khi ứng dụng đang ở nền trước để mở rộng các thao tác do người dùng thực hiện. Trong một số trường hợp cụ thể, ứng dụng được phép chạy dịch vụ nền trước khi ứng dụng đang chạy ở chế độ nền. Tuy nhiên, các dịch vụ nền trước này thường không được cấp khả năng Khi đang sử dụng (WIU).

WIU đóng vai trò là một cổng bảo mật – ngăn FGS bắt đầu từ chế độ nền tham gia vào một số hành vi nhạy cảm nhất định khi người dùng có thể không biết về hoạt động của ứng dụng. Chế độ này ngăn ứng dụng truy cập vào dữ liệu nhạy cảm như thông tin vị trí, máy ảnh hoặc micrô. Ngoài ra, kể từ Android 17, chế độ này cũng chặn các API âm thanh thường yêu cầu bối cảnh giao diện người dùng hiển thị.

Sau đây là thông tin tham khảo hữu ích:

  • FGS tiêu chuẩn: Các dịch vụ được khởi động khi ứng dụng hiển thị hoặc được cấp khả năng khởi chạy hoạt động ở chế độ nền sẽ được cấp quyền truy cập WIU.
  • Dịch vụ trên nền trước được bắt đầu ở chế độ nền (BFSL): Hầu hết các dịch vụ này không cấp quyền truy cập WIU. Các trường hợp ngoại lệ chính cấp WIU là những lượt tương tác liên quan đến ý định rõ ràng của người dùng, chẳng hạn như lượt nhấp vào thông báo, lượt tương tác với tiện ích hoặc sự kiện phím nội dung nghe nhìn từ một thiết bị bên ngoài.
  • Dịch vụ trên nền trước do hệ thống khởi động: Dịch vụ trên nền trước được cấp quyền truy cập WIU nếu được khởi động bằng tính năng uỷ quyền của máy chủ hệ thống (ví dụ: từ thư viện Jetpack Viễn thông) hoặc bằng các liên kết hệ thống đại diện cho trạng thái nền trước nâng cao để thực hiện chức năng chuyên biệt (chẳng hạn như cho VoiceInteractionService).

Đọc thêm trong phần Các hạn chế khi khởi động dịch vụ nền trước từ nền.

Danh sách đầy đủ các API âm thanh bị ảnh hưởng

Chức năng âm thanh

Kết quả

Các API chịu ảnh hưởng

Phát âm thanh

Đã tắt tiếng khi phát

Không có ngoại lệ, không có thông báo lỗi nào do bất kỳ API nào cung cấp

AudioTrack.write()

(NDK) AAudioStream_write

OpenSL ES cho Android

Mọi thư viện nội dung nghe nhìn phía máy khách quản lý việc phát như media3, Exoplayer và Oboe cũng có thể bị ảnh hưởng.

Yêu cầu quyền phát âm thanh

Trả về AUDIOFOCUS_REQUEST_FAILED

Không ảnh hưởng đến việc phát âm thanh của các ứng dụng khác, không có quyền phát âm thanh

AudioManager.requestAudioFocus()

API chế độ chuông và âm lượng

Không ảnh hưởng đến chế độ chuông hoặc âm lượng (lệnh gọi phương thức bị bỏ qua mà không có thông báo)

Không có ngoại lệ, không có thông báo lỗi nào do bất kỳ API nào cung cấp

AudioManager.setStreamVolume()

AudioManager.setStreamMute()

AudioManager.adjustStreamVolume()

AudioManager.adjustVolume()

AudioManager.adjustSuggestedStreamVolume()

AudioManager.setRingerMode()