การอัปเดตที่ทำในพื้นที่เฉพาะการแสดงผลเหล่านี้มีดังต่อไปนี้:
- การปรับขนาดกิจกรรมและการแสดงผล
- ขนาดการแสดงผลและอัตราส่วนภาพ
- นโยบายการแสดงผล
- การตั้งค่าหน้าต่างการแสดงผล
- ตัวระบุการแสดงผลแบบคงที่
- การใช้จอแสดงผลมากกว่าสองจอ
- โฟกัสต่อการแสดงผล
ปรับขนาดกิจกรรมและการแสดงผล
เพื่อระบุว่าแอปอาจไม่รองรับโหมดหลายหน้าต่างหรือการปรับขนาด กิจกรรมจะใช้แอตทริบิวต์ resizeableActivity=false
ปัญหาทั่วไปที่แอพพบเมื่อมีการปรับขนาดกิจกรรม ได้แก่:
- กิจกรรมอาจมีการกำหนดค่าที่แตกต่างจากแอปหรือส่วนประกอบอื่นที่ไม่ใช่ภาพ ข้อผิดพลาดทั่วไปคือการอ่านเมตริกการแสดงผลจากบริบทของแอป ค่าที่ส่งคืนจะไม่ถูกปรับเป็นเมตริกพื้นที่ที่มองเห็นได้ซึ่งมีกิจกรรมแสดงอยู่
- กิจกรรมอาจไม่รองรับการปรับขนาดและข้อขัดข้อง แสดง UI ที่บิดเบี้ยว หรือสูญเสียสถานะเนื่องจากการเปิดใหม่โดยไม่บันทึกสถานะอินสแตนซ์
- แอปอาจพยายามใช้พิกัดอินพุตสัมบูรณ์ (แทนที่จะเป็นพิกัดที่สัมพันธ์กับตำแหน่งหน้าต่าง) ซึ่งอาจทำให้อินพุตในหลายหน้าต่างเสียหาย
ใน Android 7 (และสูงกว่า) สามารถตั้งค่าแอป resizeableActivity=false
ให้ทำงานในโหมดเต็มหน้าจอได้ตลอดเวลา ในกรณีนี้ แพลตฟอร์มจะป้องกันไม่ให้กิจกรรมที่ไม่สามารถปรับขนาดได้เข้าสู่หน้าจอแยก หากผู้ใช้พยายามเรียกใช้กิจกรรมที่ไม่สามารถปรับขนาดได้จากตัวเรียกใช้งานในขณะที่อยู่ในโหมดแบ่งหน้าจออยู่แล้ว แพลตฟอร์มจะออกจากโหมดแบ่งหน้าจอและเปิดกิจกรรมที่ไม่สามารถปรับขนาดได้ในโหมดเต็มหน้าจอ
แอปที่ตั้งค่าแอตทริบิวต์นี้เป็น false
อย่างชัดเจนในรายการจะต้องไม่เปิดในโหมดหลายหน้าต่าง เว้นแต่จะใช้โหมดความเข้ากันได้:
- มีการใช้การตั้งค่าคอนฟิกเดียวกันกับกระบวนการ ซึ่งประกอบด้วยกิจกรรมและส่วนประกอบที่ไม่ใช่กิจกรรมทั้งหมด
- การกำหนดค่าที่ใช้เป็นไปตามข้อกำหนด CDD สำหรับจอแสดงผลที่เข้ากันได้กับแอป
ใน Android 10 แพลตฟอร์มยังคงป้องกันไม่ให้กิจกรรมที่ไม่สามารถปรับขนาดได้เข้าสู่โหมดแบ่งหน้าจอ แต่สามารถปรับขนาดได้ชั่วคราวหากกิจกรรมได้ประกาศการวางแนวหรืออัตราส่วนภาพคงที่ ถ้าไม่เช่นนั้น กิจกรรมจะปรับขนาดให้เต็มหน้าจอเหมือนกับใน Android 9 และต่ำกว่า
การใช้งานเริ่มต้นจะใช้นโยบายต่อไปนี้:
เมื่อกิจกรรมที่ประกาศว่าเข้ากันไม่ได้กับหลายหน้าต่างผ่านการใช้แอตทริบิวต์ android:resizeableActivity
และเมื่อกิจกรรมนั้นตรงตามเงื่อนไขข้อใดข้อหนึ่งที่อธิบายไว้ด้านล่าง เมื่อต้องเปลี่ยนการกำหนดค่าหน้าจอที่ใช้ กิจกรรมและกระบวนการจะถูกบันทึกด้วยการกำหนดค่าดั้งเดิม และผู้ใช้จะได้รับสิทธิ์ในการเปิดกระบวนการแอปอีกครั้งเพื่อใช้การกำหนดค่าหน้าจอที่อัปเดต
- มีการวางแนวคงที่ผ่านแอปพลิเคชัน
android:screenOrientation
- แอปมีอัตราส่วนกว้างยาวสูงสุดหรือต่ำสุดเริ่มต้นโดยการกำหนดเป้าหมายระดับ API หรือประกาศอัตราส่วนอย่างชัดเจน
รูปนี้แสดงกิจกรรมที่ไม่สามารถปรับขนาดได้โดยมีอัตราส่วนกว้างยาวที่ประกาศไว้ เมื่อพับอุปกรณ์ หน้าต่างจะถูกย่อขนาดลงเพื่อให้พอดีกับพื้นที่โดยยังคงรักษาอัตราส่วนไว้โดยใช้แถบดำแถบดำที่เหมาะสม นอกจากนี้ ผู้ใช้จะมีตัวเลือกกิจกรรมการรีสตาร์ททุกครั้งที่พื้นที่แสดงผลสำหรับกิจกรรมมีการเปลี่ยนแปลง
เมื่อกางอุปกรณ์ออก การกำหนดค่า ขนาด และอัตราส่วนภาพของกิจกรรมจะไม่เปลี่ยนแปลง แต่ตัวเลือกในการรีสตาร์ทกิจกรรมจะปรากฏขึ้น
เมื่อไม่ได้ตั้ง resizeableActivity
(หรือตั้งค่าเป็น true
) แอปจะรองรับการปรับขนาดอย่างสมบูรณ์
การนำไปปฏิบัติ
กิจกรรมที่ไม่สามารถปรับขนาดได้ซึ่งมีการวางแนวหรืออัตราส่วนภาพคงที่เรียกว่าโหมดความเข้ากันได้ของขนาด (SCM) ในโค้ด เงื่อนไขถูกกำหนดไว้ใน ActivityRecord#shouldUseSizeCompatMode()
เมื่อเปิดใช้งานกิจกรรม SCM การกำหนดค่าที่เกี่ยวข้องกับหน้าจอ (เช่น ขนาดหรือความหนาแน่น) จะได้รับการแก้ไขในการกำหนดค่าแทนที่ที่ร้องขอ ดังนั้นกิจกรรมจึงไม่ขึ้นอยู่กับการกำหนดค่าการแสดงผลปัจจุบันอีกต่อไป
หากกิจกรรม SCM ไม่สามารถเติมเต็มทั้งหน้าจอได้ กิจกรรมนั้นจะจัดชิดด้านบนและจัดกึ่งกลางแนวนอน ขอบเขตของกิจกรรมคำนวณโดย AppWindowToken#calculateCompatBoundsTransformation()
เมื่อกิจกรรม SCM ใช้การกำหนดค่าหน้าจอที่แตกต่างจากคอนเทนเนอร์ (เช่น จอแสดงผลถูกปรับขนาด หรือกิจกรรมถูกย้ายไปยังจอแสดงผลอื่น) ActivityRecord#inSizeCompatMode()
เป็นจริง และ SizeCompatModeActivityController
(ใน System UI) ได้รับการติดต่อกลับเพื่อแสดงกระบวนการ ปุ่มรีสตาร์ท
ขนาดการแสดงผลและอัตราส่วนภาพ
Android 10 ให้การสนับสนุนอัตราส่วนภาพใหม่ตั้งแต่อัตราส่วนหน้าจอที่ยาวและบางในระดับสูงไปจนถึงอัตราส่วน 1:1 แอปสามารถกำหนด ApplicationInfo#maxAspectRatio
และ ApplicationInfo#minAspectRatio
ของหน้าจอที่แอปสามารถจัดการได้
รูปที่ 1 ตัวอย่างอัตราส่วนแอปที่รองรับใน Android 10
การใช้งานอุปกรณ์สามารถมีจอแสดงผลรองที่มีขนาดและความละเอียดเล็กกว่าที่กำหนดโดย Android 9 และต่ำกว่า (ความกว้างหรือความสูงขั้นต่ำ 2.5 นิ้ว ขั้นต่ำ 320 DP สำหรับ smallestScreenWidth
) แต่เฉพาะกิจกรรมที่เลือกใช้เพื่อรองรับจอแสดงผลขนาดเล็กเหล่านี้เท่านั้นที่สามารถทำได้ วางไว้ที่นั่น
แอปสามารถเลือกใช้งานได้โดยประกาศขนาดขั้นต่ำที่รองรับซึ่งเล็กกว่า oe เท่ากับขนาดการแสดงผลเป้าหมาย ใช้แอตทริบิวต์เค้าโครงกิจกรรม android:minHeight
และ android:minWidth
ใน AndroidManifest เพื่อดำเนินการดังกล่าว
นโยบายการแสดงผล
Android 10 แยกและย้ายนโยบายการแสดงผลบางอย่างจากการใช้งาน WindowManagerPolicy
เริ่มต้นใน PhoneWindowManager
ไปยังคลาสต่อการแสดงผล เช่น:
- แสดงสถานะและการหมุน
- ปุ่มบางปุ่มและการติดตามเหตุการณ์การเคลื่อนไหว
- UI ระบบและหน้าต่างตกแต่ง
ใน Android 9 (และต่ำกว่า) คลาส PhoneWindowManager
จัดการนโยบายการแสดงผล สถานะและการตั้งค่า การหมุน การติดตามกรอบหน้าต่างการตกแต่ง และอื่นๆ Android 10 ย้ายส่วนใหญ่ไปยังคลาส DisplayPolicy
ยกเว้นการติดตามการหมุนซึ่งถูกย้ายไปที่ DisplayRotation
การตั้งค่าหน้าต่างการแสดงผล
ใน Android 10 การตั้งค่าหน้าต่างต่อการแสดงผลที่กำหนดค่าได้ได้รับการขยายให้ครอบคลุมถึง:
- โหมดหน้าต่างแสดงผลเริ่มต้น
- ค่าโอเวอร์สแกน
- การหมุนและโหมดการหมุนของผู้ใช้
- ขนาดที่บังคับ ความหนาแน่น และโหมดการปรับขนาด
- โหมดการลบเนื้อหา (เมื่อนำจอแสดงผลออก)
- รองรับการตกแต่งระบบและ IME
คลาส DisplayWindowSettings
ประกอบด้วยการตั้งค่าสำหรับตัวเลือกเหล่านี้ สิ่งเหล่านี้จะยังคงอยู่ในดิสก์ใน /data
พาร์ติชันใน display_settings.xml
ทุกครั้งที่มีการเปลี่ยนแปลงการตั้งค่า สำหรับรายละเอียด โปรดดูที่ DisplayWindowSettings.AtomicFileStorage
และ DisplayWindowSettings#writeSettings()
ผู้ผลิตอุปกรณ์สามารถระบุค่าเริ่มต้นใน display_settings.xml
สำหรับการกำหนดค่าอุปกรณ์ของตนได้ อย่างไรก็ตาม เนื่องจากไฟล์ถูกจัดเก็บไว้ใน /data
จึงอาจจำเป็นต้องใช้ตรรกะเพิ่มเติมในการกู้คืนไฟล์หากถูกลบด้วยการล้างข้อมูล
ตามค่าเริ่มต้น Android 10 จะใช้ DisplayInfo#uniqueId
เป็นตัวระบุสำหรับจอแสดงผลเมื่อคงการตั้งค่าไว้ ควรมีการระบุ uniqueId
สำหรับจอแสดงผลทั้งหมด นอกจากนี้ยังมีความเสถียรสำหรับการแสดงผลแบบฟิสิคัลและแบบเครือข่าย นอกจากนี้ยังสามารถใช้พอร์ตของจอแสดงผลจริงเป็นตัวระบุได้ ซึ่งสามารถตั้งค่าได้ใน DisplayWindowSettings#mIdentifier
ในการเขียนแต่ละครั้ง การตั้งค่าทั้งหมดจะถูกเขียน ดังนั้นจึงปลอดภัยที่จะอัปเดตคีย์ที่ใช้สำหรับรายการแสดงผลในพื้นที่จัดเก็บข้อมูล สำหรับรายละเอียด โปรดดู ตัวระบุการแสดงผลแบบคงที่
การตั้งค่าจะยังคงอยู่ในไดเร็กทอรี /data
ด้วยเหตุผลทางประวัติศาสตร์ เดิมทีใช้เพื่อคงการตั้งค่าที่ผู้ใช้กำหนดไว้ เช่น การหมุนจอแสดงผล
ตัวระบุการแสดงผลแบบคงที่
Android 9 (และต่ำกว่า) ไม่มีตัวระบุที่เสถียรสำหรับการแสดงผลในเฟรมเวิร์ก เมื่อเพิ่มจอแสดงผลลงในระบบ Display#mDisplayId
หรือ DisplayInfo#displayId
จะถูกสร้างขึ้นสำหรับจอแสดงผลนั้นโดยการเพิ่มตัวนับแบบคงที่ หากระบบเพิ่มและลบจอแสดงผลเดียวกัน จะเกิด ID อื่น
หากอุปกรณ์มีจอแสดงผลหลายจอตั้งแต่บูต จอแสดงผลอาจได้รับการกำหนดตัวระบุที่แตกต่างกัน ขึ้นอยู่กับช่วงเวลา แม้ว่า Android 9 (และรุ่นก่อนหน้า) จะรวม DisplayInfo#uniqueId
ไว้ แต่ก็มีข้อมูลไม่เพียงพอที่จะแยกความแตกต่างระหว่างจอแสดงผลต่างๆ เนื่องจากจอแสดงผลทางกายภาพถูกระบุเป็น local:0
หรือ local:1
เพื่อแสดงถึงจอแสดงผลในตัวและจอแสดงผลภายนอก
Android 10 เปลี่ยน DisplayInfo#uniqueId
เพื่อเพิ่มตัวระบุที่เสถียร และเพื่อแยกความแตกต่างระหว่างจอแสดงผลภายใน เครือข่าย และเสมือน
ประเภทการแสดงผล | รูปแบบ |
---|---|
ท้องถิ่น | local:<stable-id> |
เครือข่าย | network:<mac-address> |
เสมือน | virtual:<package-name-and-name> |
นอกจากการอัปเดตของ uniqueId
แล้ว DisplayInfo.address
ยังมี DisplayAddress
ซึ่งเป็นตัวระบุการแสดงผลที่เสถียรตลอดการรีบูต ใน Android 10 DisplayAddress
รองรับการแสดงผลทางกายภาพและเครือข่าย DisplayAddress.Physical
มี ID การแสดงผลที่เสถียร (เหมือนกับใน uniqueId
) และสามารถสร้างได้ด้วย DisplayAddress#fromPhysicalDisplayId()
Android 10 ยังมีวิธีที่สะดวกในการรับข้อมูลพอร์ต ( Physical#getPort()
) วิธีการนี้สามารถใช้ในกรอบงานเพื่อระบุจอแสดงผลแบบคงที่ได้ ตัวอย่างเช่น ใช้ใน DisplayWindowSettings
) DisplayAddress.Network
มีที่อยู่ MAC และสามารถสร้างได้ด้วย DisplayAddress#fromMacAddress()
ส่วนเพิ่มเติมเหล่านี้ช่วยให้ผู้ผลิตอุปกรณ์สามารถระบุจอแสดงผลในการตั้งค่าจอแสดงผลหลายจอแบบคงที่ และกำหนดค่าการตั้งค่าระบบและคุณสมบัติต่างๆ ได้โดยใช้ตัวระบุจอแสดงผลแบบคงที่ เช่น พอร์ตสำหรับจอแสดงผลทางกายภาพ วิธีการเหล่านี้ถูกซ่อนไว้และมีวัตถุประสงค์เพื่อใช้ภายใน system_server
เท่านั้น
เมื่อกำหนด ID การแสดงผล HWC (ซึ่งอาจทึบแสงและไม่เสถียรเสมอไป) วิธีการนี้จะส่งคืนหมายเลขพอร์ต 8 บิต (เฉพาะแพลตฟอร์ม) ที่ระบุตัวเชื่อมต่อทางกายภาพสำหรับเอาต์พุตการแสดงผล รวมถึง EDID blob ของจอแสดงผล SurfaceFlinger แยกข้อมูลผู้ผลิตหรือรุ่นจาก EDID เพื่อสร้าง ID การแสดงผล 64 บิตที่เสถียรซึ่งเปิดเผยต่อเฟรมเวิร์ก หากวิธีนี้ไม่รองรับหรือเกิดข้อผิดพลาด SurfaceFlinger จะถอยกลับไปยังโหมด MD ดั้งเดิม โดยที่ DisplayInfo#address
เป็น null และ DisplayInfo#uniqueId
เป็นแบบฮาร์ดโค้ด ตามที่อธิบายไว้ข้างต้น
เพื่อตรวจสอบว่าคุณสมบัตินี้ได้รับการสนับสนุน ให้รัน:
$ dumpsys SurfaceFlinger --display-id # Example output. Display 21691504607621632 (HWC display 0): port=0 pnpId=SHP displayName="LQ123P1JX32" Display 9834494747159041 (HWC display 2): port=1 pnpId=HWP displayName="HP Z24i" Display 1886279400700944 (HWC display 1): port=2 pnpId=AUS displayName="ASUS MB16AP"
ใช้จอแสดงผลมากกว่าสองจอ
ใน Android 9 (และต่ำกว่า) SurfaceFlinger และ DisplayManagerService
ถือว่ามีจอแสดงผลจริงสูงสุดสองจอที่มีรหัสฮาร์ดโค้ด 0 และ 1
ตั้งแต่ Android 10 เป็นต้นไป SurfaceFlinger สามารถใช้ประโยชน์จาก Hardware Composer (HWC) API เพื่อสร้าง ID การแสดงผลที่เสถียร ซึ่งช่วยให้สามารถจัดการการแสดงผลทางกายภาพตามจำนวนที่ต้องการได้ หากต้องการเรียนรู้เพิ่มเติม โปรดดูที่ ตัวระบุการแสดงผลแบบคงที่
เฟรมเวิร์กสามารถค้นหาโทเค็น IBinder
สำหรับการแสดงผลจริงผ่าน SurfaceControl#getPhysicalDisplayToken
หลังจากได้รับ ID การแสดงผล 64 บิตจาก SurfaceControl#getPhysicalDisplayIds
หรือจากเหตุการณ์ HotPlug DisplayEventReceiver
ใน Android 10 (และต่ำกว่า) จอแสดงผลภายในหลักคือ TYPE_INTERNAL
และจอแสดงผลรองทั้งหมดจะถูกตั้งค่าสถานะเป็น TYPE_EXTERNAL
โดยไม่คำนึงถึงประเภทการเชื่อมต่อ ดังนั้น จอแสดงผลภายในเพิ่มเติมจะถือเป็นจอแสดงผลภายนอก เพื่อเป็นวิธีแก้ปัญหา รหัสเฉพาะอุปกรณ์สามารถตั้งสมมติฐานเกี่ยวกับ DisplayAddress.Physical#getPort
ได้ หากทราบ HWC และตรรกะการจัดสรรพอร์ตสามารถคาดเดาได้
ข้อจำกัดนี้จะถูกลบออกใน Android 11 (และสูงกว่า)
- ใน Android 11 จอแสดงผลแรกที่รายงานระหว่างการบู๊ตคือจอแสดงผลหลัก ประเภทการเชื่อมต่อ (ภายในและภายนอก) ไม่มีความเกี่ยวข้อง อย่างไรก็ตาม ยังคงเป็นความจริงที่ว่าจอแสดงผลหลักไม่สามารถถอดออกได้ และในทางปฏิบัติแล้วจะต้องเป็นจอแสดงผลภายใน โปรดทราบว่าโทรศัพท์แบบพับได้บางรุ่นมีจอแสดงผลภายในหลายจอ
- จอแสดงผลรองได้รับการจัดหมวดหมู่อย่างถูกต้องเป็น
Display.TYPE_INTERNAL
หรือDisplay.TYPE_EXTERNAL
(เดิมชื่อDisplay.TYPE_BUILT_IN
และDisplay.TYPE_HDMI
ตามลำดับ) ขึ้นอยู่กับประเภทการเชื่อมต่อ
การนำไปปฏิบัติ
ใน Android 9 และต่ำกว่า จอแสดงผลจะถูกระบุด้วย ID 32 บิต โดยที่ 0 คือจอแสดงผลภายใน 1 คือจอแสดงผลภายนอก [2, INT32_MAX]
คือจอแสดงผลเสมือน HWC และ -1 หมายถึงจอแสดงผลที่ไม่ถูกต้องหรือไม่ใช่ HWC จอแสดงผลเสมือนจริง
เริ่มตั้งแต่ Android 10 เป็นต้นไป จอแสดงผลจะได้รับ ID ที่เสถียรและคงอยู่ ซึ่งช่วยให้ SurfaceFlinger และ DisplayManagerService
ติดตามจอแสดงผลมากกว่าสองจอและจดจำจอแสดงผลที่เห็นก่อนหน้านี้ หาก HWC รองรับ IComposerClient.getDisplayIdentificationData
และให้ข้อมูลการระบุจอแสดงผล SurfaceFlinger จะแยกวิเคราะห์โครงสร้าง EDID และจัดสรร ID การแสดงผล 64 บิตที่เสถียรสำหรับจอแสดงผลจริงและจอแสดงผลเสมือน HWC ID จะแสดงโดยใช้ประเภทตัวเลือก โดยที่ค่า Null แสดงถึงการแสดงผลที่ไม่ถูกต้องหรือการแสดงผลเสมือนที่ไม่ใช่ HWC หากไม่มีการสนับสนุน HWC SurfaceFlinger จะกลับไปใช้ลักษณะการทำงานแบบเดิมโดยมีจอแสดงผลทางกายภาพไม่เกินสองจอ
โฟกัสต่อการแสดงผล
เพื่อรองรับแหล่งอินพุตหลายแหล่งที่กำหนดเป้าหมายจอแสดงผลแต่ละจอพร้อมกัน คุณสามารถกำหนดค่า Android 10 ให้รองรับหน้าต่างที่โฟกัสหลายหน้าต่างได้มากที่สุดหนึ่งหน้าต่างต่อจอแสดงผล สิ่งนี้มีไว้สำหรับอุปกรณ์ประเภทพิเศษเท่านั้นเมื่อผู้ใช้หลายคนโต้ตอบกับอุปกรณ์เดียวกันในเวลาเดียวกันและใช้วิธีการป้อนข้อมูลหรืออุปกรณ์ที่แตกต่างกัน เช่น Android Automotive
ขอแนะนำอย่างยิ่งว่า อย่า เปิดใช้งานคุณสมบัตินี้กับอุปกรณ์ทั่วไป รวมถึงอุปกรณ์ที่มีหลายหน้าจอหรืออุปกรณ์ที่ใช้สำหรับประสบการณ์แบบเดสก์ท็อป นี่เป็นสาเหตุหลักมาจากข้อกังวลด้านความปลอดภัยที่อาจทำให้ผู้ใช้สงสัยว่าหน้าต่างใดมีโฟกัสการป้อนข้อมูล
ลองนึกภาพผู้ใช้ที่ป้อนข้อมูลที่ปลอดภัยในช่องป้อนข้อความ อาจเข้าสู่ระบบแอปธนาคารหรือป้อนข้อความที่มีข้อมูลที่ละเอียดอ่อน แอพที่เป็นอันตรายสามารถสร้างการแสดงผลเสมือนนอกหน้าจอเพื่อดำเนินกิจกรรม รวมถึงช่องป้อนข้อความด้วย กิจกรรมที่ถูกกฎหมายและเป็นอันตรายมีการมุ่งเน้นและทั้งสองจะแสดงตัวบ่งชี้อินพุตที่ใช้งานอยู่ (เคอร์เซอร์กะพริบ)
อย่างไรก็ตาม เนื่องจากการป้อนข้อมูลจากแป้นพิมพ์ (ฮาร์ดแวร์หรือซอฟต์แวร์) จะถูกป้อนเข้าสู่กิจกรรมระดับบนสุดเท่านั้น (แอปที่เปิดตัวล่าสุด) ด้วยการสร้างจอแสดงผลเสมือนที่ซ่อนอยู่ แอปที่เป็นอันตรายจึงสามารถดึงข้อมูลจากผู้ใช้ได้ แม้ว่าจะใช้แป้นพิมพ์ซอฟต์แวร์ก็ตาม บนหน้าจออุปกรณ์หลัก
ใช้ com.android.internal.R.bool.config_perDisplayFocusEnabled
เพื่อตั้งค่าโฟกัสต่อการแสดงผล
ความเข้ากันได้
ปัญหา: ใน Android 9 และต่ำกว่า หน้าต่างในระบบมีโฟกัสได้สูงสุดครั้งละหนึ่งหน้าต่าง
วิธีแก้ไข: ในกรณีที่พบไม่บ่อยเมื่อหน้าต่างสองบานจากกระบวนการเดียวกันถูกโฟกัส ระบบจะให้โฟกัสเฉพาะหน้าต่างที่อยู่สูงกว่าในลำดับ Z ข้อจำกัดนี้จะถูกลบออกสำหรับแอปที่กำหนดเป้าหมายเป็น Android 10 ซึ่ง ณ จุดนี้คาดว่าจะสามารถรองรับหลายหน้าต่างที่โฟกัสพร้อมกันได้
การนำไปปฏิบัติ
WindowManagerService#mPerDisplayFocusEnabled
ควบคุมความพร้อมใช้งานของคุณลักษณะนี้ ใน ActivityManager
ตอน ActivityDisplay#getFocusedStack()
ถูกใช้แทนการติดตามทั่วโลกในตัวแปร ActivityDisplay#getFocusedStack()
กำหนดโฟกัสตามลำดับ Z แทนที่จะแคชค่า นี่เป็นเพราะว่า WindowManager แหล่งเดียวเท่านั้นที่ต้องติดตามลำดับ Z ของกิจกรรม
ActivityStackSupervisor#getTopDisplayFocusedStack()
ใช้แนวทางที่คล้ายกันสำหรับกรณีเหล่านั้นเมื่อต้องระบุสแต็กที่โฟกัสบนสุดในระบบ สแต็กจะถูกสำรวจจากบนลงล่าง เพื่อค้นหาสแต็กที่มีสิทธิ์แรกที่มีสิทธิ์
ขณะนี้ InputDispatcher
สามารถมีหน้าต่างที่โฟกัสได้หลายหน้าต่าง (หนึ่งหน้าต่างต่อจอแสดงผล) หากเหตุการณ์อินพุตเป็นแบบเฉพาะการแสดงผล เหตุการณ์นั้นจะถูกส่งไปยังหน้าต่างที่โฟกัสในจอแสดงผลที่เกี่ยวข้อง มิฉะนั้น จะถูกส่งไปยังหน้าต่างที่โฟกัสในจอแสดงผลที่โฟกัส ซึ่งเป็นจอแสดงผลที่ผู้ใช้โต้ตอบด้วยล่าสุด
โปรดดูที่ InputDispatcher::mFocusedWindowHandlesByDisplay
และ InputDispatcher::setFocusedDisplay()
แอปที่มุ่งเน้นยังได้รับการอัปเดตแยกต่างหากใน InputManagerService ผ่าน NativeInputManager::setFocusedApplication()
ใน WindowManager
หน้าต่างที่โฟกัสจะถูกติดตามแยกกันเช่นกัน ดู DisplayContent#mCurrentFocus
และ DisplayContent#mFocusedApp
และการใช้งานที่เกี่ยวข้อง วิธีการติดตามและอัปเดตโฟกัสที่เกี่ยวข้องได้ถูกย้ายจาก WindowManagerService
ไปยัง DisplayContent