پشتیبانی از نمایش

به روز رسانی های انجام شده در این مناطق ویژه نمایشگر در زیر ارائه شده است:

تغییر اندازه فعالیت ها و نمایشگرها

برای نشان دادن اینکه یک برنامه ممکن است حالت چند پنجره ای یا تغییر اندازه را پشتیبانی نکند، فعالیت ها از ویژگی resizeableActivity=false استفاده می کنند. مشکلات رایجی که برنامه‌ها هنگام تغییر اندازه فعالیت‌ها با آن مواجه می‌شوند عبارتند از:

  • یک فعالیت می‌تواند پیکربندی متفاوتی از برنامه یا مؤلفه غیربصری دیگر داشته باشد. یک اشتباه رایج این است که معیارهای نمایش را از متن برنامه بخوانید. مقادیر برگشتی با معیارهای منطقه قابل مشاهده که در آن یک فعالیت نمایش داده می شود، تنظیم نمی شود.
  • ممکن است یک اکتیویتی با تغییر اندازه و خرابی، نمایش رابط کاربری تحریف شده یا از دست دادن حالت به دلیل راه‌اندازی مجدد بدون ذخیره حالت نمونه، کار نکند.
  • یک برنامه ممکن است سعی کند از مختصات ورودی مطلق استفاده کند (به جای مختصات مربوط به موقعیت پنجره)، که ممکن است ورودی را در چند پنجره شکست دهد.

در اندروید 7 (و بالاتر)، یک برنامه را می توان resizeableActivity=false تنظیم کرد تا همیشه در حالت تمام صفحه اجرا شود. در این حالت، پلتفرم از ورود فعالیت های غیرقابل تغییر اندازه به صفحه نمایش تقسیم شده جلوگیری می کند. اگر کاربر سعی کند یک فعالیت غیرقابل تغییر اندازه را از راه‌انداز در حالی که قبلاً در حالت تقسیم صفحه است فراخوانی کند، پلتفرم از حالت تقسیم صفحه خارج شده و فعالیت غیرقابل تغییر اندازه را در حالت تمام صفحه راه‌اندازی می‌کند.

برنامه‌هایی که صراحتاً این ویژگی را در مانیفست روی false تنظیم می‌کنند، نباید در حالت چند پنجره‌ای راه‌اندازی شوند، مگر اینکه حالت سازگاری اعمال شود:

  • پیکربندی مشابهی برای فرآیند اعمال می‌شود که شامل تمام فعالیت‌ها و اجزای غیرفعالیتی است.
  • پیکربندی کاربردی الزامات CDD را برای نمایشگرهای سازگار با برنامه برآورده می کند.

در اندروید 10، این پلتفرم همچنان از رفتن به حالت تقسیم صفحه نمایش فعالیت‌های غیرقابل تغییر اندازه جلوگیری می‌کند، اما اگر فعالیت دارای جهت یا نسبت تصویر ثابتی باشد، می‌توان آن‌ها را به‌طور موقت مقیاس‌بندی کرد. در غیر این صورت، اندازه فعالیت تغییر می کند تا کل صفحه مانند اندروید 9 و پایین تر را پر کند.

اجرای پیش فرض سیاست زیر را اعمال می کند:

هنگامی که فعالیتی با استفاده از ویژگی android:resizeableActivity با چند پنجره ناسازگار اعلام می شود و زمانی که آن فعالیت یکی از شرایط توضیح داده شده در زیر را برآورده می کند، هنگامی که پیکربندی صفحه اعمال شده باید تغییر کند، فعالیت و فرآیند با پیکربندی اصلی ذخیره می شود و به کاربر امکان راه اندازی مجدد فرآیند برنامه برای استفاده از پیکربندی صفحه به روز شده داده می شود.

  • جهت گیری از طریق برنامه android:screenOrientation ثابت شده است
  • با هدف قرار دادن سطح API یا اعلام صریح نسبت ابعاد، برنامه دارای حداکثر یا حداقل نسبت ابعاد پیش‌فرض است.

این شکل یک فعالیت غیرقابل تغییر اندازه را با نسبت ابعادی اعلام شده نشان می دهد. هنگام تا کردن دستگاه، پنجره کوچک می‌شود تا متناسب با ناحیه باشد و در عین حال نسبت تصویر را با استفاده از جعبه نامه مناسب حفظ می‌کند. علاوه بر این، هر بار که ناحیه نمایش فعالیت تغییر می‌کند، یک گزینه شروع مجدد فعالیت در اختیار کاربر قرار می‌گیرد.

هنگام باز کردن دستگاه، پیکربندی، اندازه و نسبت ابعاد فعالیت تغییر نمی‌کند، اما گزینه راه‌اندازی مجدد فعالیت نمایش داده می‌شود.

وقتی resizeableActivity تنظیم نشده باشد (یا روی true تنظیم شده باشد)، برنامه به طور کامل از تغییر اندازه پشتیبانی می کند.

پیاده سازی

یک فعالیت غیرقابل تغییر اندازه با جهت یا نسبت ابعاد ثابت در کد حالت سازگاری اندازه (SCM) نامیده می شود. این شرط در ActivityRecord#shouldUseSizeCompatMode() تعریف شده است. هنگامی که یک فعالیت SCM راه اندازی می شود، پیکربندی مربوط به صفحه (مانند اندازه یا تراکم) در پیکربندی لغو درخواستی ثابت می شود، بنابراین فعالیت دیگر به پیکربندی نمایش فعلی وابسته نیست.

اگر فعالیت SCM نتواند کل صفحه را پر کند، در بالا تراز و در مرکز افقی قرار می گیرد. محدوده فعالیت توسط AppWindowToken#calculateCompatBoundsTransformation() محاسبه می شود.

هنگامی که یک فعالیت SCM از پیکربندی صفحه متفاوتی نسبت به محفظه خود استفاده می کند (به عنوان مثال، اندازه صفحه نمایش تغییر می کند یا فعالیت به نمایشگر دیگری منتقل می شود)، ActivityRecord#inSizeCompatMode() true است و SizeCompatModeActivityController (در System UI) برای نشان دادن دکمه راه اندازی مجدد فرآیند، پاسخ تماس را دریافت می کند.

اندازه و نسبت ابعاد نمایشگر

اندروید 10 از نسبت ابعاد جدید از نسبت بالای صفحه نمایش بلند و نازک تا نسبت 1:1 پشتیبانی می کند. برنامه‌ها می‌توانند ApplicationInfo#maxAspectRatio و ApplicationInfo#minAspectRatio صفحه‌نمایش را که قادر به مدیریت آن هستند، تعریف کنند.

نسبت برنامه ها در اندروید 10

شکل 1. نمونه نسبت برنامه های پشتیبانی شده در اندروید 10

پیاده‌سازی‌های دستگاه می‌توانند نمایشگرهای ثانویه با اندازه‌ها و رزولوشن‌های کوچک‌تر از آنچه در Android 9 مورد نیاز است، و کمتر (حداقل عرض یا ارتفاع 2.5 اینچ، حداقل 320 DP برای smallestScreenWidth ) داشته باشند، اما فقط فعالیت‌هایی که از این نمایشگرهای کوچک پشتیبانی می‌کنند می‌توانند در آنجا قرار بگیرند.

برنامه‌ها می‌توانند با اعلام حداقل اندازه پشتیبانی شده که کوچک‌تر یا مساوی اندازه نمایش هدف است، شرکت کنند. برای این کار از ویژگی‌های طرح‌بندی فعالیت android:minHeight و android:minWidth در AndroidManifest استفاده کنید.

سیاست های نمایش

Android 10 برخی از سیاست‌های نمایشگر را از اجرای پیش‌فرض WindowManagerPolicy در PhoneWindowManager به کلاس‌های هر نمایشگر جدا کرده و منتقل می‌کند، مانند:

  • نمایش وضعیت و چرخش
  • برخی از کلیدها و ردیابی رویداد حرکت
  • رابط کاربری سیستم و پنجره های دکوراسیون

در اندروید 9 (و پایین تر)، کلاس PhoneWindowManager سیاست های نمایش، وضعیت و تنظیمات، چرخش، ردیابی قاب پنجره دکوراسیون و موارد دیگر را مدیریت می کند. اندروید 10 بیشتر این موارد را به کلاس DisplayPolicy منتقل می کند، به جز ردیابی چرخش، که به DisplayRotation منتقل شده است.

نمایش تنظیمات پنجره

در اندروید 10، تنظیمات پنجره قابل تنظیم برای هر نمایشگر گسترش یافته است تا شامل موارد زیر باشد:

  • حالت پنجره نمایش پیش فرض
  • مقادیر Overscan
  • چرخش کاربر و حالت چرخش
  • اندازه اجباری، چگالی، و حالت پوسته پوسته شدن
  • حالت حذف محتوا (زمانی که نمایشگر حذف می شود)
  • پشتیبانی از تزئینات سیستم و IME

کلاس DisplayWindowSettings شامل تنظیماتی برای این گزینه ها است. هر بار که یک تنظیم تغییر می کند، آنها در پارتیشن /data در display_settings.xml دیسک می شوند. برای جزئیات، به DisplayWindowSettings.AtomicFileStorage و DisplayWindowSettings#writeSettings() مراجعه کنید. سازندگان دستگاه می توانند مقادیر پیش فرض را در display_settings.xml برای پیکربندی دستگاه خود ارائه دهند. با این حال، از آنجایی که فایل در /data ذخیره می شود، ممکن است منطق اضافی برای بازیابی فایل در صورت پاک شدن با پاک کردن نیاز باشد.

به‌طور پیش‌فرض، Android 10 از DisplayInfo#uniqueId به‌عنوان شناسه نمایشگر هنگام ادامه تنظیمات استفاده می‌کند. uniqueId باید برای همه نمایشگرها پر شود. علاوه بر این، برای نمایشگرهای فیزیکی و شبکه پایدار است. همچنین می توان از پورت یک نمایشگر فیزیکی به عنوان شناسه استفاده کرد که می تواند در DisplayWindowSettings#mIdentifier تنظیم شود. پس از هر نوشتن، همه تنظیمات نوشته می‌شوند، بنابراین می‌توان کلیدی را که برای ورودی نمایشگر در فضای ذخیره‌سازی استفاده می‌شود، به‌روزرسانی کرد. برای جزئیات، به شناسه های نمایشگر استاتیک مراجعه کنید.

تنظیمات به دلایل تاریخی در فهرست /data باقی می مانند. در اصل، از آنها برای تداوم تنظیمات تنظیم شده توسط کاربر، مانند چرخش نمایشگر استفاده می شد.

شناسه های صفحه نمایش استاتیک

اندروید 9 (و پایین تر) شناسه های پایداری برای نمایشگرها در چارچوب ارائه نمی کند. هنگامی که یک نمایشگر به سیستم اضافه شد، Display#mDisplayId یا DisplayInfo#displayId با افزایش یک شمارنده استاتیک برای آن نمایشگر تولید شد. اگر سیستم همان نمایشگر را اضافه و حذف کند، شناسه متفاوتی حاصل می‌شود.

اگر دستگاهی دارای چندین نمایشگر از راه‌اندازی بود، بسته به زمان، می‌توان به نمایشگرها شناسه‌های مختلفی اختصاص داد. در حالی که اندروید 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 است، یک شناسه نمایشگر که در هنگام راه‌اندازی مجدد پایدار است. در اندروید 10، DisplayAddress از نمایشگرهای فیزیکی و شبکه پشتیبانی می کند. DisplayAddress.Physical حاوی یک شناسه نمایش پایدار (همانند در uniqueId ) است و می تواند با DisplayAddress#fromPhysicalDisplayId() ایجاد شود.

اندروید 10 همچنین روشی مناسب برای دریافت اطلاعات پورت ( Physical#getPort() ) ارائه می‌کند. این روش را می توان در چارچوب برای شناسایی ایستا نمایشگرها استفاده کرد. به عنوان مثال، در DisplayWindowSettings استفاده می شود. DisplayAddress.Network حاوی آدرس MAC است و می تواند با DisplayAddress#fromMacAddress() ایجاد شود.

این افزودنی‌ها به سازندگان دستگاه اجازه می‌دهد نمایشگرها را در تنظیمات چند صفحه‌نمایش ثابت شناسایی کنند و تنظیمات و ویژگی‌های مختلف سیستم را با استفاده از شناسه‌های نمایشگر ثابت، مانند پورت‌های نمایشگرهای فیزیکی، پیکربندی کنند. این روش‌ها پنهان هستند و فقط برای استفاده در system_server در نظر گرفته شده‌اند.

با توجه به شناسه نمایشگر HWC (که می تواند مات باشد و همیشه پایدار نیست)، این روش شماره پورت 8 بیتی (ویژه پلتفرم) را برمی گرداند که یک رابط فیزیکی برای خروجی نمایشگر و همچنین لکه 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"

از بیش از دو نمایشگر استفاده کنید

در اندروید 9 (و پایین‌تر)، SurfaceFlinger و DisplayManagerService حداکثر دو نمایشگر فیزیکی با شناسه‌های کد سخت 0 و 1 را فرض کردند.

با شروع اندروید 10، SurfaceFlinger می‌تواند از API سخت‌افزار Composer (HWC) برای تولید شناسه‌های نمایشگر پایدار استفاده کند که به آن امکان می‌دهد تعداد دلخواه نمایش‌های فیزیکی را مدیریت کند. برای کسب اطلاعات بیشتر، به شناسه های نمایشگر استاتیک مراجعه کنید.

این فریم ورک می‌تواند رمز IBinder را برای نمایش فیزیکی از طریق SurfaceControl#getPhysicalDisplayToken پس از دریافت شناسه نمایشگر 64 بیتی از SurfaceControl#getPhysicalDisplayIds یا از یک رویداد hotplug DisplayEventReceiver جستجو کند.

در Android 10 (و پایین تر)، صفحه نمایش داخلی اصلی TYPE_INTERNAL است و همه نمایشگرهای ثانویه بدون در نظر گرفتن نوع اتصال به عنوان TYPE_EXTERNAL علامت گذاری می شوند. بنابراین، نمایشگرهای داخلی اضافی به عنوان خارجی در نظر گرفته می شوند. به عنوان یک راه حل، اگر HWC شناخته شده باشد و منطق تخصیص پورت قابل پیش بینی باشد، کد مخصوص دستگاه می تواند در مورد DisplayAddress.Physical#getPort مفروضاتی ایجاد کند.

این محدودیت در اندروید 11 (و بالاتر) حذف شده است.

  • در اندروید 11، اولین نمایشگر گزارش شده در هنگام بوت، نمایشگر اصلی است. نوع اتصال (داخلی در مقابل خارجی) بی ربط است. با این حال، درست است که صفحه نمایش اصلی را نمی توان قطع کرد و به این ترتیب که در عمل باید نمایشگر داخلی باشد. توجه داشته باشید که برخی از گوشی های تاشو دارای چندین نمایشگر داخلی هستند.
  • نمایشگرهای ثانویه بسته به نوع اتصالشان به درستی به‌عنوان Display.TYPE_INTERNAL یا Display.TYPE_EXTERNAL (که قبلاً به ترتیب Display.TYPE_BUILT_IN و Display.TYPE_HDMI شناخته می‌شد) دسته‌بندی می‌شوند.

پیاده سازی

در اندروید 9 و پایین‌تر، نمایشگرها با شناسه‌های 32 بیتی شناسایی می‌شوند که 0 نمایشگر داخلی، 1 نمایشگر خارجی، [2, INT32_MAX] نمایشگرهای مجازی HWC، و -1 نمایشگر نامعتبر یا نمایش مجازی غیر HWC است.

با شروع اندروید 10، به نمایشگرها شناسه‌های پایدار و پایدار داده می‌شود که به SurfaceFlinger و DisplayManagerService اجازه می‌دهد بیش از دو نمایشگر را ردیابی کنند و نمایشگرهایی که قبلاً دیده‌شده را تشخیص دهند. اگر HWC از IComposerClient.getDisplayIdentificationData پشتیبانی می‌کند و داده‌های شناسایی نمایشگر را ارائه می‌کند، SurfaceFlinger ساختار EDID را تجزیه می‌کند و شناسه‌های نمایشگر ۶۴ بیتی پایدار را برای نمایشگرهای فیزیکی و مجازی HWC اختصاص می‌دهد. شناسه ها با استفاده از یک نوع گزینه بیان می شوند، جایی که مقدار تهی نشان دهنده یک نمایشگر نامعتبر یا نمایش مجازی غیر HWC است. بدون پشتیبانی HWC، SurfaceFlinger به رفتار قدیمی با حداکثر دو نمایشگر فیزیکی بازمی گردد.

فوکوس هر صفحه نمایش

برای پشتیبانی از چندین منبع ورودی که نمایشگرهای فردی را به طور همزمان هدف قرار می دهند، اندروید 10 را می توان طوری پیکربندی کرد که از چندین پنجره متمرکز، حداکثر یک در هر نمایشگر پشتیبانی کند. این فقط برای انواع خاصی از دستگاه‌ها در نظر گرفته شده است که چندین کاربر به طور همزمان با یک دستگاه تعامل دارند و از روش‌ها یا دستگاه‌های ورودی متفاوتی مانند Android Automotive استفاده می‌کنند.

اکیداً توصیه می‌شود که این ویژگی برای دستگاه‌های معمولی، از جمله دستگاه‌های چند صفحه‌نما یا دستگاه‌هایی که برای تجربه‌هایی شبیه به دسکتاپ استفاده می‌شوند، فعال نشود . این در درجه اول به دلیل یک نگرانی امنیتی است که ممکن است باعث شود کاربران تعجب کنند که کدام پنجره دارای فوکوس ورودی است.

کاربری را تصور کنید که اطلاعات ایمن را در یک قسمت ورودی متن وارد می کند، شاید وارد یک برنامه بانکی شده یا متنی را وارد می کند که حاوی اطلاعات حساس است. یک برنامه مخرب می تواند یک صفحه نمایش مجازی خارج از صفحه ایجاد کند که با آن یک فعالیت را انجام دهد، همچنین با یک فیلد ورودی متن. فعالیت های مشروع و مخرب دارای فوکوس هستند و هر دو یک نشانگر ورودی فعال (مکان نما چشمک زن) را نمایش می دهند.

با این حال، از آنجایی که ورودی از یک صفحه کلید (سخت افزار یا نرم افزار) فقط در بالاترین فعالیت (آن برنامه ای که اخیراً راه اندازی شده است) وارد می شود، با ایجاد یک نمایشگر مجازی مخفی، یک برنامه مخرب می تواند ورودی کاربر را حتی زمانی که از صفحه کلید نرم افزاری در صفحه نمایش دستگاه اصلی استفاده می کند، بگیرد.

برای تنظیم فوکوس هر نمایشگر com.android.internal.R.bool.config_perDisplayFocusEnabled استفاده کنید.

سازگاری

مشکل: در اندروید 9 و پایین تر، حداکثر یک پنجره در سیستم هر بار فوکوس دارد.

راه‌حل: در موارد نادری که دو پنجره از یک فرآیند فوکوس می‌شوند، سیستم تنها به پنجره‌ای که در مرتبه Z بالاتر است فوکوس می‌دهد. این محدودیت برای برنامه‌هایی که اندروید 10 را هدف قرار می‌دهند برداشته می‌شود، در این مرحله انتظار می‌رود که آنها بتوانند چندین پنجره را که به طور همزمان بر روی آنها متمرکز شده‌اند پشتیبانی کنند.

پیاده سازی

WindowManagerService#mPerDisplayFocusEnabled در دسترس بودن این ویژگی را کنترل می کند. در ActivityManager ، ActivityDisplay#getFocusedStack() اکنون به جای ردیابی سراسری در یک متغیر استفاده می شود. ActivityDisplay#getFocusedStack() فوکوس را بر اساس Z-order به جای کش کردن مقدار تعیین می کند. این به این دلیل است که تنها یک منبع، WindowManager، نیاز به ردیابی ترتیب Z فعالیت‌ها دارد.

ActivityStackSupervisor#getTopDisplayFocusedStack() رویکرد مشابهی را برای مواردی که بالاترین پشته متمرکز در سیستم باید شناسایی شود، اتخاذ می کند. پشته ها از بالا به پایین طی می شوند و اولین پشته واجد شرایط را جستجو می کنند.

InputDispatcher اکنون می تواند چندین پنجره متمرکز داشته باشد (یکی در هر نمایشگر). اگر یک رویداد ورودی مختص صفحه نمایش باشد، به پنجره متمرکز در نمایشگر مربوطه ارسال می شود. در غیر این صورت، به پنجره متمرکز در صفحه نمایش متمرکز ارسال می شود، که نمایشگری است که کاربر اخیراً با آن تعامل داشته است.

InputDispatcher::mFocusedWindowHandlesByDisplay و InputDispatcher::setFocusedDisplay() را ببینید. برنامه های متمرکز نیز به طور جداگانه در InputManagerService از طریق NativeInputManager::setFocusedApplication() به روز می شوند.

در WindowManager ، پنجره های متمرکز نیز به طور جداگانه ردیابی می شوند. DisplayContent#mCurrentFocus و DisplayContent#mFocusedApp و کاربردهای مربوطه را ببینید. روش‌های ردیابی و به‌روزرسانی فوکوس مرتبط از WindowManagerService به DisplayContent منتقل شده‌اند.

،

به روز رسانی های انجام شده در این مناطق ویژه نمایشگر در زیر ارائه شده است:

تغییر اندازه فعالیت ها و نمایشگرها

برای نشان دادن اینکه یک برنامه ممکن است حالت چند پنجره ای یا تغییر اندازه را پشتیبانی نکند، فعالیت ها از ویژگی resizeableActivity=false استفاده می کنند. مشکلات رایجی که برنامه‌ها هنگام تغییر اندازه فعالیت‌ها با آن مواجه می‌شوند عبارتند از:

  • یک فعالیت می‌تواند پیکربندی متفاوتی از برنامه یا مؤلفه غیربصری دیگر داشته باشد. یک اشتباه رایج این است که معیارهای نمایش را از متن برنامه بخوانید. مقادیر برگشتی با معیارهای منطقه قابل مشاهده که در آن یک فعالیت نمایش داده می شود، تنظیم نمی شود.
  • ممکن است یک اکتیویتی با تغییر اندازه و خرابی، نمایش رابط کاربری تحریف شده یا از دست دادن حالت به دلیل راه‌اندازی مجدد بدون ذخیره حالت نمونه، کار نکند.
  • یک برنامه ممکن است سعی کند از مختصات ورودی مطلق استفاده کند (به جای مختصات مربوط به موقعیت پنجره)، که ممکن است ورودی را در چند پنجره شکست دهد.

در اندروید 7 (و بالاتر)، یک برنامه را می توان resizeableActivity=false تنظیم کرد تا همیشه در حالت تمام صفحه اجرا شود. در این حالت، پلتفرم از ورود فعالیت های غیرقابل تغییر اندازه به صفحه نمایش تقسیم شده جلوگیری می کند. اگر کاربر سعی کند یک فعالیت غیرقابل تغییر اندازه را از راه‌انداز در حالی که قبلاً در حالت تقسیم صفحه است فراخوانی کند، پلتفرم از حالت تقسیم صفحه خارج شده و فعالیت غیرقابل تغییر اندازه را در حالت تمام صفحه راه‌اندازی می‌کند.

برنامه‌هایی که صراحتاً این ویژگی را در مانیفست روی false تنظیم می‌کنند، نباید در حالت چند پنجره‌ای راه‌اندازی شوند، مگر اینکه حالت سازگاری اعمال شود:

  • پیکربندی مشابهی برای فرآیند اعمال می‌شود که شامل تمام فعالیت‌ها و اجزای غیرفعالیتی است.
  • پیکربندی کاربردی الزامات CDD را برای نمایشگرهای سازگار با برنامه برآورده می کند.

در اندروید 10، این پلتفرم همچنان از رفتن به حالت تقسیم صفحه نمایش فعالیت‌های غیرقابل تغییر اندازه جلوگیری می‌کند، اما اگر فعالیت دارای جهت یا نسبت تصویر ثابتی باشد، می‌توان آن‌ها را به‌طور موقت مقیاس‌بندی کرد. در غیر این صورت، اندازه فعالیت تغییر می کند تا کل صفحه مانند اندروید 9 و پایین تر را پر کند.

اجرای پیش فرض سیاست زیر را اعمال می کند:

هنگامی که فعالیتی با استفاده از ویژگی android:resizeableActivity با چند پنجره ناسازگار اعلام می شود و زمانی که آن فعالیت یکی از شرایط توضیح داده شده در زیر را برآورده می کند، هنگامی که پیکربندی صفحه اعمال شده باید تغییر کند، فعالیت و فرآیند با پیکربندی اصلی ذخیره می شود و به کاربر امکان راه اندازی مجدد فرآیند برنامه برای استفاده از پیکربندی صفحه به روز شده داده می شود.

  • جهت گیری از طریق برنامه android:screenOrientation ثابت شده است
  • با هدف قرار دادن سطح API یا اعلام صریح نسبت ابعاد، برنامه دارای حداکثر یا حداقل نسبت ابعاد پیش‌فرض است.

این شکل یک فعالیت غیرقابل تغییر اندازه را با نسبت ابعادی اعلام شده نشان می دهد. هنگام تا کردن دستگاه، پنجره کوچک می‌شود تا متناسب با ناحیه باشد و در عین حال نسبت تصویر را با استفاده از جعبه نامه مناسب حفظ می‌کند. علاوه بر این، هر بار که ناحیه نمایش فعالیت تغییر می‌کند، یک گزینه شروع مجدد فعالیت در اختیار کاربر قرار می‌گیرد.

هنگام باز کردن دستگاه، پیکربندی، اندازه و نسبت ابعاد فعالیت تغییر نمی‌کند، اما گزینه راه‌اندازی مجدد فعالیت نمایش داده می‌شود.

وقتی resizeableActivity تنظیم نشده باشد (یا روی true تنظیم شده باشد)، برنامه به طور کامل از تغییر اندازه پشتیبانی می کند.

پیاده سازی

یک فعالیت غیرقابل تغییر اندازه با جهت یا نسبت ابعاد ثابت در کد حالت سازگاری اندازه (SCM) نامیده می شود. این شرط در ActivityRecord#shouldUseSizeCompatMode() تعریف شده است. هنگامی که یک فعالیت SCM راه اندازی می شود، پیکربندی مربوط به صفحه (مانند اندازه یا تراکم) در پیکربندی لغو درخواستی ثابت می شود، بنابراین فعالیت دیگر به پیکربندی نمایش فعلی وابسته نیست.

اگر فعالیت SCM نتواند کل صفحه را پر کند، در بالا تراز و در مرکز افقی قرار می گیرد. محدوده فعالیت توسط AppWindowToken#calculateCompatBoundsTransformation() محاسبه می شود.

هنگامی که یک فعالیت SCM از پیکربندی صفحه متفاوتی نسبت به محفظه خود استفاده می کند (به عنوان مثال، اندازه صفحه نمایش تغییر می کند یا فعالیت به نمایشگر دیگری منتقل می شود)، ActivityRecord#inSizeCompatMode() true است و SizeCompatModeActivityController (در System UI) برای نشان دادن دکمه راه اندازی مجدد فرآیند، پاسخ تماس را دریافت می کند.

اندازه و نسبت ابعاد نمایشگر

اندروید 10 از نسبت ابعاد جدید از نسبت بالای صفحه نمایش بلند و نازک تا نسبت 1:1 پشتیبانی می کند. برنامه‌ها می‌توانند ApplicationInfo#maxAspectRatio و ApplicationInfo#minAspectRatio صفحه‌نمایش را که قادر به مدیریت آن هستند، تعریف کنند.

نسبت برنامه ها در اندروید 10

شکل 1. نمونه نسبت برنامه های پشتیبانی شده در اندروید 10

پیاده‌سازی‌های دستگاه می‌توانند نمایشگرهای ثانویه با اندازه‌ها و رزولوشن‌های کوچک‌تر از آنچه در Android 9 مورد نیاز است، و کمتر (حداقل عرض یا ارتفاع 2.5 اینچ، حداقل 320 DP برای smallestScreenWidth ) داشته باشند، اما فقط فعالیت‌هایی که از این نمایشگرهای کوچک پشتیبانی می‌کنند می‌توانند در آنجا قرار بگیرند.

برنامه‌ها می‌توانند با اعلام حداقل اندازه پشتیبانی شده که کوچک‌تر یا مساوی اندازه نمایش هدف است، شرکت کنند. برای این کار از ویژگی‌های طرح‌بندی فعالیت android:minHeight و android:minWidth در AndroidManifest استفاده کنید.

سیاست های نمایش

Android 10 برخی از سیاست‌های نمایشگر را از اجرای پیش‌فرض WindowManagerPolicy در PhoneWindowManager به کلاس‌های هر نمایشگر جدا کرده و منتقل می‌کند، مانند:

  • نمایش وضعیت و چرخش
  • برخی از کلیدها و ردیابی رویداد حرکت
  • رابط کاربری سیستم و پنجره های دکوراسیون

در اندروید 9 (و پایین تر)، کلاس PhoneWindowManager سیاست های نمایش، وضعیت و تنظیمات، چرخش، ردیابی قاب پنجره دکوراسیون و موارد دیگر را مدیریت می کند. اندروید 10 بیشتر این موارد را به کلاس DisplayPolicy منتقل می کند، به جز ردیابی چرخش، که به DisplayRotation منتقل شده است.

نمایش تنظیمات پنجره

در اندروید 10، تنظیمات پنجره قابل تنظیم برای هر نمایشگر گسترش یافته است تا شامل موارد زیر باشد:

  • حالت پنجره نمایش پیش فرض
  • مقادیر Overscan
  • چرخش کاربر و حالت چرخش
  • اندازه اجباری، چگالی، و حالت پوسته پوسته شدن
  • حالت حذف محتوا (زمانی که نمایشگر حذف می شود)
  • پشتیبانی از تزئینات سیستم و IME

کلاس DisplayWindowSettings شامل تنظیماتی برای این گزینه ها است. هر بار که یک تنظیم تغییر می کند، آنها در پارتیشن /data در display_settings.xml دیسک می شوند. برای جزئیات، به DisplayWindowSettings.AtomicFileStorage و DisplayWindowSettings#writeSettings() مراجعه کنید. سازندگان دستگاه می توانند مقادیر پیش فرض را در display_settings.xml برای پیکربندی دستگاه خود ارائه دهند. با این حال، از آنجایی که فایل در /data ذخیره می شود، ممکن است منطق اضافی برای بازیابی فایل در صورت پاک شدن با پاک کردن نیاز باشد.

به‌طور پیش‌فرض، Android 10 از DisplayInfo#uniqueId به‌عنوان شناسه نمایشگر هنگام ادامه تنظیمات استفاده می‌کند. uniqueId باید برای همه نمایشگرها پر شود. علاوه بر این، برای نمایشگرهای فیزیکی و شبکه پایدار است. همچنین می توان از پورت یک نمایشگر فیزیکی به عنوان شناسه استفاده کرد که می تواند در DisplayWindowSettings#mIdentifier تنظیم شود. پس از هر نوشتن، همه تنظیمات نوشته می‌شوند، بنابراین می‌توان کلیدی را که برای ورودی نمایشگر در فضای ذخیره‌سازی استفاده می‌شود، به‌روزرسانی کرد. برای جزئیات، به شناسه های نمایشگر استاتیک مراجعه کنید.

تنظیمات به دلایل تاریخی در فهرست /data باقی می مانند. در اصل، از آنها برای تداوم تنظیمات تنظیم شده توسط کاربر، مانند چرخش نمایشگر استفاده می شد.

شناسه های صفحه نمایش استاتیک

اندروید 9 (و پایین تر) شناسه های پایداری برای نمایشگرها در چارچوب ارائه نمی کند. هنگامی که یک نمایشگر به سیستم اضافه شد، Display#mDisplayId یا DisplayInfo#displayId با افزایش یک شمارنده استاتیک برای آن نمایشگر تولید شد. اگر سیستم همان نمایشگر را اضافه و حذف کند، شناسه متفاوتی حاصل می‌شود.

اگر دستگاهی دارای چندین نمایشگر از راه‌اندازی بود، بسته به زمان، می‌توان به نمایشگرها شناسه‌های مختلفی اختصاص داد. در حالی که اندروید 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 است، یک شناسه نمایشگر که در هنگام راه‌اندازی مجدد پایدار است. در اندروید 10، DisplayAddress از نمایشگرهای فیزیکی و شبکه پشتیبانی می کند. DisplayAddress.Physical حاوی یک شناسه نمایش پایدار (همانند در uniqueId ) است و می تواند با DisplayAddress#fromPhysicalDisplayId() ایجاد شود.

اندروید 10 همچنین روشی مناسب برای دریافت اطلاعات پورت ( Physical#getPort() ) ارائه می‌کند. این روش را می توان در چارچوب برای شناسایی ایستا نمایشگرها استفاده کرد. به عنوان مثال، در DisplayWindowSettings استفاده می شود. DisplayAddress.Network حاوی آدرس MAC است و می تواند با DisplayAddress#fromMacAddress() ایجاد شود.

این افزودنی‌ها به سازندگان دستگاه اجازه می‌دهد نمایشگرها را در تنظیمات چند صفحه‌نمایش ثابت شناسایی کنند و تنظیمات و ویژگی‌های مختلف سیستم را با استفاده از شناسه‌های نمایشگر ثابت، مانند پورت‌های نمایشگرهای فیزیکی، پیکربندی کنند. این روش‌ها پنهان هستند و فقط برای استفاده در system_server در نظر گرفته شده‌اند.

با توجه به شناسه نمایشگر HWC (که می تواند مات باشد و همیشه پایدار نیست)، این روش شماره پورت 8 بیتی (ویژه پلتفرم) را برمی گرداند که یک رابط فیزیکی برای خروجی نمایشگر و همچنین لکه 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"

از بیش از دو نمایشگر استفاده کنید

در اندروید 9 (و پایین‌تر)، SurfaceFlinger و DisplayManagerService حداکثر دو نمایشگر فیزیکی با شناسه‌های کد سخت 0 و 1 را فرض کردند.

با شروع اندروید 10، SurfaceFlinger می‌تواند از API سخت‌افزار Composer (HWC) برای تولید شناسه‌های نمایشگر پایدار استفاده کند که به آن امکان می‌دهد تعداد دلخواه نمایش‌های فیزیکی را مدیریت کند. برای کسب اطلاعات بیشتر، به شناسه های نمایشگر استاتیک مراجعه کنید.

این فریم ورک می‌تواند رمز IBinder را برای نمایش فیزیکی از طریق SurfaceControl#getPhysicalDisplayToken پس از دریافت شناسه نمایشگر 64 بیتی از SurfaceControl#getPhysicalDisplayIds یا از یک رویداد hotplug DisplayEventReceiver جستجو کند.

در Android 10 (و پایین تر)، صفحه نمایش داخلی اصلی TYPE_INTERNAL است و همه نمایشگرهای ثانویه بدون در نظر گرفتن نوع اتصال به عنوان TYPE_EXTERNAL علامت گذاری می شوند. بنابراین، نمایشگرهای داخلی اضافی به عنوان خارجی در نظر گرفته می شوند. به عنوان یک راه حل، اگر HWC شناخته شده باشد و منطق تخصیص پورت قابل پیش بینی باشد، کد مخصوص دستگاه می تواند در مورد DisplayAddress.Physical#getPort مفروضاتی ایجاد کند.

این محدودیت در اندروید 11 (و بالاتر) حذف شده است.

  • در اندروید 11، اولین نمایشگر گزارش شده در هنگام بوت، نمایشگر اصلی است. نوع اتصال (داخلی در مقابل خارجی) بی ربط است. با این حال، درست است که صفحه نمایش اصلی را نمی توان قطع کرد و به این ترتیب که در عمل باید نمایشگر داخلی باشد. توجه داشته باشید که برخی از گوشی های تاشو دارای چندین نمایشگر داخلی هستند.
  • نمایشگرهای ثانویه بسته به نوع اتصالشان به درستی به‌عنوان Display.TYPE_INTERNAL یا Display.TYPE_EXTERNAL (که قبلاً به ترتیب Display.TYPE_BUILT_IN و Display.TYPE_HDMI شناخته می‌شد) دسته‌بندی می‌شوند.

پیاده سازی

در اندروید 9 و پایین‌تر، نمایشگرها با شناسه‌های 32 بیتی شناسایی می‌شوند که 0 نمایشگر داخلی، 1 نمایشگر خارجی، [2, INT32_MAX] نمایشگرهای مجازی HWC، و -1 نمایشگر نامعتبر یا نمایش مجازی غیر HWC است.

با شروع اندروید 10، به نمایشگرها شناسه‌های پایدار و پایدار داده می‌شود که به SurfaceFlinger و DisplayManagerService اجازه می‌دهد بیش از دو نمایشگر را ردیابی کنند و نمایشگرهایی که قبلاً دیده‌شده را تشخیص دهند. اگر HWC از IComposerClient.getDisplayIdentificationData پشتیبانی می‌کند و داده‌های شناسایی نمایشگر را ارائه می‌کند، SurfaceFlinger ساختار EDID را تجزیه می‌کند و شناسه‌های نمایشگر ۶۴ بیتی پایدار را برای نمایشگرهای فیزیکی و مجازی HWC اختصاص می‌دهد. شناسه ها با استفاده از یک نوع گزینه بیان می شوند، جایی که مقدار تهی نشان دهنده یک نمایشگر نامعتبر یا نمایش مجازی غیر HWC است. بدون پشتیبانی HWC، SurfaceFlinger به رفتار قدیمی با حداکثر دو نمایشگر فیزیکی بازمی گردد.

فوکوس هر صفحه نمایش

برای پشتیبانی از چندین منبع ورودی که نمایشگرهای فردی را به طور همزمان هدف قرار می دهند، اندروید 10 را می توان طوری پیکربندی کرد که از چندین پنجره متمرکز، حداکثر یک در هر نمایشگر پشتیبانی کند. این فقط برای انواع خاصی از دستگاه‌ها در نظر گرفته شده است که چندین کاربر به طور همزمان با یک دستگاه تعامل دارند و از روش‌ها یا دستگاه‌های ورودی متفاوتی مانند Android Automotive استفاده می‌کنند.

اکیداً توصیه می‌شود که این ویژگی برای دستگاه‌های معمولی، از جمله دستگاه‌های چند صفحه‌نما یا دستگاه‌هایی که برای تجربه‌هایی شبیه به دسکتاپ استفاده می‌شوند، فعال نشود . این در درجه اول به دلیل یک نگرانی امنیتی است که ممکن است باعث شود کاربران تعجب کنند که کدام پنجره دارای فوکوس ورودی است.

کاربری را تصور کنید که اطلاعات ایمن را در یک قسمت ورودی متن وارد می کند، شاید وارد یک برنامه بانکی شده یا متنی را وارد می کند که حاوی اطلاعات حساس است. یک برنامه مخرب می تواند یک صفحه نمایش مجازی خارج از صفحه ایجاد کند که با آن یک فعالیت را انجام دهد، همچنین با یک فیلد ورودی متن. فعالیت های مشروع و مخرب دارای فوکوس هستند و هر دو یک نشانگر ورودی فعال (مکان نما چشمک زن) را نمایش می دهند.

با این حال، از آنجایی که ورودی از یک صفحه کلید (سخت افزار یا نرم افزار) فقط در بالاترین فعالیت (آن برنامه ای که اخیراً راه اندازی شده است) وارد می شود، با ایجاد یک نمایشگر مجازی مخفی، یک برنامه مخرب می تواند ورودی کاربر را حتی زمانی که از صفحه کلید نرم افزاری در صفحه نمایش دستگاه اصلی استفاده می کند، بگیرد.

برای تنظیم فوکوس هر نمایشگر com.android.internal.R.bool.config_perDisplayFocusEnabled استفاده کنید.

سازگاری

مشکل: در اندروید 9 و پایین تر، حداکثر یک پنجره در سیستم هر بار فوکوس دارد.

راه‌حل: در موارد نادری که دو پنجره از یک فرآیند فوکوس می‌شوند، سیستم تنها به پنجره‌ای که در مرتبه Z بالاتر است فوکوس می‌دهد. این محدودیت برای برنامه هایی که Android 10 را هدف قرار می دهند حذف می شود ، در این مرحله انتظار می رود که آنها بتوانند چندین ویندوز را به طور همزمان متمرکز کنند.

پیاده سازی

WindowManagerService#mPerDisplayFocusEnabled در دسترس بودن این ویژگی را کنترل می کند. در ActivityManager ، ActivityDisplay#getFocusedStack() اکنون به جای ردیابی جهانی در یک متغیر استفاده می شود. ActivityDisplay#getFocusedStack() تمرکز را بر اساس سفارش z به جای ذخیره کردن مقدار تعیین می کند. این به گونه ای است که فقط یک منبع ، WindowManager ، نیاز به ردیابی مرتبه فعالیت ها دارد.

ActivityStackSupervisor#getTopDisplayFocusedStack() برای مواردی که باید بالاترین پشته متمرکز در سیستم مشخص شود ، رویکرد مشابهی را انجام می دهد. پشته ها از بالا به پایین عبور می کنند و اولین پشته واجد شرایط را جستجو می کنند.

InputDispatcher اکنون می تواند چندین ویندوز متمرکز (یک در هر صفحه) داشته باشد. اگر یک رویداد ورودی خاص نمایشگر باشد ، پس از آن به پنجره متمرکز در صفحه نمایش مربوطه اعزام می شود. در غیر این صورت ، آن را به پنجره متمرکز در صفحه نمایش متمرکز اعزام می کند ، این نمایشگر است که کاربر اخیراً با آن در ارتباط است.

به InputDispatcher::mFocusedWindowHandlesByDisplay و InputDispatcher::setFocusedDisplay() مراجعه کنید. برنامه های متمرکز نیز به طور جداگانه در InputManagerService از طریق NativeInputManager::setFocusedApplication() به روز می شوند.

در WindowManager ، ویندوزهای متمرکز نیز به طور جداگانه ردیابی می شوند. به DisplayContent#mCurrentFocus و DisplayContent#mFocusedApp و موارد مربوطه مراجعه کنید. روشهای ردیابی و به روزرسانی تمرکز مرتبط از WindowManagerService به DisplayContent منتقل شده است.

،

به روزرسانی های ساخته شده در این مناطق خاص نمایشگر در زیر ارائه شده است:

تغییر اندازه فعالیت ها و نمایشگرها

برای نشان دادن اینکه یک برنامه ممکن است از حالت چند پنجره یا تغییر اندازه پشتیبانی نکند ، فعالیت ها از resizeableActivity=false استفاده می کنند. موضوعات متداول که توسط برنامه ها هنگام تغییر فعالیت انجام می شود شامل موارد زیر است:

  • یک فعالیت می تواند پیکربندی متفاوتی از برنامه یا یک مؤلفه غیر بصری دیگر داشته باشد. یک اشتباه رایج خواندن معیارهای نمایش از متن برنامه است. مقادیر برگشتی به معیارهای منطقه قابل مشاهده که در آن یک فعالیت نمایش داده می شود تنظیم نمی شود.
  • یک فعالیت ممکن است تغییر اندازه و خرابی نداشته باشد ، یک رابط کاربری تحریف شده را به نمایش بگذارد ، یا به دلیل راه اندازی مجدد بدون صرفه جویی در وضعیت نمونه ، وضعیت خود را از دست بدهد.
  • یک برنامه ممکن است سعی در استفاده از مختصات ورودی مطلق (به جای آنکه نسبت به موقعیت پنجره) باشد ، که ممکن است ورودی را در چند پنجره بشکند.

در Android 7 (و بالاتر) ، یک برنامه می تواند resizeableActivity=false را تنظیم کند تا همیشه در حالت تمام صفحه اجرا شود. در این حالت ، این پلتفرم مانع از فعالیت های غیر قابل تنظیم به صفحه تقسیم می شود. اگر کاربر سعی کند در حالی که در حالت اسپلیت صفحه قرار دارد ، از یک فعالیت غیر قابل تنظیم از پرتابگر استفاده کند ، این پلتفرم از حالت اسپلیت صفحه خارج می شود و فعالیت غیر قابل تنظیم را در حالت تمام صفحه راه اندازی می کند.

برنامه هایی که صریحاً این ویژگی را به false در مانیفست تنظیم می کنند ، نباید در حالت چند پنجره راه اندازی شوند ، مگر اینکه از حالت سازگاری استفاده شود:

  • پیکربندی یکسان برای فرآیند اعمال می شود ، که شامل کلیه فعالیت ها و اجزای غیر فعالیتی است.
  • پیکربندی کاربردی نیازهای CDD را برای نمایشگرهای سازگار با برنامه مطابقت می دهد.

در Android 10 ، این پلتفرم هنوز هم مانع از فعالیت های غیر قابل تنظیم به حالت اسپلیت صفحه می شود ، اما اگر فعالیت یک جهت گیری ثابت یا نسبت ابعاد را اعلام کرده باشد ، می توانند به طور موقت مقیاس شوند. در غیر این صورت ، این فعالیت برای پر کردن کل صفحه نمایش مانند Android 9 و پایین تر تغییر می کند.

اجرای پیش فرض خط مشی زیر را اعمال می کند:

هنگامی که فعالیتی که اعلام شده با چند پنجره از طریق استفاده از android:resizeableActivity ناسازگار است و هنگامی که این فعالیت یکی از شرایط شرح داده شده در زیر را برآورده می کند ، پس از آن که پیکربندی صفحه کاربردی باید تغییر کند ، فعالیت و فرایند با پیکربندی اصلی ذخیره می شود و کاربر با هزینه ای برای استفاده مجدد از فرآیند برنامه برای استفاده از پیکربندی صفحه نمایش به روز شده فراهم می شود.

  • جهت گیری ثابت از طریق استفاده از android:screenOrientation است
  • برنامه با هدف قرار دادن سطح API حداکثر یا حداقل نسبت ابعاد پیش فرض دارد یا نسبت ابعاد را صریح اعلام می کند

این شکل یک فعالیت غیر قابل تنظیم با نسبت ابعاد اعلام شده را نشان می دهد. هنگام تاشو دستگاه ، پنجره در حالی که در حالی که نسبت ابعاد را با استفاده از جعبه نامه مناسب حفظ می کند ، به سمت پایین حرکت می کند. علاوه بر این ، هر بار که منطقه نمایشگر برای فعالیت تغییر می کند ، یک گزینه فعالیت راه اندازی مجدد به کاربر ارائه می شود.

هنگام آشکار کردن دستگاه ، پیکربندی ، اندازه و نسبت ابعاد فعالیت تغییر نمی کند ، اما گزینه راه اندازی مجدد فعالیت نمایش داده می شود.

هنگامی که resizeableActivity تنظیم نشده است (یا روی آن true تنظیم شده است) ، برنامه کاملاً از تغییر اندازه پشتیبانی می کند.

پیاده سازی

یک فعالیت غیر قابل تنظیم با جهت گیری ثابت یا نسبت ابعاد حالت سازگاری اندازه (SCM) در کد نامیده می شود. این شرایط در ActivityRecord#shouldUseSizeCompatMode() تعریف شده است. هنگامی که یک فعالیت SCM راه اندازی می شود ، پیکربندی مربوط به صفحه (مانند اندازه یا تراکم) در پیکربندی درخواست شده Override ثابت می شود ، بنابراین فعالیت دیگر به پیکربندی صفحه نمایش فعلی وابسته نیست.

اگر فعالیت SCM نتواند کل صفحه را پر کند ، از بالا و محور افقی قرار دارد. مرزهای فعالیت توسط AppWindowToken#calculateCompatBoundsTransformation() محاسبه می شود.

هنگامی که یک فعالیت SCM از پیکربندی صفحه نمایش متفاوت از ظرف خود استفاده می کند (به عنوان مثال ، صفحه نمایش تغییر یافته است ، یا فعالیتی که به صفحه دیگری منتقل می شود) ، ActivityRecord#inSizeCompatMode() درست است و SizeCompatModeActivityController (در سیستم UI) تماس تلفنی را دریافت می کند تا دکمه راه اندازی مجدد را نشان دهد.

اندازه و نسبت ابعاد

Android 10 پشتیبانی از نسبت های جدید از نسبت های بالای صفحه های طولانی و نازک را به نسبت 1: 1 پشتیبانی می کند. برنامه ها می توانند ApplicationInfo#maxAspectRatio و ApplicationInfo#minAspectRatio صفحه را که قادر به کنترل آنها هستند تعریف کنند.

نسبت برنامه در اندروید 10

شکل 1. مثال نسبت برنامه پشتیبانی شده در اندروید 10

اجرای دستگاه می تواند دارای نمایشگرهای ثانویه با اندازه و وضوح کوچکتر از موارد مورد نیاز Android 9 و پایین تر باشد (حداقل عرض یا ارتفاع 2.5 اینچ ، حداقل 320 DP برای smallestScreenWidth ) ، اما فقط فعالیت هایی که برای پشتیبانی از این نمایشگرهای کوچک انتخاب می شوند می توانند در آنجا قرار گیرند.

برنامه ها می توانند با اعلام حداقل اندازه پشتیبانی شده که کوچکتر از یا مساوی با اندازه صفحه نمایش هدف هستند ، انتخاب کنند. برای انجام این کار از android:minHeight and android:minWidth Activity Projections در AndroidManifest استفاده کنید.

سیاست های نمایش

Android 10 برخی از خط مشی های نمایشگر را از اجرای پیش فرض WindowManagerPolicy در PhoneWindowManager به کلاس های هر صفحه نمایش جدا می کند و حرکت می کند ، مانند:

  • حالت نمایش و چرخش
  • برخی از کلیدها و ردیابی رویدادهای حرکتی
  • UI سیستم و ویندوز دکوراسیون

در Android 9 (و پایین) ، کلاس PhoneWindowManager سیاست های نمایش ، حالت و تنظیمات ، چرخش ، ردیابی قاب پنجره دکوراسیون و موارد دیگر را اداره می کند. Android 10 بیشتر این موارد را به کلاس DisplayPolicy منتقل می کند ، به جز ردیابی چرخش ، که به DisplayRotation منتقل شده است.

تنظیمات پنجره

در Android 10 ، تنظیمات پنجره ای قابل تنظیم برای هر صفحه نمایش گسترش یافته است که شامل موارد زیر است:

  • حالت پنجره نمایش پیش فرض
  • مقادیر بیش از حد
  • حالت چرخش و چرخش کاربر
  • اندازه اجباری ، چگالی و حالت مقیاس گذاری
  • حالت حذف محتوا (هنگام حذف نمایش)
  • پشتیبانی از تزئینات سیستم و IME

کلاس DisplayWindowSettings شامل تنظیماتی برای این گزینه ها است. آنها ادامه می دهند که هر بار که یک تنظیم تغییر می کند ، پارتیشن DISC /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 با افزایش یک پیشخوان استاتیک برای آن نمایشگر تولید شد. اگر سیستم اضافه شده و همان صفحه را حذف کرده و حذف کند ، یک شناسه متفاوت نتیجه می گیرد.

اگر یک دستگاه چندین نمایشگر از Boot در دسترس باشد ، بسته به زمان بندی ، می توان به نمایشگرها شناسه های مختلفی اختصاص داد. در حالی که 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 Display مشخص می کند ، برمی گرداند. Soursflinger اطلاعات تولید کننده یا مدل را از EDID برای تولید شناسه های صفحه نمایش 64 بیتی پایدار در معرض چارچوب استخراج می کند. اگر این روش پشتیبانی نشود یا خطایی از آن خارج شود ، SurfaceFlinger به حالت MD Legacy باز می گردد ، جایی که 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 وجود حداکثر دو نمایشگر فیزیکی با IDS 0 و 1 کدگذاری شده را فرض کردند.

با شروع با Android 10 ، SurfaceFlinger می تواند از API آهنگساز سخت افزاری (HWC) استفاده کند تا شناسه های صفحه نمایش پایدار تولید کند ، که این امکان را برای مدیریت تعداد دلخواه نمایشگرهای فیزیکی فراهم می کند. برای کسب اطلاعات بیشتر ، به شناسه های صفحه نمایش استاتیک مراجعه کنید.

این چارچوب می تواند پس از به دست آوردن شناسه نمایشگر 64 بیتی از SurfaceControl#getPhysicalDisplayIds یا از یک رویداد Hotplug DisplayEventReceiver ، توکن IBinder برای یک نمایشگر فیزیکی از طریق SurfaceControl#getPhysicalDisplayToken جستجو کند.

در Android 10 (و پایین) ، صفحه اصلی داخلی TYPE_INTERNAL است و تمام نمایشگرهای ثانویه بدون توجه به نوع اتصال ، به عنوان TYPE_EXTERNAL پرچم گذاری می شوند. بنابراین ، نمایشگرهای داخلی اضافی به صورت خارجی رفتار می شوند. به عنوان یک راه حل ، کد خاص دستگاه می تواند فرضیاتی راجع به DisplayAddress.Physical#getPort در صورت شناخته شدن HWC و منطق تخصیص پورت قابل پیش بینی باشد.

این محدودیت در اندروید 11 (و بالاتر) حذف می شود.

  • در اندروید 11 ، اولین صفحه نمایش گزارش شده در هنگام بوت ، صفحه اصلی است. نوع اتصال (داخلی در مقابل خارجی) بی ربط است. با این حال ، این درست است که صفحه اصلی نمی تواند قطع شود و از این رو نتیجه می گیرد که باید در عمل یک نمایشگر داخلی باشد. توجه داشته باشید که برخی از تلفن های تاشو دارای چندین نمایشگاه داخلی هستند.
  • نمایشگرهای ثانویه به درستی به عنوان Display.TYPE_INTERNAL یا Display.TYPE_EXTERNAL (که قبلاً به عنوان Display.TYPE_BUILT_IN و Display.TYPE_HDMI شناخته می شد) بسته به نوع اتصال آنها طبقه بندی می شوند.

پیاده سازی

در اندروید 9 و پایین ، نمایشگرها توسط شناسه های 32 بیتی مشخص می شوند ، جایی که 0 صفحه نمایش داخلی است ، 1 صفحه نمایش خارجی است ، [2, INT32_MAX] نمایشگرهای مجازی HWC هستند و -1 یک نمایش نامعتبر یا یک صفحه نمایش مجازی غیر HWC را نشان می دهد.

با شروع Android 10 ، به نمایشگرها شناسه های پایدار و مداوم داده می شود ، که به SurfaceFlinger و DisplayManagerService اجازه می دهد تا بیش از دو نمایشگر را ردیابی کرده و نمایشگرهای قبلاً دیده شده را تشخیص دهند. اگر HWC از IComposerClient.getDisplayIdentificationData پشتیبانی کند و داده های شناسایی نمایش را ارائه می دهد ، SuffaceFlinger ساختار EDID را تجزیه می کند و شناسه های صفحه نمایش 64 بیتی پایدار را برای نمایشگرهای مجازی فیزیکی و HWC اختصاص می دهد. IDS با استفاده از یک نوع گزینه بیان می شود ، جایی که مقدار تهی نمایانگر یک نمایش نامعتبر یا صفحه نمایش مجازی غیر HWC است. بدون پشتیبانی HWC ، SurfaceFlinger با حداکثر دو نمایشگر فیزیکی به رفتار میراث می رسد.

تمرکز در هر صفحه نمایش

برای پشتیبانی از چندین منبع ورودی که به طور همزمان نمایشگرهای فردی را هدف قرار می دهند ، می توان Android 10 را برای پشتیبانی از چندین ویندوز متمرکز ، حداکثر در هر صفحه نمایش پیکربندی کرد. این فقط برای انواع خاص دستگاه ها در نظر گرفته شده است که چندین کاربر به طور همزمان با همان دستگاه در تعامل هستند و از روش ها یا دستگاه های مختلف ورودی مانند Android Automobile استفاده می کنند.

به شدت توصیه می شود که این ویژگی برای دستگاه های معمولی ، از جمله دستگاه های چند صفحه ای یا آنهایی که برای تجربیات مانند دسک تاپ استفاده می شوند ، فعال نشود . این امر در درجه اول به دلیل نگرانی امنیتی است که ممکن است باعث تعجب کاربران شود که کدام پنجره تمرکز ورودی را دارد.

کاربری را تصور کنید که اطلاعات ایمن را در یک قسمت ورودی متن وارد می کند ، شاید وارد یک برنامه بانکی یا وارد کردن متنی شود که حاوی اطلاعات حساس باشد. یک برنامه مخرب می تواند یک صفحه نمایش مجازی خارج از صفحه را ایجاد کند که با استفاده از آن می توان یک فعالیت را انجام داد ، همچنین با یک قسمت ورودی متن. فعالیت های قانونی و مخرب تمرکز دارد و هر دو یک نشانگر ورودی فعال (مکان نما چشمک زن) را نشان می دهند.

با این حال ، از آنجا که ورودی از صفحه کلید (سخت افزار یا نرم افزار) فقط در بالاترین فعالیت (آن برنامه ای که اخیراً راه اندازی شده است) وارد می شود ، با ایجاد یک صفحه نمایش مجازی پنهان ، یک برنامه مخرب می تواند ورودی کاربر را حتی هنگام استفاده از صفحه کلید نرم افزاری در صفحه اصلی دستگاه بدست آورد.

برای تنظیم تمرکز در هر صفحه ، از com.android.internal.R.bool.config_perDisplayFocusEnabled استفاده کنید.

سازگاری

شماره: در اندروید 9 و پایین ، حداکثر یک پنجره در سیستم در یک زمان تمرکز دارد.

راه حل: در مورد نادر که دو ویندوز از همان فرآیند متمرکز می شوند ، سیستم فقط به پنجره ای که در مرتبه Z بیشتر است ، تمرکز می کند. این محدودیت برای برنامه هایی که Android 10 را هدف قرار می دهند حذف می شود ، در این مرحله انتظار می رود که آنها بتوانند چندین ویندوز را به طور همزمان متمرکز کنند.

پیاده سازی

WindowManagerService#mPerDisplayFocusEnabled در دسترس بودن این ویژگی را کنترل می کند. در ActivityManager ، ActivityDisplay#getFocusedStack() اکنون به جای ردیابی جهانی در یک متغیر استفاده می شود. ActivityDisplay#getFocusedStack() تمرکز را بر اساس سفارش z به جای ذخیره کردن مقدار تعیین می کند. این به گونه ای است که فقط یک منبع ، WindowManager ، نیاز به ردیابی مرتبه فعالیت ها دارد.

ActivityStackSupervisor#getTopDisplayFocusedStack() برای مواردی که باید بالاترین پشته متمرکز در سیستم مشخص شود ، رویکرد مشابهی را انجام می دهد. پشته ها از بالا به پایین عبور می کنند و اولین پشته واجد شرایط را جستجو می کنند.

InputDispatcher اکنون می تواند چندین ویندوز متمرکز (یک در هر صفحه) داشته باشد. اگر یک رویداد ورودی خاص نمایشگر باشد ، پس از آن به پنجره متمرکز در صفحه نمایش مربوطه اعزام می شود. در غیر این صورت ، آن را به پنجره متمرکز در صفحه نمایش متمرکز اعزام می کند ، این نمایشگر است که کاربر اخیراً با آن در ارتباط است.

به InputDispatcher::mFocusedWindowHandlesByDisplay و InputDispatcher::setFocusedDisplay() مراجعه کنید. برنامه های متمرکز نیز به طور جداگانه در InputManagerService از طریق NativeInputManager::setFocusedApplication() به روز می شوند.

در WindowManager ، ویندوزهای متمرکز نیز به طور جداگانه ردیابی می شوند. به DisplayContent#mCurrentFocus و DisplayContent#mFocusedApp و موارد مربوطه مراجعه کنید. روشهای ردیابی و به روزرسانی تمرکز مرتبط از WindowManagerService به DisplayContent منتقل شده است.

،

به روزرسانی های ساخته شده در این مناطق خاص نمایشگر در زیر ارائه شده است:

تغییر اندازه فعالیت ها و نمایشگرها

برای نشان دادن اینکه یک برنامه ممکن است از حالت چند پنجره یا تغییر اندازه پشتیبانی نکند ، فعالیت ها از resizeableActivity=false استفاده می کنند. موضوعات متداول که توسط برنامه ها هنگام تغییر فعالیت انجام می شود شامل موارد زیر است:

  • یک فعالیت می تواند پیکربندی متفاوتی از برنامه یا یک مؤلفه غیر بصری دیگر داشته باشد. یک اشتباه رایج خواندن معیارهای نمایش از متن برنامه است. مقادیر برگشتی به معیارهای منطقه قابل مشاهده که در آن یک فعالیت نمایش داده می شود تنظیم نمی شود.
  • یک فعالیت ممکن است تغییر اندازه و خرابی نداشته باشد ، یک رابط کاربری تحریف شده را به نمایش بگذارد ، یا به دلیل راه اندازی مجدد بدون صرفه جویی در وضعیت نمونه ، وضعیت خود را از دست بدهد.
  • یک برنامه ممکن است سعی در استفاده از مختصات ورودی مطلق (به جای آنکه نسبت به موقعیت پنجره) باشد ، که ممکن است ورودی را در چند پنجره بشکند.

در Android 7 (و بالاتر) ، یک برنامه می تواند resizeableActivity=false را تنظیم کند تا همیشه در حالت تمام صفحه اجرا شود. در این حالت ، این پلتفرم مانع از فعالیت های غیر قابل تنظیم به صفحه تقسیم می شود. اگر کاربر سعی کند در حالی که در حالت اسپلیت صفحه قرار دارد ، از یک فعالیت غیر قابل تنظیم از پرتابگر استفاده کند ، این پلتفرم از حالت اسپلیت صفحه خارج می شود و فعالیت غیر قابل تنظیم را در حالت تمام صفحه راه اندازی می کند.

برنامه هایی که صریحاً این ویژگی را به false در مانیفست تنظیم می کنند ، نباید در حالت چند پنجره راه اندازی شوند ، مگر اینکه از حالت سازگاری استفاده شود:

  • پیکربندی یکسان برای فرآیند اعمال می شود ، که شامل کلیه فعالیت ها و اجزای غیر فعالیتی است.
  • پیکربندی کاربردی نیازهای CDD را برای نمایشگرهای سازگار با برنامه مطابقت می دهد.

در Android 10 ، این پلتفرم هنوز هم مانع از فعالیت های غیر قابل تنظیم به حالت اسپلیت صفحه می شود ، اما اگر فعالیت یک جهت گیری ثابت یا نسبت ابعاد را اعلام کرده باشد ، می توانند به طور موقت مقیاس شوند. در غیر این صورت ، این فعالیت برای پر کردن کل صفحه نمایش مانند Android 9 و پایین تر تغییر می کند.

اجرای پیش فرض خط مشی زیر را اعمال می کند:

هنگامی که فعالیتی که اعلام شده با چند پنجره از طریق استفاده از android:resizeableActivity ناسازگار است و هنگامی که این فعالیت یکی از شرایط شرح داده شده در زیر را برآورده می کند ، پس از آن که پیکربندی صفحه کاربردی باید تغییر کند ، فعالیت و فرایند با پیکربندی اصلی ذخیره می شود و کاربر با هزینه ای برای استفاده مجدد از فرآیند برنامه برای استفاده از پیکربندی صفحه نمایش به روز شده فراهم می شود.

  • جهت گیری ثابت از طریق استفاده از android:screenOrientation است
  • برنامه با هدف قرار دادن سطح API حداکثر یا حداقل نسبت ابعاد پیش فرض دارد یا نسبت ابعاد را صریح اعلام می کند

این شکل یک فعالیت غیر قابل تنظیم با نسبت ابعاد اعلام شده را نشان می دهد. هنگام تاشو دستگاه ، پنجره در حالی که در حالی که نسبت ابعاد را با استفاده از جعبه نامه مناسب حفظ می کند ، به سمت پایین حرکت می کند. علاوه بر این ، هر بار که منطقه نمایشگر برای فعالیت تغییر می کند ، یک گزینه فعالیت راه اندازی مجدد به کاربر ارائه می شود.

هنگام آشکار کردن دستگاه ، پیکربندی ، اندازه و نسبت ابعاد فعالیت تغییر نمی کند ، اما گزینه راه اندازی مجدد فعالیت نمایش داده می شود.

هنگامی که resizeableActivity تنظیم نشده است (یا روی آن true تنظیم شده است) ، برنامه کاملاً از تغییر اندازه پشتیبانی می کند.

پیاده سازی

یک فعالیت غیر قابل تنظیم با جهت گیری ثابت یا نسبت ابعاد حالت سازگاری اندازه (SCM) در کد نامیده می شود. این شرایط در ActivityRecord#shouldUseSizeCompatMode() تعریف شده است. هنگامی که یک فعالیت SCM راه اندازی می شود ، پیکربندی مربوط به صفحه (مانند اندازه یا تراکم) در پیکربندی درخواست شده Override ثابت می شود ، بنابراین فعالیت دیگر به پیکربندی صفحه نمایش فعلی وابسته نیست.

اگر فعالیت SCM نتواند کل صفحه را پر کند ، از بالا و محور افقی قرار دارد. مرزهای فعالیت توسط AppWindowToken#calculateCompatBoundsTransformation() محاسبه می شود.

هنگامی که یک فعالیت SCM از پیکربندی صفحه نمایش متفاوت از ظرف خود استفاده می کند (به عنوان مثال ، صفحه نمایش تغییر یافته است ، یا فعالیتی که به صفحه دیگری منتقل می شود) ، ActivityRecord#inSizeCompatMode() درست است و SizeCompatModeActivityController (در سیستم UI) تماس تلفنی را دریافت می کند تا دکمه راه اندازی مجدد را نشان دهد.

اندازه و نسبت ابعاد

Android 10 پشتیبانی از نسبت های جدید از نسبت های بالای صفحه های طولانی و نازک را به نسبت 1: 1 پشتیبانی می کند. برنامه ها می توانند ApplicationInfo#maxAspectRatio و ApplicationInfo#minAspectRatio صفحه را که قادر به کنترل آنها هستند تعریف کنند.

نسبت برنامه در اندروید 10

شکل 1. مثال نسبت برنامه پشتیبانی شده در اندروید 10

اجرای دستگاه می تواند دارای نمایشگرهای ثانویه با اندازه و وضوح کوچکتر از موارد مورد نیاز Android 9 و پایین تر باشد (حداقل عرض یا ارتفاع 2.5 اینچ ، حداقل 320 DP برای smallestScreenWidth ) ، اما فقط فعالیت هایی که برای پشتیبانی از این نمایشگرهای کوچک انتخاب می شوند می توانند در آنجا قرار گیرند.

برنامه ها می توانند با اعلام حداقل اندازه پشتیبانی شده که کوچکتر از یا مساوی با اندازه صفحه نمایش هدف هستند ، انتخاب کنند. برای انجام این کار از android:minHeight and android:minWidth Activity Projections در AndroidManifest استفاده کنید.

سیاست های نمایش

Android 10 برخی از خط مشی های نمایشگر را از اجرای پیش فرض WindowManagerPolicy در PhoneWindowManager به کلاس های هر صفحه نمایش جدا می کند و حرکت می کند ، مانند:

  • حالت نمایش و چرخش
  • برخی از کلیدها و ردیابی رویدادهای حرکتی
  • UI سیستم و ویندوز دکوراسیون

در Android 9 (و پایین) ، کلاس PhoneWindowManager سیاست های نمایش ، حالت و تنظیمات ، چرخش ، ردیابی قاب پنجره دکوراسیون و موارد دیگر را اداره می کند. Android 10 بیشتر این موارد را به کلاس DisplayPolicy منتقل می کند ، به جز ردیابی چرخش ، که به DisplayRotation منتقل شده است.

تنظیمات پنجره

در Android 10 ، تنظیمات پنجره ای قابل تنظیم برای هر صفحه نمایش گسترش یافته است که شامل موارد زیر است:

  • حالت پنجره نمایش پیش فرض
  • مقادیر بیش از حد
  • حالت چرخش و چرخش کاربر
  • اندازه اجباری ، چگالی و حالت مقیاس گذاری
  • حالت حذف محتوا (هنگام حذف نمایش)
  • پشتیبانی از تزئینات سیستم و IME

کلاس DisplayWindowSettings شامل تنظیماتی برای این گزینه ها است. آنها ادامه می دهند که هر بار که یک تنظیم تغییر می کند ، پارتیشن DISC /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 با افزایش یک پیشخوان استاتیک برای آن نمایشگر تولید شد. اگر سیستم اضافه شده و همان صفحه را حذف کرده و حذف کند ، یک شناسه متفاوت نتیجه می گیرد.

اگر یک دستگاه چندین نمایشگر از Boot در دسترس باشد ، بسته به زمان بندی ، می توان به نمایشگرها شناسه های مختلفی اختصاص داد. در حالی که 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 Display مشخص می کند ، برمی گرداند. Soursflinger اطلاعات تولید کننده یا مدل را از EDID برای تولید شناسه های صفحه نمایش 64 بیتی پایدار در معرض چارچوب استخراج می کند. اگر این روش پشتیبانی نشود یا خطایی از آن خارج شود ، SurfaceFlinger به حالت MD Legacy باز می گردد ، جایی که 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 وجود حداکثر دو نمایشگر فیزیکی با IDS 0 و 1 کدگذاری شده را فرض کردند.

با شروع با Android 10 ، SurfaceFlinger می تواند از API آهنگساز سخت افزاری (HWC) استفاده کند تا شناسه های صفحه نمایش پایدار تولید کند ، که این امکان را برای مدیریت تعداد دلخواه نمایشگرهای فیزیکی فراهم می کند. برای کسب اطلاعات بیشتر ، به شناسه های صفحه نمایش استاتیک مراجعه کنید.

این چارچوب می تواند پس از به دست آوردن شناسه نمایشگر 64 بیتی از SurfaceControl#getPhysicalDisplayIds یا از یک رویداد Hotplug DisplayEventReceiver ، توکن IBinder برای یک نمایشگر فیزیکی از طریق SurfaceControl#getPhysicalDisplayToken جستجو کند.

در Android 10 (و پایین) ، صفحه اصلی داخلی TYPE_INTERNAL است و تمام نمایشگرهای ثانویه بدون توجه به نوع اتصال ، به عنوان TYPE_EXTERNAL پرچم گذاری می شوند. بنابراین ، نمایشگرهای داخلی اضافی به صورت خارجی رفتار می شوند. به عنوان یک راه حل ، کد خاص دستگاه می تواند فرضیاتی راجع به DisplayAddress.Physical#getPort در صورت شناخته شدن HWC و منطق تخصیص پورت قابل پیش بینی باشد.

این محدودیت در اندروید 11 (و بالاتر) حذف می شود.

  • در اندروید 11 ، اولین صفحه نمایش گزارش شده در هنگام بوت ، صفحه اصلی است. نوع اتصال (داخلی در مقابل خارجی) بی ربط است. با این حال ، این درست است که صفحه اصلی نمی تواند قطع شود و از این رو نتیجه می گیرد که باید در عمل یک نمایشگر داخلی باشد. توجه داشته باشید که برخی از تلفن های تاشو دارای چندین نمایشگاه داخلی هستند.
  • نمایشگرهای ثانویه به درستی به عنوان Display.TYPE_INTERNAL یا Display.TYPE_EXTERNAL (که قبلاً به عنوان Display.TYPE_BUILT_IN و Display.TYPE_HDMI شناخته می شد) بسته به نوع اتصال آنها طبقه بندی می شوند.

پیاده سازی

در اندروید 9 و پایین ، نمایشگرها توسط شناسه های 32 بیتی مشخص می شوند ، جایی که 0 صفحه نمایش داخلی است ، 1 صفحه نمایش خارجی است ، [2, INT32_MAX] نمایشگرهای مجازی HWC هستند و -1 یک نمایش نامعتبر یا یک صفحه نمایش مجازی غیر HWC را نشان می دهد.

با شروع Android 10 ، به نمایشگرها شناسه های پایدار و مداوم داده می شود ، که به SurfaceFlinger و DisplayManagerService اجازه می دهد تا بیش از دو نمایشگر را ردیابی کرده و نمایشگرهای قبلاً دیده شده را تشخیص دهند. اگر HWC از IComposerClient.getDisplayIdentificationData پشتیبانی کند و داده های شناسایی نمایش را ارائه می دهد ، SuffaceFlinger ساختار EDID را تجزیه می کند و شناسه های صفحه نمایش 64 بیتی پایدار را برای نمایشگرهای مجازی فیزیکی و HWC اختصاص می دهد. IDS با استفاده از یک نوع گزینه بیان می شود ، جایی که مقدار تهی نمایانگر یک نمایش نامعتبر یا صفحه نمایش مجازی غیر HWC است. بدون پشتیبانی HWC ، SurfaceFlinger با حداکثر دو نمایشگر فیزیکی به رفتار میراث می رسد.

تمرکز در هر صفحه نمایش

To support several input sources that target individual displays at the same time, Android 10 can be configured to support multiple focused windows, at most one per-display. This is intended only for special types of devices when multiple users interact with the same device at the same time and use different input methods or devices, such as Android Automotive.

It is strongly recommended that this feature not be enabled for regular devices, including multi-screen devices or those used for desktop-like experiences. This is due primarily to a security concern that may cause users to wonder which window has input focus.

Imagine the user who enters secure information into a text input field, perhaps logging in to a banking app or entering text that contains sensitive information. A malicious app could create a virtual off-screen display with which to execute an activity, also with a text input field. Legitimate and malicious activities have focus and both display an active input indicator (blinking cursor).

However, since input from a keyboard (hardware or software) is entered into the topmost activity only (that app that was most recently launched), by creating a hidden virtual display, a malicious app could grab user input, even when using a software keyboard on the primary device display.

Use com.android.internal.R.bool.config_perDisplayFocusEnabled to set per-display focus.

سازگاری

Issue: In Android 9 and lower, at most one window in the system has focus at a time.

Solution: In the rare case when two windows from the same process would be focused, the system provides focus only to the window that's higher in the Z-order. This restriction is removed for apps that target Android 10, at which point it's expected that they can support multiple windows being focused on simultaneously.

پیاده سازی

WindowManagerService#mPerDisplayFocusEnabled controls the availability of this feature. In ActivityManager , ActivityDisplay#getFocusedStack() is now used instead of global tracking in a variable. ActivityDisplay#getFocusedStack() determines focus based on Z-order instead of caching the value. This is so that only one source, WindowManager, need track the Z-order of activities.

ActivityStackSupervisor#getTopDisplayFocusedStack() takes a similar approach for those cases when the topmost focused stack in the system must be identified. The stacks are traversed from top to bottom, searching for the first eligible stack.

InputDispatcher can now have multiple focused windows (one per display). If an input event is display-specific, then it's dispatched to the focused window in the corresponding display. Otherwise, it's dispatched to the focused window in the focused display, which is the display that the user most recently interacted with.

See InputDispatcher::mFocusedWindowHandlesByDisplay and InputDispatcher::setFocusedDisplay() . Focused apps are also updated separately in InputManagerService through NativeInputManager::setFocusedApplication() .

In WindowManager , focused windows are also tracked separately. See DisplayContent#mCurrentFocus and DisplayContent#mFocusedApp and the respective uses. Related focus tracking and updating methods have been moved from WindowManagerService to DisplayContent .