SurfaceFlinger และ WindowManager

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

SurfaceFlinger

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

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

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

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

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

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

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

หลังจากที่ SurfaceFlinger รวบรวมบัฟเฟอร์ทั้งหมดสำหรับเลเยอร์ที่มองเห็นได้แล้ว ก็จะถาม Hardware Composer (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