SurfaceFlinger และ WindowManager

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

SurfaceFlinger

SurfaceFlinger ยอมรับบัฟเฟอร์ได้ 2 วิธี ได้แก่ ผ่าน BufferQueue และ SurfaceControl หรือผ่าน ASurfaceControl

วิธีที่ SurfaceFlinger ยอมรับบัฟเฟอร์คือผ่าน BufferQueue และ SurfaceControl เมื่อแอปปรากฏขึ้นที่เบื้องหน้า แอปจะขอบัฟเฟอร์จาก WindowManager WindowManager จากนั้นจะขอเลเยอร์จาก SurfaceFlinger เลเยอร์คือชุดค่าผสมของ surface ซึ่งมี BufferQueue และอินสแตนซ์ SurfaceControl ซึ่งมีข้อมูลเมตาของเลเยอร์ เช่น เฟรมการแสดงผล SurfaceFlinger จะสร้างเลเยอร์และส่งไปยัง WindowManager WindowManagerจากนั้นส่ง Surface ไปยังแอป แต่เก็บอินสแตนซ์ SurfaceControl ไว้เพื่อควบคุมลักษณะที่ปรากฏของแอปบนหน้าจอ

Android 10 เพิ่ม ASurfaceControl ซึ่งเป็นอีกวิธีหนึ่งที่ SurfaceFlinger ยอมรับบัฟเฟอร์ ASurfaceControl รวมอินสแตนซ์ SurfaceControl และอินสแตนซ์ Surface เข้าเป็นแพ็กเกจธุรกรรมเดียวที่ส่งไปยัง SurfaceFlinger ASurfaceControl เชื่อมโยงกับเลเยอร์ที่แอปอัปเดตผ่านอินสแตนซ์ ASurfaceTransaction จากนั้นแอปจะได้รับข้อมูลเกี่ยวกับASurfaceTransactionอินสแตนซ์ผ่านคอลแบ็กที่ส่ง ASurfaceTransactionStats ที่มีข้อมูล เช่น เวลาแตะ เวลารับ และอื่นๆ

ตารางต่อไปนี้มีรายละเอียดเพิ่มเติมเกี่ยวกับ ASurfaceControl และคอมโพเนนต์ที่เกี่ยวข้อง

ส่วนประกอบ คำอธิบาย
ASurfaceControl ตัด SurfaceControl และช่วยให้แอปสร้างอินสแตนซ์ SurfaceControl ที่สอดคล้องกับเลเยอร์บนจอแสดงผลได้

สร้างเป็นอินสแตนซ์ย่อยของ ANativeWindow หรือเป็นอินสแตนซ์ย่อยของอินสแตนซ์ ASurfaceControl อื่นได้
ASurfaceTransaction ตัด Transaction เพื่อช่วยให้ไคลเอ็นต์แก้ไขพร็อพเพอร์ตี้ที่อธิบายของเลเยอร์ได้ เช่น เรขาคณิต และส่งบัฟเฟอร์ที่อัปเดตแล้วไปยัง SurfaceFlinger
ASurfaceTransactionStats ส่งข้อมูลเกี่ยวกับธุรกรรมที่แสดง เช่น เวลาแตะ เวลารับ และรั้วการปล่อยก่อนหน้า ไปยังแอปผ่านการเรียกกลับที่ลงทะเบียนไว้ล่วงหน้า

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

เมื่อจอแสดงผลอยู่ระหว่างการรีเฟรช จอแสดงผลจะส่งสัญญาณ VSync ไปยัง SurfaceFlinger สัญญาณ VSync บ่งบอกว่าจอแสดงผลจะรีเฟรชได้โดยไม่ฉีกขาด เมื่อ SurfaceFlinger ได้รับสัญญาณ VSync ก็จะเรียกดูรายการเลเยอร์เพื่อหาบัฟเฟอร์ใหม่ หาก SurfaceFlinger พบบัฟเฟอร์ใหม่ ก็จะรับบัฟเฟอร์นั้น หากไม่พบ ก็จะใช้บัฟเฟอร์ที่รับไว้ก่อนหน้านี้ต่อไป SurfaceFlinger ต้องแสดงข้อมูลบางอย่างเสมอ จึงจะยึดบัฟเฟอร์ไว้ 1 รายการ หากไม่เคยส่งบัฟเฟอร์ในเลเยอร์ ระบบจะไม่สนใจเลเยอร์นั้น

หลังจาก SurfaceFlinger รวบรวมบัฟเฟอร์ทั้งหมดสําหรับเลเยอร์ที่มองเห็นแล้ว ก็จะถามเครื่องมือคอมโพสิตฮาร์ดแวร์ (HWC) ว่าควรใช้การคอมโพสอย่างไร หาก HWC ระบุว่าประเภทการคอมโพสิชันเลเยอร์เป็นการคอมโพสิชันไคลเอ็นต์ SurfaceFlinger จะคอมโพสิชันเลเยอร์เหล่านั้น จากนั้น SurfaceFlinger จะส่งบัฟเฟอร์เอาต์พุตไปยัง HWC

WindowManager

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

ก่อนการหมุนเวียน

การวางซ้อนฮาร์ดแวร์จำนวนมากไม่รองรับการหมุน (และแม้ว่าจะรองรับ ก็ยังต้องใช้พลังงานในการประมวลผล) ทางออกคือการเปลี่ยนรูปแบบบัฟเฟอร์ก่อนที่จะไปถึง SurfaceFlinger Android รองรับคำแนะนำการค้นหา (NATIVE_WINDOW_TRANSFORM_HINT) ใน ANativeWindow เพื่อแสดงการเปลี่ยนรูปแบบที่มีแนวโน้มมากที่สุดที่จะใช้กับบัฟเฟอร์โดย SurfaceFlinger ไดรเวอร์ GL สามารถใช้คำแนะนำนี้เพื่อเปลี่ยนรูปแบบบัฟเฟอร์ล่วงหน้าก่อนที่จะส่งไปยัง SurfaceFlinger เพื่อให้บัฟเฟอร์ได้รับการเปลี่ยนรูปแบบอย่างถูกต้องเมื่อมาถึง

เช่น เมื่อได้รับคำแนะนำให้หมุน 90 องศา ให้สร้างและใช้เมทริกซ์กับบัฟเฟอร์เพื่อป้องกันไม่ให้แสดงที่ส่วนท้ายของหน้า โปรดดำเนินการนี้ก่อนการโรเตชันเพื่อประหยัดพลังงาน โปรดดูรายละเอียดที่อินเทอร์เฟซ ANativeWindow ที่กําหนดไว้ใน system/core/include/system/window.h