บทความนี้อธิบายว่าระบบเสียงของ Android พยายามหลีกเลี่ยงอย่างไร การกลับลำดับความสำคัญ และไฮไลต์เทคนิคต่างๆ ที่คุณสามารถนำไปใช้ได้ด้วย
เทคนิคเหล่านี้อาจเป็นประโยชน์กับนักพัฒนาซอฟต์แวร์ประสิทธิภาพสูง แอปเสียง, OEM และผู้ให้บริการ SoC ที่นำเสียงไปใช้ HAL โปรดทราบว่าการใช้เทคนิคเหล่านี้ไม่ใช่ รับประกันได้ว่าจะป้องกันข้อบกพร่องหรือการทำงานล้มเหลวอื่นๆ โดยเฉพาะอย่างยิ่ง การใช้นอกเหนือจากบริบทของเสียง ผลลัพธ์อาจแตกต่างกันไป และคุณควรดำเนินการด้วยตัวเอง การประเมินและการทดสอบ
ฉากหลัง
เซิร์ฟเวอร์เสียงของ Android AudioFlinger และ AudioTrack/AudioRecord เรากำลังปรับโครงสร้างการใช้งานไคลเอ็นต์ใหม่เพื่อลดเวลาในการตอบสนอง การทำงานนี้เริ่มต้นใน Android 4.1 และปรับปรุงต่อไป ใน 4.2, 4.3, 4.4 และ 5.0
เพื่อให้สอดคล้องกับเวลาในการตอบสนองที่น้อยลง จึงต้องทำการเปลี่ยนแปลงหลายอย่างทั่วทั้งระบบ หนึ่ง การเปลี่ยนแปลงที่สำคัญคือ การกำหนดทรัพยากร CPU ให้กับเวลาที่มีความจำเป็น ชุดข้อความที่มีนโยบายการกำหนดเวลาที่คาดการณ์ได้มากยิ่งขึ้น กำหนดการที่เชื่อถือได้ ช่วยให้สามารถลดขนาดบัฟเฟอร์ของเสียงได้ในขณะที่อยู่นิ่ง เพื่อหลีกเลี่ยงไม่ให้บริการหยุดชะงัก
การกลับลำดับความสำคัญ
การกลับลำดับความสำคัญ คือโหมดความล้มเหลวแบบคลาสสิกของระบบแบบเรียลไทม์ ที่งานที่มีลําดับความสําคัญสูงกว่าถูกบล็อกสําหรับเวลาที่ไม่มีการจํากัดเวลารอ สำหรับงานที่มีลำดับความสำคัญต่ำกว่า เพื่อปล่อยทรัพยากร เช่น ได้รับการคุ้มครองโดย) ก Mutex
ในระบบเสียง การกลับลำดับความสำคัญมักจะแสดงเป็น ข้อบกพร่อง (คลิก, จอใหญ่, เมนูแบบเลื่อนลง) เสียงซ้ำ เมื่อบัฟเฟอร์วงกลม หรือความล่าช้าในการตอบสนองคำสั่ง
วิธีแก้ปัญหาเบื้องต้นสำหรับการกลับลำดับความสำคัญคือการเพิ่มขนาดบัฟเฟอร์เสียง แต่วิธีนี้จะเพิ่มเวลาในการตอบสนองและซ่อนปัญหาไว้เท่านั้น แทนที่จะแก้ปัญหาเอง คุณจึงควรทำความเข้าใจและป้องกันลำดับความสำคัญ การกลับสีดังที่แสดงด้านล่าง
ในการใช้งานเสียงของ Android การกลับลำดับความสำคัญจะ มีโอกาสเกิดขึ้นในที่เหล่านี้ ดังนั้น คุณควรให้ความสนใจกับสิ่งต่อไปนี้:
- ระหว่างเทรดมิกเซอร์ปกติกับเทรดมิกเซอร์เร็วใน AudioFlinger
- ระหว่างเธรด Callback ของแอปพลิเคชันสำหรับ AudioTrack ที่เร็ว เทรดมิกเซอร์แบบเร็ว (ทั้ง 2 แบบต่างก็มีลำดับความสำคัญสูงกว่า แต่เล็กน้อย ลำดับความสำคัญ)
- ระหว่างเธรด Callback ของแอปพลิเคชันสำหรับ AudioRecord ที่เร็ว ชุดข้อความที่จับภาพด่วน (คล้ายกับข้อความก่อนหน้า)
- ภายในการติดตั้งใช้งาน ฮาร์ดแวร์ Abstraction Layer (HAL) สำหรับเสียง เช่น สำหรับการตัดเสียงรบกวนหรือเสียงก้อง
- ภายในไดรเวอร์เสียงในเคอร์เนล
- ระหว่างชุดข้อความ Callback หรือ AudioTrack หรือ AudioRecord กับชุดข้อความแอปอื่นๆ (ซึ่งอยู่นอกเหนือการควบคุมของเรา)
วิธีแก้ปัญหาทั่วไป
วิธีแก้ไขโดยทั่วไปมีดังนี้
- ปิดใช้การรบกวน
- Mutex ที่สืบทอดค่าลำดับความสำคัญ
ไม่สามารถปิดการรบกวนได้ในพื้นที่ของผู้ใช้ Linux และ ไม่สามารถใช้ได้กับ Symmetric Multi-Processor (SMP)
การสืบทอดลำดับความสำคัญ ฟูเท็ก (ปิดเสียงแบบ User-Space ที่รวดเร็ว) ในระบบเสียงเนื่องจากใช้งานค่อนข้างหนัก และเพราะพวกเขาพึ่งพาลูกค้าที่เชื่อถือได้
เทคนิคที่ Android ใช้
การทดสอบเริ่มต้นด้วย "try Lock" และล็อกเมื่อหมดเวลา สิ่งเหล่านี้คือ รูปแบบการบล็อกแบบไม่ใช่การบล็อกและมีแบบตายตัวของการล็อก Mutex การดำเนินการ การพยายามล็อกและล็อกการหมดเวลาทำงานได้ดีพอสมควรแต่ มีความเสี่ยงต่อโหมดทำงานล้มเหลวซึ่งไม่ชัดเจน 2 โหมด ได้แก่ ไม่มีการรับประกันว่าเซิร์ฟเวอร์จะสามารถเข้าถึงสถานะที่แชร์ได้ ไคลเอ็นต์ไม่ว่าง และระยะหมดเวลาสะสมอาจ ยาวเกินไป ถ้ามีลำดับของการล็อกที่ไม่เกี่ยวข้อง หมดเวลาทั้งหมด
เรายังใช้ การดำเนินการระดับอะตอม เช่น
- การเพิ่มขึ้น
- Bitwise "หรือ"
- Bitwise "และ"
ทุกฟังก์ชันจะแสดงค่าก่อนหน้าและรวมค่าที่จำเป็น อุปสรรคของ SMP ข้อเสียคือ โปรแกรมประเภทนี้อาจต้องมีการดำเนินการใหม่ที่ไม่มีขอบเขตจำกัด ในทางปฏิบัติ เราพบว่าการลองใหม่ไม่ใช่ปัญหา
หมายเหตุ: การทำงานของอะตอมและการโต้ตอบกับอุปสรรคทางหน่วยความจำ เป็นที่ทำให้เข้าใจผิดอย่างเลวร้ายและใช้อย่างไม่ถูกต้อง เรารวมวิธีการเหล่านี้ ที่นี่ เพื่อความครบถ้วนสมบูรณ์ แต่เราขอแนะนำให้คุณอ่านบทความ SMP Primer สำหรับ Android สำหรับข้อมูลเพิ่มเติม
เรายังคงมีและใช้เครื่องมือด้านบนเกือบทั้งหมด และเมื่อเร็วๆ นี้ ได้เพิ่มเทคนิคต่อไปนี้
- ใช้ผู้เขียนคนเดียวแบบไม่บล็อก คิว FIFO สำหรับข้อมูล
- พยายาม คัดลอก State แทนที่จะเป็น แชร์ สถานะระหว่าง โมดูลลำดับความสำคัญต่ำ
- เมื่อจำเป็นต้องแชร์สถานะ ให้จำกัดรัฐไว้เป็น ขนาดสูงสุด คำ ที่เข้าถึงได้แบบปรมาณูในการทำงานแบบ 1 คัน โดยไม่มีการลองใหม่
- สำหรับสถานะที่มีหลายคำที่ซับซ้อน ให้ใช้คิวสถานะ คิวของรัฐ ก็เป็นแค่ FIFO ของนักเขียนคนเดียวแบบไม่บล็อก คิวที่ใช้สำหรับสถานะแทนที่จะเป็นข้อมูล ยกเว้นการยุบผู้เขียน ที่ติดกันจะดันเข้าไปเพียงครั้งเดียว
- โปรดทราบ อุปสรรคทางหน่วยความจำ เพื่อดูความถูกต้องของ SMP
- เชื่อถือ แต่ยืนยัน เมื่อแชร์ สถานะ ระหว่างกระบวนการ อย่า ถือว่ารัฐมีรูปแบบที่ถูกต้อง เช่น ตรวจสอบว่าดัชนี อยู่ภายในขอบเขต ไม่จำเป็นต้องทำการยืนยันนี้ระหว่างชุดข้อความ ในกระบวนการเดียวกัน หรือระหว่างกระบวนการ สร้างความไว้วางใจร่วมกัน (ซึ่ง ตามปกติจะมี UID เดียวกัน) โดยไม่จำเป็นต้องแชร์ ข้อมูล เช่น เสียง PCM ที่ความเสียหายที่เกิดกับการค้นหาทั่วไปไม่ได้
อัลกอริทึมแบบไม่บล็อก
อัลกอริทึมแบบไม่บล็อก เป็นหัวข้อหนึ่งของการศึกษาเมื่อเร็วๆ นี้ แต่ยกเว้นคิว FIFO ของนักเขียนคนเดียวแบบอ่านคนเดียว เพราะมีความซับซ้อนและเกิดข้อผิดพลาดได้ง่าย
ตั้งแต่ Android 4.2 เป็นต้นไป คุณจะเห็นว่า ชั้นเรียนของผู้อ่าน/นักเขียนคนเดียวในพื้นที่เหล่านี้
- เฟรมเวิร์ก/av/include/media/nbaio/
- เฟรมเวิร์ก/av/media/libnbaio/
- เฟรมเวิร์ก/Av/บริการ/audioflinger/StateQueue*
ซึ่งออกแบบมาสำหรับ AudioFlinger โดยเฉพาะและไม่ อเนกประสงค์ อัลกอริทึมที่ไม่บล็อก เป็นที่รู้กันว่า แก้ไขข้อบกพร่องได้ยาก คุณสามารถดูโค้ดนี้เป็นโมเดลได้ แต่เป็น อาจจะมีข้อบกพร่อง และเราไม่รับประกันว่าชั้นเรียนจะมี เหมาะสำหรับวัตถุประสงค์อื่นๆ
สำหรับนักพัฒนาซอฟต์แวร์ ตัวอย่างโค้ดของแอปพลิเคชัน OpenSL ES บางส่วนควรได้รับการอัปเดตเป็น ใช้อัลกอริทึมแบบไม่บล็อกหรืออ้างอิงไลบรารีโอเพนซอร์สที่ไม่ใช่ Android
เราได้เผยแพร่ตัวอย่างการใช้งาน FIFO แบบไม่บล็อก ซึ่งออกแบบมาเพื่อ
โค้ดของแอปพลิเคชัน ดูไฟล์เหล่านี้ในไดเรกทอรีแหล่งที่มาของแพลตฟอร์ม
frameworks/av/audio_utils
:
เครื่องมือ
เท่าที่เราทราบ ตอนนี้ไม่มีเครื่องมืออัตโนมัติสำหรับ
เพื่อหาการกลับลำดับความสำคัญ โดยเฉพาะก่อนที่จะเกิดขึ้น ใช้บ้าง
การวิจัย เครื่องมือวิเคราะห์โค้ดแบบคงที่สามารถหาลำดับความสำคัญ
การกลับด้าน หากสามารถเข้าถึงฐานของโค้ดทั้งหมดได้ แน่นอน ถ้า
ต้องใช้รหัสผู้ใช้ที่กำหนดเอง (ตามที่แสดงในแอปพลิเคชัน)
หรือเป็นฐานของโค้ดขนาดใหญ่ (เช่น สำหรับเคอร์เนลและไดรเวอร์อุปกรณ์ของ Linux)
การวิเคราะห์แบบคงที่อาจไม่สามารถปฏิบัติได้ สิ่งสำคัญที่สุดคือ
อ่านโค้ดอย่างละเอียดและเข้าใจข้อมูลทั้งหมด
และปฏิสัมพันธ์ เครื่องมือ เช่น
Systrace
และ
ps -t -p
มีประโยชน์ในการดูการกลับลำดับความสำคัญหลังจากเกิดขึ้น แต่
ไม่ได้บอกคุณล่วงหน้า
คำพูดสุดท้าย
หลังจากการพูดคุยทั้งหมดนี้ ไม่ต้องกังวลไป ปิดเสียง เป็นเพื่อนสำหรับการใช้งานทั่วไป เมื่อมีการใช้และใช้งานอย่างถูกต้อง ใน Use Case ที่ไม่สำคัญในเวลาปกติทั่วไป แต่ระหว่างเนื้อหาระดับสูงกับ งานที่มีลำดับความสำคัญต่ำและการปิดเสียงของระบบที่มีการจำกัดเวลามีมากกว่า ก็น่าจะทำให้เกิดปัญหา