การรองรับการแสดงผล

การอัปเดตที่ทํากับพื้นที่เฉพาะของจอแสดงผลมีดังนี้

ปรับขนาดกิจกรรมและจอแสดงผล

หากต้องการระบุว่าแอปอาจไม่รองรับโหมดหลายหน้าต่างหรือการปรับขนาด ให้กิจกรรมใช้แอตทริบิวต์ 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ของหน้าจอที่รองรับได้

อัตราส่วนแอปใน Android 10

รูปที่ 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 แล้ว