SurfaceFlinger และ WindowManager

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

SurfaceFlinger

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

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

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

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

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

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

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

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

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

ตัวจัดการหน้าต่าง

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

การหมุนล่วงหน้า

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

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