การเพิ่มความปลอดภัยของเสียงเบื้องหลัง

ตั้งแต่ Android 17 เป็นต้นไป เฟรมเวิร์กเสียงจะบังคับใช้ข้อจำกัดเกี่ยวกับการโต้ตอบเสียงในเบื้องหลัง ซึ่งรวมถึงการเล่นเสียง คำขอโฟกัสเสียง และ API การเปลี่ยนระดับเสียง เพื่อให้มั่นใจว่าผู้ใช้เป็นผู้เริ่มการเปลี่ยนแปลงเหล่านี้โดยเจตนา

แอปทั้งหมดที่ทำงานบน Android 17 ซึ่งมีการโต้ตอบกับเสียงในเบื้องหลังเหล่านี้ต้องมีกิจกรรมที่มองเห็นได้หรือต้องเรียกใช้บริการที่ทำงานอยู่เบื้องหน้าซึ่งไม่ใช่ประเภท SHORT_SERVICE ซึ่งจะมีผลไม่ว่าแอปจะกำหนดเป้าหมายเป็น API ระดับ 37 หรือไม่ก็ตาม

หากแอปกำหนดเป้าหมายเป็น Android 17 (ระดับ API 37) จะมีข้อจำกัดเพิ่มเติม หากแอปทำงานในเบื้องหลัง แอปต้องเรียกใช้ บริการที่ทำงานอยู่เบื้องหน้าซึ่งมีความสามารถขณะใช้งาน (WIU) (ระบบจะให้ความสามารถ WIU แก่บริการเบื้องหน้า หากบริการเริ่มต้นขึ้นเพื่อตอบสนองต่อการดำเนินการที่ผู้ใช้เริ่ม หรือขณะที่แอปแสดงต่อผู้ใช้) อย่างไรก็ตาม ข้อกำหนดสำหรับความสามารถของ WIU จะได้รับการยกเว้นหากแอปได้รับสิทธิ์การปลุกในเวลาที่แน่นอน และแอปทำการเปลี่ยนแปลงสตรีมเสียงที่มีแอตทริบิวต์ USAGE_ALARM

หากแอปพยายามเรียกใช้ Audio API ขณะที่แอปไม่ได้อยู่ในวงจรที่ถูกต้อง API การเล่นเสียงและการเปลี่ยนระดับเสียงจะทำงานไม่สำเร็จโดยไม่มีการแจ้งเตือน ข้อยกเว้นหรือข้อความแสดงข้อผิดพลาด API โฟกัสเสียงล้มเหลวโดยมี รหัสผลลัพธ์ AUDIOFOCUS_REQUEST_FAILED

สาเหตุที่เราทำการเปลี่ยนแปลง

จุดประสงค์ของการนำข้อจำกัดเหล่านี้มาใช้คือเพื่อลดประสบการณ์การใช้งานเสียงในเบื้องหลังที่ผิดพลาดโดยไม่ตั้งใจ ตัวอย่างเช่น

  • ระบบอาจหยุดแอปที่เล่นเสียงโดยไม่มีบริการที่ทำงานอยู่เบื้องหน้า เมื่อแอป เลิกหยุดทำงานแล้ว แอปจะกลับมาเล่นเสียงต่อโดยไม่คาดคิด ซึ่งอาจเกิดขึ้น หลังจากนั้นหลายชั่วโมง
  • แอปที่เล่นเสียงโดยไม่มีบริการที่ทำงานอยู่เบื้องหน้าจะเผชิญกับข้อจำกัดในการเรียกใช้ที่หลากหลาย ซึ่งส่งผลให้ประสิทธิภาพเสียงไม่ราบรื่น
  • การเล่นที่แยกออกจากวงจรกิจกรรม ซึ่งอาจส่งผลให้เซสชันการเล่นหรือเหตุการณ์โฟกัสรั่วไหล ซึ่งจะดำเนินต่อไปโดยที่ผู้ใช้ไม่มีวิธีหยุดการเล่น

เราขอแนะนำให้นักพัฒนาแอปทดสอบแอปของตนและแสดงความคิดเห็นเกี่ยวกับการเปลี่ยนแปลงลักษณะการทำงาน หากมี Use Case ด้านเสียงที่ตั้งใจไว้ซึ่งได้รับผลกระทบในทางลบ โปรดรายงานปัญหาโดยใช้เครื่องมือติดตามปัญหาความเข้ากันได้ของแอปใน Android 17นี้

ระบุกรณีการใช้งานเสียงพื้นหลังที่ได้รับผลกระทบ

ตรวจสอบการติดตั้งใช้งานการเล่นเสียงและระบุว่าแอปของคุณต้องการ ให้ฟังก์ชันการโต้ตอบเสียงในเบื้องหลังแม้ในกรณีที่มีเงื่อนไข หรือไม่

หากแอปของคุณมีเจตนาที่จะเล่นเสียงหรือใช้ API เสียงขณะแสดงกิจกรรมที่ผู้ใช้มองเห็น รวมถึงการใช้โหมดภาพในภาพ (PIP) แอปจะไม่ได้รับผลกระทบจากการเปลี่ยนแปลงเหล่านี้

หากแอปของคุณมีฟังก์ชัน VoIP รวมถึงแอปวิดีโอคอล แอปจะต้องเป็นไปตามข้อกำหนดที่แนะนำสำหรับการเล่นอยู่แล้ว (โดยปกติจะผ่านการใช้ telecom APIs ที่แนะนำ) เพื่อบันทึกเสียงให้สำเร็จ จึงไม่น่าจะได้รับผลกระทบ

หากแอปของคุณตั้งใจที่จะเล่นเสียงต่อไปขณะที่หน้าจอปิดอยู่หรือขณะที่กิจกรรมของคุณมองไม่เห็น ซึ่งมักพบในแอปสตรีมมิงเพลงหรือแอปพอดแคสต์ ระบบจะถือว่าแอปของคุณมีฟังก์ชันการทำงานของเสียงในเบื้องหลังและต้องเป็นไปตามข้อกำหนดใหม่

สถานการณ์เสียงพื้นหลังที่อาจได้รับผลกระทบ

หากแอปไม่ทำตามรูปแบบของการโต้ตอบด้วยเสียงอย่างต่อเนื่อง ซึ่งเริ่มต้นขณะที่แอปเปิดอยู่ หรือเป็นการตอบสนองต่อทริกเกอร์ของผู้ใช้ที่ชัดเจน ระบบอาจระงับฟังก์ชันการทำงานของแอปโดยไม่แจ้งให้ทราบ

ตัวอย่างเช่น หากแอปของคุณเริ่มบริการที่ทำงานอยู่เบื้องหน้าเพื่อตอบสนองต่อ BOOT_COMPLETE และพยายามโต้ตอบกับเสียง ระบบจะระงับแอป

แนวทางปฏิบัติแนะนำเกี่ยวกับเสียงพื้นหลังเพื่อลดผลกระทบ

  • ใช้คอมโพเนนต์ MediaSessionService ของไลบรารี Jetpack media3 เพื่อ จัดการการเล่นเสียงในเบื้องหลัง

    หากทำเช่นนั้น แอปของคุณจะไม่ได้รับผลกระทบจากการเพิ่มความปลอดภัยในเบื้องหลังเนื่องจากไลบรารีจะช่วยจัดการวงจรการเล่น

  • หากไม่ได้ใช้ประโยชน์จากไลบรารี Media3 คุณจะต้องเริ่ม mediaPlayback FGS ด้วยตนเอง เริ่มต้นบริการที่ทำงานอยู่เบื้องหน้าเสมอในขณะที่แอปทำงานอยู่เบื้องหน้าหากอาจมีเสียงเบื้องหลัง

    เช่น หากแอปของคุณเป็นแอปสตรีมมิงวิดีโอซึ่งโดยปกติแล้วจะทำงานอยู่เบื้องหน้าเท่านั้น แต่มีฟีเจอร์ที่ให้ผู้ใช้เล่นต่อได้ขณะที่หน้าจอปิดอยู่ เมื่อทริกเกอร์การเล่นที่ผู้ใช้เริ่มต้นขึ้น แอปของคุณควรยังคงเริ่มบริการที่ทำงานอยู่เบื้องหน้า

    การทำเช่นนี้จะช่วยให้มั่นใจได้ว่าบริการที่ทำงานอยู่เบื้องหน้าจะเริ่มต้นด้วยความสามารถของ WIU

  • เปิดใช้งาน mediaPlayback FGS ต่อไปในระหว่างที่เกิดข้อผิดพลาดชั่วคราวที่ใช้เวลาไม่เกิน 10 นาที

    หากแอปมีข้อผิดพลาดชั่วคราว เช่น ปัญหาเกี่ยวกับการบัฟเฟอร์เนื่องจาก กิจกรรมเครือข่าย หรือมีการหยุดชะงักชั่วคราวที่คาดไว้ เช่น AUDIOFOCUS_LOSS_TRANSIENT ความตั้งใจที่จะเล่นควรดำเนินต่อไป ดังนั้น FGS ของคุณจึงควรยังคงใช้งานได้

  • หยุดบริการที่ทำงานอยู่เบื้องหน้าที่ส่วนท้ายของการเล่น และเริ่มการเล่นใหม่เฉพาะในกรณีที่ผู้ใช้กลับมาเล่นต่ออย่างชัดแจ้ง

    ในกรณีที่มีสัญญาณถาวรให้สิ้นสุดการเล่น (เช่น เนื้อหาเล่นจบแล้วโดยไม่มีการเล่นอัตโนมัติ มี AUDIOFOCUS_LOSS เหตุการณ์หยุดชั่วคราวจาก UMO หรือเหตุการณ์ปุ่มสื่อ) หรือเกิดข้อผิดพลาดที่กู้คืนไม่ได้ แอปของคุณควร หยุดการโต้ตอบด้วยเสียง หยุดบริการที่ทำงานอยู่เบื้องหน้า และสิ้นสุดเซสชันสื่อ การดำเนินการทั้งหมดนี้สอดคล้องกับแนวคิดของผู้ใช้ในการ "สิ้นสุด" การโต้ตอบเสียงพื้นหลังที่ต้องการ หลังจากดำเนินการนี้แล้ว แอปของคุณจะไม่มีความสามารถในการโต้ตอบกับเสียงในเบื้องหลังอีกต่อไป

    ต่อมา หากผู้ใช้กลับมาเล่นต่ออย่างชัดเจน เช่น ผ่าน UI ของแอปหรือปุ่มเล่นของออบเจ็กต์สื่อแบบสากล ความตั้งใจที่จะเริ่มเล่นเสียงควรกลับมา ซึ่งส่งผลให้ FGS เริ่มทำงานใหม่

  • ทดสอบลักษณะการทำงานของการเล่นเสียงด้วยคำสั่ง adb shell

การทดสอบการเปลี่ยนแปลง

คุณทดสอบการปฏิบัติตามข้อกำหนดของแอปในแอปที่ใช้ Android 17 ขึ้นไป (เริ่มตั้งแต่เบต้า 3) ได้โดยเรียกใช้คำสั่ง ADB ต่อไปนี้

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

คำสั่งนี้มีตัวเลือกต่อไปนี้

  • enable: เปิดใช้ข้อจำกัดการปิดช่องโหว่ของเสียงทั้งหมดสำหรับแอปทั้งหมด ข้อกำหนดสำหรับบริการที่ทำงานอยู่เบื้องหน้าของ WIU จะมีผลไม่ว่าแอปจะกำหนดเป้าหมายเป็น Android 17 (ระดับ API 37) หรือไม่ก็ตาม นอกจากนี้ เราจะบังคับใช้ข้อกำหนดนี้แม้ว่าแอปจะทำการเปลี่ยนแปลงสตรีมการปลุกและมีสิทธิ์การปลุกที่แน่นอนก็ตาม

  • disable: ปิดใช้ข้อจำกัดการเพิ่มความปลอดภัยของเสียงทั้งหมด

  • throw: เปิดใช้ข้อจำกัดการปิดช่องโหว่ของเสียงทั้งหมดสำหรับแอปทั้งหมด เช่น enable นอกจากนี้ แฟล็กนี้ยังเปิดใช้การล้มเหลวที่ดัง ซึ่งจะทำให้เกิดข้อผิดพลาดIllegalStateExceptionสำหรับการโต้ตอบเกี่ยวกับระดับเสียงและโฟกัส สำหรับการเล่นเสียง เมธอดเขียนจะแสดงรหัสข้อผิดพลาดอย่างต่อเนื่อง สำหรับการเล่น ในโหมดที่ไม่มีการเขียนอย่างชัดเจน แอปจะขัดข้อง

ใช้ adb dumpsys audio หรือ logcat เพื่อระบุว่าแอปพบข้อผิดพลาดแบบเงียบ เนื่องจากการบังคับใช้การปิดช่องโหว่ของเสียงหรือไม่ หากมีรายการดังกล่าว จะมีรายการ ที่ขึ้นต้นด้วย AudioHardening พร้อมชื่อแพ็กเกจของคุณ หากข้อความมี level: full แสดงว่าแอปของคุณกำลังเรียกใช้บริการที่ทำงานอยู่เบื้องหน้า แต่บริการดังกล่าวไม่มี ความสามารถขณะใช้งาน หากข้อความมี level: partial แสดงว่าแอปไม่ได้เรียกใช้บริการที่ทำงานอยู่เบื้องหน้าเลย

ทำความเข้าใจ FGS ที่มีความสามารถขณะใช้งาน

โดยทั่วไปแล้ว บริการที่ทำงานอยู่เบื้องหน้า (FGS) ต้องเปิดใช้ขณะที่แอปทำงานอยู่เบื้องหน้าเพื่อขยายการดำเนินการที่ผู้ใช้เริ่มต้น ในบางกรณี แอปได้รับอนุญาตให้เปิดใช้บริการที่ทำงานอยู่เบื้องหน้าขณะที่แอปทำงานอยู่ใน เบื้องหลัง อย่างไรก็ตาม โดยปกติแล้วระบบจะไม่ให้สิทธิ์ความสามารถ ขณะใช้งาน (WIU) แก่บริการที่ทำงานอยู่เบื้องหน้าเหล่านี้

WIU ทำหน้าที่เป็นประตูรักษาความปลอดภัย โดยจะป้องกันไม่ให้ FGS ที่เริ่มต้นจากเบื้องหลัง มีส่วนร่วมในพฤติกรรมที่มีความละเอียดอ่อนบางอย่างในกรณีที่ผู้ใช้อาจไม่ทราบ กิจกรรมของแอป ซึ่งจะป้องกันไม่ให้แอปเข้าถึงข้อมูลที่ละเอียดอ่อน เช่น ตำแหน่ง กล้อง หรือไมโครโฟน และตั้งแต่ Android 17 เป็นต้นไป ก็จะบล็อก API เสียง ที่มักต้องใช้บริบท UI ที่มองเห็นได้ด้วย

ดูข้อมูลอ้างอิงที่มีประโยชน์ได้ที่นี่

  • FGS มาตรฐาน: บริการที่เริ่มต้นขณะที่แอปมองเห็นได้หรือได้รับความสามารถในการเปิดกิจกรรมในเบื้องหลังจะได้รับสิทธิ์เข้าถึง WIU
  • FGS ที่เริ่มในเบื้องหลัง (BFSL): ส่วนใหญ่ไม่ได้ให้สิทธิ์เข้าถึง WIU ข้อยกเว้นหลักที่อนุญาตให้ใช้ WIU คือการโต้ตอบที่เกี่ยวข้องกับ ความตั้งใจของผู้ใช้ที่ชัดเจน เช่น การคลิกการแจ้งเตือน การโต้ตอบกับวิดเจ็ต หรือเหตุการณ์ ปุ่มสื่อจากอุปกรณ์ภายนอก
  • ระบบเริ่ม FGS: บริการที่ทำงานอยู่เบื้องหน้าจะได้รับสิทธิ์เข้าถึง WIU หากบริการดังกล่าว เริ่มต้นโดยการมอบสิทธิ์จากเซิร์ฟเวอร์ของระบบ (เช่น จากไลบรารี Jetpack ของ Telecom ) หรือโดยการเชื่อมโยงระบบที่แสดงถึงสถานะที่ทำงานอยู่เบื้องหน้าที่มีสิทธิ์สูงขึ้นเพื่อ ดำเนินการฟังก์ชันการทำงานเฉพาะ (เช่น สำหรับ VoiceInteractionService)

อ่านเพิ่มเติมได้ในข้อจำกัดในการเริ่มบริการที่ทำงานอยู่เบื้องหน้าจาก เบื้องหลัง

รายการ API เสียงทั้งหมดที่ได้รับผลกระทบ

ฟังก์ชันเสียง

ผลลัพธ์

API ที่ได้รับผลกระทบ

การเล่นเสียง

ปิดเสียงการเล่นแล้ว

ไม่มีข้อยกเว้นและไม่มีข้อความแสดงข้อผิดพลาดจาก API ใดๆ

AudioTrack.write()

(NDK) AAudioStream_write

OpenSL ES สำหรับ Android

ไลบรารีสื่อฝั่งไคลเอ็นต์ที่จัดการการเล่น เช่น media3, Exoplayer และ Oboe ก็อาจได้รับผลกระทบด้วย

คำขอโฟกัสเสียง

การคืนสินค้า AUDIOFOCUS_REQUEST_FAILED

ไม่มีผลต่อการเล่นเสียงของแอปอื่นๆ ไม่มีการโฟกัส

AudioManager.requestAudioFocus()

API ระดับเสียงและโหมดเสียงเรียกเข้า

ไม่มีผลต่อโหมดหรือระดับเสียงเรียกเข้า (ระบบจะไม่สนใจการเรียกเมธอดโดยไม่มีการแจ้งเตือน)

ไม่มีข้อยกเว้นและไม่มีข้อความแสดงข้อผิดพลาดจาก API ใดๆ

AudioManager.setStreamVolume()

AudioManager.setStreamMute()

AudioManager.adjustStreamVolume()

AudioManager.adjustVolume()

AudioManager.adjustSuggestedStreamVolume()

AudioManager.setRingerMode()