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

การอัปเดตที่ทำในส่วนที่เกี่ยวข้องกับโฆษณา Display โดยเฉพาะมีดังนี้

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

หากต้องการระบุว่าแอปอาจไม่รองรับโหมดหลายหน้าต่างหรือการปรับขนาด กิจกรรมจะใช้แอตทริบิวต์ resizeableActivity=false ปัญหาทั่วไปที่แอปพบเมื่อมีการปรับขนาดกิจกรรม ได้แก่

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

ใน Android 7 (และสูงกว่า) คุณสามารถตั้งค่าแอป resizeableActivity=falseให้ทำงานในโหมดเต็มหน้าจอเสมอได้ ใน กรณีนี้ แพลตฟอร์มจะป้องกันไม่ให้กิจกรรมที่ปรับขนาดไม่ได้เข้าสู่โหมดแยก หน้าจอ หากผู้ใช้พยายามเรียกใช้กิจกรรมที่ปรับขนาดไม่ได้จาก Launcher ขณะที่อยู่ในโหมดแยกหน้าจออยู่แล้ว แพลตฟอร์มจะออกจากโหมดแยกหน้าจอและเปิดใช้กิจกรรมที่ปรับขนาดไม่ได้ในโหมดเต็มหน้าจอ

แอปที่ตั้งค่าแอตทริบิวต์นี้เป็น 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 การตั้งค่าการแสดงหน้าต่างต่อจอแสดงผลที่กำหนดค่าได้ได้รับการขยายให้รวมถึงรายการต่อไปนี้

  • โหมดการแสดงผลแบบหน้าต่างเริ่มต้น
  • ค่า Overscan
  • การหมุนผู้ใช้และโหมดการหมุน
  • โหมดขนาด ความหนาแน่น และการปรับขนาดที่บังคับ
  • โหมดการนำเนื้อหาออก (เมื่อนำโฆษณา Display ออก)
  • การรองรับการตกแต่งระบบและ 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 เป็นค่าว่างและ 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 ถือว่ามีจอแสดงผลจริงอย่างมาก 2 จอที่มีรหัส 0 และ 1 ที่ฮาร์ดโค้ด

ตั้งแต่ Android 10 เป็นต้นมา SurfaceFlinger สามารถใช้ประโยชน์จาก API ของ Hardware Composer (HWC) เพื่อสร้างรหัสจอแสดงผลที่เสถียร ซึ่งช่วยให้จัดการจอแสดงผลจริงได้ตามจำนวนที่ต้องการ ดูข้อมูลเพิ่มเติมได้ที่ ตัวระบุแบบคงที่ของโฆษณา Display

เฟรมเวิร์กสามารถค้นหาโทเค็น 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 แล้ว