การอัปเดตที่ทํากับพื้นที่เฉพาะของจอแสดงผลมีดังนี้
- การปรับขนาดกิจกรรมและการแสดงผล
- ขนาดการแสดงผลและอัตราส่วน
- นโยบายดิสเพลย์
- การตั้งค่าหน้าต่างการแสดงผล
- ตัวระบุโฆษณาแบบดิสเพลย์แบบคงที่
- การใช้จอแสดงผลมากกว่า 2 จอ
- โฟกัสต่อจอแสดงผล
ปรับขนาดกิจกรรมและจอแสดงผล
กิจกรรมจะใช้แอตทริบิวต์ resizeableActivity=false
เพื่อระบุว่าแอปอาจไม่รองรับโหมดหลายหน้าต่างหรือการปรับขนาด ปัญหาที่พบได้ทั่วไปซึ่งแอปพบเมื่อปรับขนาดกิจกรรมมีดังนี้
- กิจกรรมอาจมีการกำหนดค่าที่แตกต่างจากแอปหรือคอมโพเนนต์อื่นๆ ที่ไม่มีภาพ ข้อผิดพลาดที่พบบ่อยคือการอ่านเมตริก Display จากบริบทแอป ระบบจะไม่ปรับค่าที่แสดงผลเป็นเมตริกพื้นที่ที่มองเห็นได้ซึ่งมีกิจกรรมแสดงอยู่
- กิจกรรมอาจไม่สามารถจัดการการปรับขนาดและข้อขัดข้อง แสดง UI ที่บิดเบี้ยว หรือสถานะสูญหายเนื่องจากการเปิดอีกครั้งโดยไม่บันทึกสถานะอินสแตนซ์
- แอปอาจพยายามใช้พิกัดอินพุตแบบสัมบูรณ์ (แทนที่จะเป็นพิกัดที่สัมพันธ์กับตำแหน่งหน้าต่าง) ซึ่งอาจทำให้อินพุตในหน้าต่างหลายหน้าต่างเสียหาย
ใน Android 7 (และเวอร์ชันที่ใหม่กว่า) คุณสามารถตั้งค่าแอปให้ทำงานในโหมดเต็มหน้าจอเสมอได้
resizeableActivity=false
ในกรณีนี้ แพลตฟอร์มจะป้องกันไม่ให้กิจกรรมแบบปรับขนาดไม่ได้แยกหน้าจอ หากผู้ใช้พยายามเรียกใช้กิจกรรมที่ปรับขนาดไม่ได้จากตัวเปิดแอปขณะที่อยู่ในโหมดแยกหน้าจออยู่แล้ว แพลตฟอร์มจะออกจากโหมดแยกหน้าจอและเปิดกิจกรรมที่ปรับขนาดไม่ได้ในโหมดเต็มหน้าจอ
แอปที่ตั้งค่าแอตทริบิวต์นี้เป็น false
อย่างชัดเจนในไฟล์ Manifest ต้องไม่เปิดขึ้นในโหมดหลายหน้าต่าง เว้นแต่ว่าจะมีการใช้โหมดความเข้ากันได้
- ระบบจะใช้การกําหนดค่าเดียวกันกับกระบวนการซึ่งมีกิจกรรมและคอมโพเนนต์ที่ไม่ใช่กิจกรรมทั้งหมด
- การกําหนดค่าที่ใช้เป็นไปตามข้อกําหนด CDD สําหรับจอแสดงผลที่เข้ากันได้กับแอป
ใน Android 10 แพลตฟอร์มนี้ยังคงป้องกันไม่ให้กิจกรรมแบบปรับขนาดไม่ได้เข้าสู่โหมดแยกหน้าจอ แต่สามารถปรับขนาดชั่วคราวได้หากกิจกรรมประกาศการวางแนวหรืออัตราส่วนคงที่ หากไม่ กิจกรรมจะปรับขนาดให้เต็มหน้าจอเหมือนใน Android 9 และต่ำกว่า
การใช้งานเริ่มต้นจะใช้นโยบายต่อไปนี้
เมื่อกิจกรรมที่ประกาศว่าใช้ร่วมกับหลายหน้าต่างไม่ได้ผ่านการใช้แอตทริบิวต์ android:resizeableActivity
และเมื่อกิจกรรมนั้นตรงตามเงื่อนไขข้อใดข้อหนึ่งที่อธิบายไว้ด้านล่าง เมื่อการกำหนดค่าหน้าจอที่ใช้ต้องเปลี่ยนแปลง ระบบจะบันทึกกิจกรรมและกระบวนการตามการกำหนดค่าเดิม และผู้ใช้ยังจะได้รับโอกาสในการเปิดใช้กระบวนการของแอปอีกครั้งเพื่อใช้การกำหนดค่าหน้าจอที่อัปเดตแล้ว
- เป็นการวางแนวที่แก้ไขไม่ได้ผ่านการใช้
android:screenOrientation
- แอปมีสัดส่วนภาพสูงสุดหรือต่ำสุดเริ่มต้นโดยการกำหนดเป้าหมาย API ระดับ หรือประกาศสัดส่วนภาพอย่างชัดเจน
รูปภาพนี้แสดงกิจกรรมที่ปรับขนาดไม่ได้ซึ่งมีสัดส่วนภาพที่ประกาศไว้ เมื่อพับอุปกรณ์ หน้าต่างจะปรับลดขนาดลงให้พอดีกับพื้นที่ในขณะที่รักษาสัดส่วนการแสดงผลโดยใช้แถบดำด้านบน-ล่างของภาพที่เหมาะสม นอกจากนี้ ระบบจะแสดงตัวเลือก "เริ่มกิจกรรมอีกครั้ง" แก่ผู้ใช้ทุกครั้งที่มีการเปลี่ยนแปลงพื้นที่แสดงผลของกิจกรรม
เมื่อกางอุปกรณ์ออก การกำหนดค่า ขนาด และสัดส่วนภาพของกิจกรรมจะไม่เปลี่ยนแปลง แต่ตัวเลือกให้เริ่มกิจกรรมอีกครั้งจะปรากฏ
เมื่อไม่ได้ตั้งค่า resizeableActivity
(หรือตั้งค่าเป็น true
) แอปจะรองรับการปรับขนาดอย่างเต็มรูปแบบ
การใช้งาน
กิจกรรมที่ปรับขนาดไม่ได้ซึ่งมีการวางแนวหรือสัดส่วนภาพที่คงที่เรียกว่าโหมดความเข้ากันได้ของขนาด (SCM) ในโค้ด เงื่อนไขมีการระบุไว้ใน
ActivityRecord#shouldUseSizeCompatMode()
เมื่อเปิดใช้งานกิจกรรม SCM ระบบจะกำหนดค่าที่เกี่ยวข้องกับหน้าจอ (เช่น ขนาดหรือความหนาแน่น) ในการกำหนดค่าการลบล้างที่ขอไว้ ดังนั้นกิจกรรมจะไม่ขึ้นอยู่กับการกำหนดค่าการแสดงผลปัจจุบันอีกต่อไป
หากกิจกรรม SCM แสดงเต็มหน้าจอไม่ได้ ระบบจะจัดแนวกิจกรรมไว้ที่ด้านบนและจัดกึ่งกลางในแนวนอน ขอบเขตของกิจกรรมจะคำนวณโดย AppWindowToken#calculateCompatBoundsTransformation()
เมื่อกิจกรรม SCM ใช้การกำหนดค่าหน้าจอที่แตกต่างจากคอนเทนเนอร์ (เช่น ปรับขนาดจอแสดงผลหรือย้ายกิจกรรมไปยังจอแสดงผลอื่น) ActivityRecord#inSizeCompatMode()
จะเท่ากับ "จริง" และ SizeCompatModeActivityController
(ใน UI ของระบบ) จะได้รับคอลแบ็กเพื่อแสดงปุ่ม "เริ่มกระบวนการอีกครั้ง"
ขนาดการแสดงผลและสัดส่วนภาพ
Android 10 รองรับสัดส่วนภาพใหม่
ตั้งแต่สัดส่วนภาพสูงและหน้าจอบาง ไปจนถึงอัตราส่วน 1:1 แอปสามารถกำหนดApplicationInfo#maxAspectRatio
และApplicationInfo#minAspectRatio
ของหน้าจอที่รองรับได้
รูปที่ 1 ตัวอย่างอัตราส่วนแอปที่รองรับใน Android 10
การใช้งานอุปกรณ์อาจมีหน้าจอรองที่มีขนาดและความละเอียดน้อยกว่าที่ Android 9 กำหนดและต่ำกว่า (ความกว้างหรือความสูงอย่างน้อย 2.5 นิ้ว และอย่างน้อย 320 DP สำหรับ smallestScreenWidth
) แต่จะวางได้เฉพาะกิจกรรมที่เลือกใช้การรองรับจอแสดงผลขนาดเล็กเหล่านี้เท่านั้น
แอปเลือกใช้ได้โดยประกาศขนาดขั้นต่ำที่รองรับซึ่งเล็กกว่าหรือเท่ากับขนาดการแสดงผลเป้าหมาย โดยให้ใช้แอตทริบิวต์เลย์เอาต์กิจกรรม 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
ให้กับจอแสดงผลนั้นโดยการเพิ่มตัวนับแบบคงที่ หากระบบเพิ่มและนําจอแสดงผลเดียวกันออก รหัสที่ได้จะต่างออกไป
หากอุปกรณ์มีจอแสดงผลหลายจอที่พร้อมใช้งานตั้งแต่การบูต ระบบอาจกำหนดตัวระบุที่แตกต่างกันให้กับจอแสดงผล ทั้งนี้ขึ้นอยู่กับช่วงเวลา แม้ว่า 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
มีรหัส Display แบบคงที่ (เหมือนกับใน uniqueId
) และสร้างขึ้นได้ด้วย DisplayAddress#fromPhysicalDisplayId()
นอกจากนี้ Android 10 ยังมีวิธีที่สะดวกในการรับข้อมูลพอร์ต (Physical#getPort()
) ซึ่งสามารถใช้ในเฟรมเวิร์กเพื่อระบุจอแสดงผลแบบคงที่ เช่น ใช้ใน DisplayWindowSettings
) DisplayAddress.Network
มีที่อยู่ MAC และสร้างได้ด้วย DisplayAddress#fromMacAddress()
ส่วนเพิ่มเติมเหล่านี้ช่วยให้ผู้ผลิตอุปกรณ์สามารถระบุการแสดงผลในการตั้งค่าหลายจอแสดงผลแบบคงที่ รวมถึงสามารถกำหนดการตั้งค่าระบบและฟีเจอร์ต่างๆ โดยใช้ตัวระบุการแสดงผลแบบคงที่ เช่น พอร์ตสำหรับจอแสดงผลจริง วิธีการเหล่านี้จะซ่อนอยู่และมีจุดประสงค์เพื่อใช้ภายใน system_server
เท่านั้น
เมื่อระบุรหัสจอแสดงผล HWC (ซึ่งอาจทึบแสงและไม่เสถียรเสมอไป) วิธีการนี้จะแสดงผลหมายเลขพอร์ต 8 บิต (สำหรับแพลตฟอร์มที่เฉพาะเจาะจง) ซึ่งระบุขั้วต่อทางกายภาพสำหรับเอาต์พุตของจอแสดงผล รวมถึง BLOB EDID ของจอแสดงผล
SurfaceFlinger จะดึงข้อมูลผู้ผลิตหรือโมเดลจาก EDID เพื่อสร้างรหัสการแสดงผล 64 บิตแบบคงที่ที่เปิดเผยต่อเฟรมเวิร์ก หากระบบไม่รองรับวิธีนี้หรือเกิดข้อผิดพลาด SurfaceFlinger จะกลับไปใช้โหมด MD เดิม โดยที่ DisplayInfo#address
เป็นค่าว่างและ 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"
ใช้จอแสดงผลมากกว่า 2 จอ
ใน Android 9 (และต่ำกว่า) SurfaceFlinger และ DisplayManagerService
assumed the existence of at most two physical displays with hard-coded IDs 0 and 1
ตั้งแต่ Android 10 เป็นต้นไป SurfaceFlinger จะใช้ประโยชน์จาก API ฮาร์ดแวร์ Composer (HWC) เพื่อสร้างรหัสการแสดงผลแบบคงที่ ซึ่งช่วยให้จัดการจอแสดงผลจริงได้ไม่จำกัดจำนวน ดูข้อมูลเพิ่มเติมได้ที่ตัวระบุโฆษณาแบบดิสเพลย์แบบคงที่
เฟรมเวิร์กจะค้นหาโทเค็น IBinder
สำหรับจอแสดงผลจริงผ่าน SurfaceControl#getPhysicalDisplayToken
หลังจากได้รับรหัสจอแสดงผล 64 บิตจาก SurfaceControl#getPhysicalDisplayIds
หรือจากเหตุการณ์การเสียบปลั๊ก 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 และต่ำกว่า ระบบจะระบุจอแสดงผลด้วยรหัส 32 บิต โดยที่ 0 คือจอแสดงผลภายใน, 1 คือจอแสดงผลภายนอก, [2, INT32_MAX]
คือจอแสดงผลเสมือน HWC และ -1 แสดงถึงจอแสดงผลที่ไม่ถูกต้องหรือจอแสดงผลเสมือนที่ไม่ใช่ HWC
ตั้งแต่ Android 10 เป็นต้นไป จอแสดงผลจะได้รับรหัสที่เสถียรและถาวร ซึ่งช่วยให้ SurfaceFlinger และ DisplayManagerService
ติดตามจอแสดงผลได้มากกว่า 2 จอและจดจำจอแสดงผลที่เคยเห็นก่อนหน้านี้ หาก HWC รองรับ IComposerClient.getDisplayIdentificationData
และให้ข้อมูลการระบุจอแสดงผล SurfaceFlinger จะแยกวิเคราะห์โครงสร้าง EDID และจัดสรรรหัสการแสดงผล 64 บิตแบบคงที่สำหรับจอแสดงผลจริงและ HWC เสมือน รหัสจะแสดงโดยใช้ประเภทตัวเลือก โดยค่าว่างแสดงถึงจอแสดงผลที่ไม่ถูกต้องหรือจอแสดงผลเสมือนที่ไม่ใช่ HWC หากไม่มีการสนับสนุน HWC แพลตฟอร์ม SurfaceFlinger จะกลับไปใช้ลักษณะการทำงานเดิมโดยมีจอแสดงผลจริงสูงสุด 2 หน้าจอ
การโฟกัสต่อจอแสดงผล
หากต้องการรองรับแหล่งที่มาของอินพุตหลายแหล่งที่กำหนดเป้าหมายไปยังจอแสดงผลแต่ละหน้าจอพร้อมกัน คุณสามารถกำหนดค่า Android 10 ให้รองรับหน้าต่างที่เน้นหลายหน้าต่าง โดยไม่เกิน 1 หน้าต่างต่อจอแสดงผล ตัวเลือกนี้มีไว้สําหรับอุปกรณ์ประเภทพิเศษเท่านั้นเมื่อผู้ใช้หลายคนโต้ตอบกับอุปกรณ์เครื่องเดียวกันในเวลาเดียวกันและใช้วิธีการป้อนข้อมูลหรืออุปกรณ์ที่แตกต่างกัน เช่น Android Automotive
เราขอแนะนำอย่างยิ่งว่าอย่าเปิดใช้ฟีเจอร์นี้ในอุปกรณ์ทั่วไป ซึ่งรวมถึงอุปกรณ์หลายหน้าจอหรืออุปกรณ์ที่ใช้เพื่อประสบการณ์การใช้งานแบบเดสก์ท็อป สาเหตุหลักๆ มาจากข้อกังวลด้านความปลอดภัยที่อาจทําให้ผู้ใช้สงสัยว่าหน้าต่างใดมีโฟกัสการป้อนข้อมูล
ลองนึกภาพผู้ใช้ที่ป้อนข้อมูลที่ปลอดภัยลงในช่องป้อนข้อความ อาจเข้าสู่ระบบแอปธนาคารหรือป้อนข้อความที่มีข้อมูลที่ละเอียดอ่อน แอปที่เป็นอันตรายอาจสร้างจอแสดงผลเสมือนจริงนอกหน้าจอเพื่อดําเนินการต่างๆ รวมถึงมีช่องป้อนข้อความ กิจกรรมที่ถูกต้องและที่เป็นอันตรายจะมีโฟกัสและทั้ง 2 กิจกรรมจะแสดงตัวบ่งชี้อินพุตที่ใช้งานอยู่ (เคอร์เซอร์กะพริบ)
อย่างไรก็ตาม เนื่องจากระบบจะป้อนข้อมูลจากแป้นพิมพ์ (ฮาร์ดแวร์หรือซอฟต์แวร์) ไปยังกิจกรรมบนสุดเท่านั้น (แอปที่เปิดล่าสุด) การสร้างจอแสดงผลเสมือนที่ซ่อนอยู่จึงช่วยให้แอปที่เป็นอันตรายสามารถรับข้อมูลจากผู้ใช้ได้ แม้ว่าจะใช้แป้นพิมพ์ซอฟต์แวร์บนจอแสดงผลหลักของอุปกรณ์ก็ตาม
ใช้ com.android.internal.R.bool.config_perDisplayFocusEnabled
เพื่อตั้งค่าโฟกัสต่อจอแสดงผล
ความเข้ากันได้
ปัญหา: ใน Android 9 และต่ำกว่า ระบบจะโฟกัสหน้าต่างได้สูงสุด 1 หน้าต่างในแต่ละครั้ง
วิธีแก้ไข: ในกรณีที่เกิดขึ้นไม่บ่อยนักเมื่อโฟกัสหน้าต่าง 2 หน้าต่างจากกระบวนการเดียวกัน ระบบจะโฟกัสเฉพาะหน้าต่างที่มีลำดับสูงกว่าใน Z-order เท่านั้น ระบบจะนำข้อจำกัดนี้ออกสำหรับแอปที่กำหนดเป้าหมายเป็น Android 10 ซึ่งคาดว่าแอปเหล่านี้จะรองรับการโฟกัสหลายหน้าต่างพร้อมกันได้
การใช้งาน
WindowManagerService#mPerDisplayFocusEnabled
จะควบคุมความพร้อมใช้งานของฟีเจอร์นี้ ใน ActivityManager
จะมีการใช้ ActivityDisplay#getFocusedStack()
แทนการติดตามส่วนกลางในตัวแปร ActivityDisplay#getFocusedStack()
กำหนดโฟกัสตามลําดับ Z แทนการแคชค่า เพื่อให้มีแหล่งที่มาเพียงแหล่งเดียว ซึ่งก็คือ WindowManager ต้องติดตามลำดับ Z ของกิจกรรม
ActivityStackSupervisor#getTopDisplayFocusedStack()
ใช้แนวทางที่คล้ายกันสำหรับกรณีเหล่านั้นเมื่อต้องระบุสแต็กที่โฟกัสมากที่สุดในระบบ ระบบจะข้ามสแต็กจากบนลงล่างเพื่อค้นหาสแต็กแรกที่มีสิทธิ์
ตอนนี้ InputDispatcher
มีหน้าต่างที่โฟกัสได้หลายหน้าต่าง
(1 หน้าต่างต่อจอแสดงผล) หากเหตุการณ์อินพุตเจาะจงจอแสดงผล ระบบจะส่งเหตุการณ์ไปยังหน้าต่างที่มีโฟกัสในจอแสดงผลที่เกี่ยวข้อง มิเช่นนั้น ระบบจะส่งเหตุการณ์ไปยังหน้าต่างที่โฟกัสในจอแสดงผลที่โฟกัส ซึ่งเป็นจอแสดงผลที่ผู้ใช้โต้ตอบด้วยล่าสุด
โปรดดูInputDispatcher::mFocusedWindowHandlesByDisplay
และ
InputDispatcher::setFocusedDisplay()
แอปที่โฟกัสอยู่จะได้รับการอัปเดตแยกต่างหากใน InputManagerService ผ่าน NativeInputManager::setFocusedApplication()
ใน WindowManager
หน้าต่างที่โฟกัสจะมีการติดตามแยกต่างหากเช่นกัน
โปรดดู DisplayContent#mCurrentFocus
และ DisplayContent#mFocusedApp
รวมถึงการใช้งานที่เกี่ยวข้อง วิธีการอัปเดตและการติดตามโฟกัสที่เกี่ยวข้องได้ย้ายจาก WindowManagerService
ไปยัง DisplayContent
แล้ว