การอัปเดตที่ทํากับพื้นที่เฉพาะของจอแสดงผลมีดังนี้
- การปรับขนาดกิจกรรมและการแสดงผล
- ขนาดการแสดงผลและสัดส่วนการแสดงผล
- นโยบายการแสดงผล
- การตั้งค่ากรอบเวลาการแสดงผล
- ตัวระบุ Display แบบคงที่
- การใช้จอแสดงผลมากกว่า 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
มีรหัสการแสดงผลที่เสถียร (เหมือนกับใน 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
เป็นค่า 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"
ใช้จอแสดงผลมากกว่า 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 ของเครื่องมือจัดเรียงฮาร์ดแวร์ (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 รหัสจะแสดงโดยใช้ประเภทตัวเลือก โดยค่า Null จะแสดงถึงจอแสดงผลที่ไม่ถูกต้องหรือจอแสดงผลเสมือนที่ไม่ใช่ HWC หากไม่รองรับ HWC ทาง SurfaceFlinger จะกลับไปใช้ลักษณะการทำงานเดิมที่มีจอแสดงผลจริงไม่เกิน 2 จอ
โฟกัสต่อจอแสดงผล
หากต้องการรองรับแหล่งที่มาของอินพุตหลายแหล่งที่กำหนดเป้าหมายไปยังจอแสดงผลแต่ละจอพร้อมกัน คุณสามารถกำหนดค่า Android 10 ให้รองรับหน้าต่างที่โฟกัสหลายรายการได้ โดยสูงสุด 1 รายการต่อจอแสดงผล ตัวเลือกนี้มีไว้สําหรับอุปกรณ์ประเภทพิเศษเท่านั้นเมื่อผู้ใช้หลายคนโต้ตอบกับอุปกรณ์เครื่องเดียวกันในเวลาเดียวกันและใช้วิธีการป้อนข้อมูลหรืออุปกรณ์ที่แตกต่างกัน เช่น Android Automotive
เราขอแนะนำอย่างยิ่งว่าอย่าเปิดใช้ฟีเจอร์นี้ในอุปกรณ์ทั่วไป ซึ่งรวมถึงอุปกรณ์หลายหน้าจอหรืออุปกรณ์ที่ใช้เพื่อประสบการณ์การใช้งานแบบเดสก์ท็อป สาเหตุหลักๆ มาจากข้อกังวลด้านความปลอดภัยที่อาจทําให้ผู้ใช้สงสัยว่าหน้าต่างใดมีโฟกัสการป้อนข้อมูล
ลองจินตนาการถึงผู้ใช้ที่ป้อนข้อมูลที่ปลอดภัยลงในช่องป้อนข้อความ เช่น เข้าสู่ระบบแอปธนาคารหรือป้อนข้อความที่มีข้อมูลที่ละเอียดอ่อน แอปที่เป็นอันตรายอาจสร้างจอแสดงผลเสมือนจริงนอกหน้าจอเพื่อดําเนินการต่างๆ รวมถึงมีช่องป้อนข้อความ กิจกรรมที่ถูกต้องและที่เป็นอันตรายจะมีโฟกัสและทั้ง 2 กิจกรรมจะแสดงตัวบ่งชี้อินพุตที่ใช้งานอยู่ (เคอร์เซอร์กะพริบ)
อย่างไรก็ตาม เนื่องจากระบบจะป้อนข้อมูลจากแป้นพิมพ์ (ฮาร์ดแวร์หรือซอฟต์แวร์) ไปยังกิจกรรมบนสุดเท่านั้น (แอปที่เปิดล่าสุด) การสร้างจอแสดงผลเสมือนที่ซ่อนอยู่จึงช่วยให้แอปที่เป็นอันตรายสามารถรับข้อมูลจากผู้ใช้ได้ แม้ว่าจะใช้แป้นพิมพ์ซอฟต์แวร์บนจอแสดงผลหลักของอุปกรณ์ก็ตาม
ใช้ com.android.internal.R.bool.config_perDisplayFocusEnabled
เพื่อตั้งค่าโฟกัสต่อจอแสดงผล
ความเข้ากันได้
ปัญหา: ใน Android 9 และต่ำกว่า ระบบจะโฟกัสหน้าต่างได้สูงสุด 1 หน้าต่างในแต่ละครั้ง
วิธีแก้ปัญหา: ในกรณีที่เกิดขึ้นไม่บ่อยเมื่อระบบจะโฟกัสที่หน้าต่าง 2 บานจากกระบวนการเดียวกัน ระบบจะโฟกัสเฉพาะที่หน้าต่างที่สูงกว่าในลําดับ Z ระบบจะนำข้อจำกัดนี้ออกสำหรับแอปที่กำหนดเป้าหมายเป็น 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
แล้ว