پشتیبانی از دکوراسیون سیستم

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

تزئینات سیستم

اندروید 10 از پیکربندی نمایشگرهای ثانویه برای نمایش تزئینات خاص سیستم مانند کاغذ دیواری، نوار ناوبری و راه‌انداز پشتیبانی می‌کند. به‌طور پیش‌فرض، نمایشگر اصلی تمام تزئینات سیستم را نشان می‌دهد و نمایشگرهای ثانویه مواردی را که به صورت اختیاری فعال هستند نشان می‌دهند. پشتیبانی از یک ویرایشگر روش ورودی (IME) را می توان جدا از سایر تزئینات سیستم تنظیم کرد.

از DisplayWindowSettings#setShouldShowSystemDecorsLocked() برای اضافه کردن پشتیبانی از تزئینات سیستم در یک نمایشگر خاص یا ارائه یک مقدار پیش فرض در /data/system/display_settings.xml استفاده کنید. برای مثال، تنظیمات پنجره نمایش را ببینید.

پیاده سازی

DisplayWindowSettings#setShouldShowSystemDecorsLocked() نیز در WindowManager#setShouldShowSystemDecors() برای آزمایش نمایش داده می شود. راه‌اندازی این روش با هدف فعال کردن دکورهای سیستم، پنجره‌های دکوری را که قبلاً گم شده بودند اضافه نمی‌کند، یا اگر قبلاً وجود داشته‌اند، آن‌ها را حذف نمی‌کند. در بیشتر موارد، تغییر پشتیبانی از تزئینات سیستم تنها پس از راه‌اندازی مجدد دستگاه کاملاً تأثیر می‌گذارد.

بررسی‌های پشتیبانی از تزئینات سیستم در پایگاه کد WindowManager معمولاً از طریق DisplayContent#supportsSystemDecorations() انجام می‌شود، در حالی که بررسی‌های مربوط به سرویس‌های خارجی (مانند رابط کاربری سیستم برای بررسی اینکه آیا نوار پیمایش باید نشان داده شود) از WindowManager#shouldShowSystemDecors() استفاده می‌کند. برای درک اینکه چه چیزی توسط این تنظیم کنترل می شود، نقاط تماس این روش ها را بررسی کنید.

پنجره های دکور رابط کاربری سیستم

Android 10 پشتیبانی از پنجره تزئینی سیستم را فقط برای نوار پیمایش اضافه می کند، زیرا نوار پیمایش برای پیمایش بین فعالیت ها و برنامه ها ضروری است. به طور پیش‌فرض، نوار پیمایش هزینه‌های بازگشت و خانه را نشان می‌دهد. این فقط در صورتی گنجانده می شود که نمایشگر هدف از تزئینات سیستم پشتیبانی کند (به DisplayWindowSettings مراجعه کنید).

نوار وضعیت یک پنجره سیستم پیچیده‌تر است، زیرا شامل Notification Shade، تنظیمات سریع و Lock Screen نیز می‌شود. در اندروید 10، نوار وضعیت در نمایشگرهای ثانویه پشتیبانی نمی شود. بنابراین، اعلان ها، تنظیمات و یک صفحه کلید کامل فقط در صفحه نمایش اصلی در دسترس هستند.

پنجره سیستم نمای کلی/اخیرا در صفحه‌های ثانویه پشتیبانی نمی‌شود. در اندروید 10، AOSP فقط Recents را در نمایشگر پیش‌فرض نمایش می‌دهد و شامل فعالیت‌هایی از همه نمایشگرها است. هنگامی که از Recents راه اندازی می شود، فعالیتی که در یک نمایشگر ثانویه بود به طور پیش فرض در جلوی آن نمایشگر آورده می شود. این رویکرد دارای برخی مشکلات شناخته شده است، مانند عدم به روز رسانی فوری زمانی که برنامه ها در صفحه های دیگر ظاهر می شوند.

پیاده سازی

برای پیاده‌سازی ویژگی‌های اضافی System UI، سازندگان دستگاه باید از یک جزء System UI استفاده کنند که به اضافه/حذف نمایشگرها گوش دهد و محتوای مناسب را ارائه دهد.

یک مؤلفه رابط کاربری سیستم که از چند نمایشگر (MD) پشتیبانی می کند باید موارد زیر را مدیریت کند:

  • مقداردهی اولیه نمایشگر در هنگام راه اندازی
  • نمایشگر در زمان اجرا اضافه شد
  • نمایشگر در زمان اجرا حذف شد

وقتی System UI اضافه شدن یک نمایشگر را قبل از WindowManager تشخیص می‌دهد، یک شرط مسابقه ایجاد می‌کند. هنگامی که نمایشگری به جای اشتراک در رویدادهای DisplayManager .DisplayListener اضافه می شود، می توان با اجرای یک پاسخ تماس سفارشی از WindowManager به System UI اجتناب کرد. برای اجرای مرجع، CommandQueue.Callbacks#onDisplayReady برای پشتیبانی از نوار ناوبری و WallpaperManagerInternal#onDisplayReady برای تصاویر پس زمینه ببینید.

علاوه بر این، اندروید 10 این به روز رسانی ها را ارائه می دهد:

  • کلاس NavigationBarController تمام عملکردهای مخصوص نوارهای ناوبری را کنترل می کند.
  • برای مشاهده نوار پیمایش سفارشی شده، CarStatusBar ببینید.
  • TYPE_NAVIGATION_BAR دیگر محدود به یک نمونه نیست و می‌تواند در هر نمایشگر استفاده شود.
  • IWindowManager#hasNavigationBar() به‌روزرسانی می‌شود تا پارامتر displayId را فقط برای System UI شامل شود.

پرتاب کننده

در Android 10، هر صفحه نمایشی که برای پشتیبانی از تزئینات سیستم پیکربندی شده است، به طور پیش‌فرض دارای یک پشته خانه اختصاصی برای فعالیت‌های راه‌انداز با نوع WindowConfiguration#ACTIVITY_TYPE_HOME است. هر نمایشگر از یک نمونه جداگانه از فعالیت راه‌انداز استفاده می‌کند.

شکل 1. نمونه راه‌انداز چند نمایشگر برای platform/development/samples/MultiDisplay

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

<activity>
    ...
    <intent-filter>
        <category android:name="android.intent.category.SECONDARY_HOME" />
        ...
    </intent-filter>
</activity>

فعالیت باید حالت راه اندازی داشته باشد که از چندین نمونه جلوگیری نمی کند و انتظار می رود با اندازه های مختلف صفحه سازگار شود. حالت راه اندازی نمی تواند singleInstance یا singleTask باشد.

پیاده سازی

در اندروید 10، RootActivityContainer#startHomeOnDisplay() به طور خودکار مؤلفه و هدف مورد نظر را بسته به نمایشگری که در آن صفحه اصلی راه اندازی می شود، انتخاب می کند. RootActivityContainer#resolveSecondaryHomeActivity() حاوی منطق جستجوی مؤلفه فعالیت راه‌انداز بسته به راه‌انداز فعلی انتخاب شده است و در صورت نیاز می‌تواند از پیش‌فرض سیستم استفاده کند (به ActivityTaskManagerService#getSecondaryHomeIntent() ) مراجعه کنید.

محدودیت های امنیتی

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

تصاویر پس زمینه

در اندروید 10 (و بالاتر)، تصاویر پس زمینه در نمایشگرهای ثانویه پشتیبانی می شوند:

شکل 2. تصویر زمینه زنده در نمایشگرهای داخلی (بالا) و خارجی (زیر)

توسعه دهندگان می توانند با ارائه android:supportsMultipleDisplays="true" در تعریف WallpaperInfo XML از ویژگی تصویر زمینه حمایت کنند. همچنین از توسعه دهندگان کاغذ دیواری انتظار می رود که دارایی ها را با استفاده از زمینه نمایش در WallpaperService.Engine#getDisplayContext() بارگیری کنند.

این چارچوب در هر نمایشگر یک نمونه WallpaperService.Engine ایجاد می کند، بنابراین هر موتور سطح و زمینه نمایش خود را دارد. توسعه‌دهنده باید مطمئن شود که هر موتور می‌تواند به‌طور مستقل، با نرخ فریم‌های مختلف، با رعایت VSYNC طراحی کند.

تصاویر پس زمینه را برای هر صفحه نمایش انتخاب کنید

اندروید 10 برای انتخاب تصاویر پس زمینه برای هر صفحه نمایش پشتیبانی نمی کند. برای انجام این کار، به یک شناسه نمایشگر پایدار برای تداوم تنظیمات کاغذدیواری در هر نمایشگر نیاز است. Display#getDisplayId() پویا است، بنابراین هیچ تضمینی وجود ندارد که یک نمایشگر فیزیکی پس از راه اندازی مجدد همان شناسه را داشته باشد.

با این حال، Android 10 DisplayInfo.mAddress اضافه کرد که حاوی شناسه های پایدار برای نمایشگرهای فیزیکی است و می تواند برای اجرای کامل در آینده استفاده شود. متاسفانه برای پیاده سازی منطق اندروید 10 خیلی دیر شده است. راه حل پیشنهادی:

  1. از WallpaperManager API برای تنظیم تصاویر پس زمینه استفاده کنید.
  2. WallpaperManager از یک شی Context بدست می آید و هر شی Context اطلاعاتی در مورد نمایش مربوطه دارد ( Context#getDisplay()/getDisplayId() ). بنابراین، می‌توانید displayId از یک نمونه WallpaperManager بدون اضافه کردن روش‌های جدید دریافت کنید.
  3. در سمت چارچوب، از displayId به دست آمده از یک شی Context استفاده کنید و آن را به یک شناسه ثابت (مانند یک پورت نمایش فیزیکی) نگاشت کنید. از شناسه ثابت برای ماندگاری تصویر زمینه انتخابی استفاده کنید.

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

اگر نیاز به تنظیم کاغذ دیواری برای نمایشگری غیر از نمایشگر فعلی وجود دارد، سپس یک شی Context جدید برای نمایشگر هدف ایجاد کنید ( Context#createDisplayContext ) و نمونه WallpaperManager از آن نمایشگر دریافت کنید.

محدودیت های امنیتی

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

پیاده سازی

در اندروید 10، رابط های IWallpaperConnection#attachEngine() و IWallpaperService#attach() پارامتر displayId را برای ایجاد اتصالات هر نمایشگر می پذیرند. WallpaperManagerService.DisplayConnector یک موتور کاغذ دیواری و اتصال به ازای هر نمایشگر را در بر می گیرد. در WindowManager، به جای یک WallpaperController برای همه نمایشگرها، برای هر شی DisplayContent در هنگام ساخت، کنترل‌کننده‌های کاغذدیواری ایجاد می‌شوند.

برخی از پیاده سازی های عمومی متد WallpaperManager (مانند WallpaperManager#getDesiredMinimumWidth() ) برای محاسبه و ارائه اطلاعات برای نمایشگرهای مربوطه به روز شدند. WallpaperInfo#supportsMultipleDisplays() و یک ویژگی منبع مربوطه اضافه شد، به طوری که توسعه دهندگان برنامه می توانند گزارش دهند که کدام والپیپرها برای چندین صفحه آماده هستند.

اگر سرویس کاغذدیواری نشان داده شده در نمایشگر پیش‌فرض از نمایشگرهای متعدد پشتیبانی نمی‌کند، سیستم تصویر زمینه پیش‌فرض را روی نمایشگرهای ثانویه نشان می‌دهد.

شکل 3. منطق بازگشتی کاغذ دیواری برای نمایشگرهای ثانویه

،

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

تزئینات سیستم

اندروید 10 از پیکربندی نمایشگرهای ثانویه برای نمایش تزئینات خاص سیستم مانند کاغذ دیواری، نوار ناوبری و راه‌انداز پشتیبانی می‌کند. به‌طور پیش‌فرض، نمایشگر اصلی تمام تزئینات سیستم را نشان می‌دهد و نمایشگرهای ثانویه مواردی را که به صورت اختیاری فعال هستند نشان می‌دهند. پشتیبانی از یک ویرایشگر روش ورودی (IME) را می توان جدا از سایر تزئینات سیستم تنظیم کرد.

از DisplayWindowSettings#setShouldShowSystemDecorsLocked() برای اضافه کردن پشتیبانی از تزئینات سیستم در یک نمایشگر خاص یا ارائه یک مقدار پیش فرض در /data/system/display_settings.xml استفاده کنید. برای مثال، تنظیمات پنجره نمایش را ببینید.

پیاده سازی

DisplayWindowSettings#setShouldShowSystemDecorsLocked() نیز در WindowManager#setShouldShowSystemDecors() برای آزمایش نمایش داده می شود. راه‌اندازی این روش با هدف فعال کردن دکورهای سیستم، پنجره‌های دکوری را که قبلاً گم شده بودند اضافه نمی‌کند، یا اگر قبلاً وجود داشته‌اند، آن‌ها را حذف نمی‌کند. در بیشتر موارد، تغییر پشتیبانی از تزئینات سیستم تنها پس از راه‌اندازی مجدد دستگاه کاملاً تأثیر می‌گذارد.

بررسی‌های پشتیبانی از تزئینات سیستم در پایگاه کد WindowManager معمولاً از طریق DisplayContent#supportsSystemDecorations() انجام می‌شود، در حالی که بررسی‌های مربوط به سرویس‌های خارجی (مانند رابط کاربری سیستم برای بررسی اینکه آیا نوار پیمایش باید نشان داده شود) از WindowManager#shouldShowSystemDecors() استفاده می‌کند. برای درک اینکه چه چیزی توسط این تنظیم کنترل می شود، نقاط تماس این روش ها را بررسی کنید.

پنجره های دکور رابط کاربری سیستم

Android 10 پشتیبانی از پنجره تزئینی سیستم را فقط برای نوار پیمایش اضافه می کند، زیرا نوار پیمایش برای پیمایش بین فعالیت ها و برنامه ها ضروری است. به طور پیش‌فرض، نوار پیمایش هزینه‌های بازگشت و خانه را نشان می‌دهد. این فقط در صورتی گنجانده می شود که نمایشگر هدف از تزئینات سیستم پشتیبانی کند (به DisplayWindowSettings مراجعه کنید).

نوار وضعیت یک پنجره سیستم پیچیده‌تر است، زیرا شامل Notification Shade، تنظیمات سریع و Lock Screen نیز می‌شود. در اندروید 10، نوار وضعیت در نمایشگرهای ثانویه پشتیبانی نمی شود. بنابراین، اعلان ها، تنظیمات و یک صفحه کلید کامل فقط در صفحه نمایش اصلی در دسترس هستند.

پنجره سیستم نمای کلی/اخیرا در صفحه‌های ثانویه پشتیبانی نمی‌شود. در اندروید 10، AOSP فقط Recents را در نمایشگر پیش‌فرض نمایش می‌دهد و شامل فعالیت‌هایی از همه نمایشگرها است. هنگامی که از Recents راه اندازی می شود، فعالیتی که در یک نمایشگر ثانویه بود به طور پیش فرض در جلوی آن نمایشگر آورده می شود. این رویکرد دارای برخی مشکلات شناخته شده است، مانند عدم به روز رسانی فوری زمانی که برنامه ها در صفحه های دیگر ظاهر می شوند.

پیاده سازی

برای پیاده‌سازی ویژگی‌های اضافی System UI، سازندگان دستگاه باید از یک جزء System UI استفاده کنند که به اضافه/حذف نمایشگرها گوش دهد و محتوای مناسب را ارائه دهد.

یک مؤلفه رابط کاربری سیستم که از چند نمایشگر (MD) پشتیبانی می کند باید موارد زیر را مدیریت کند:

  • مقداردهی اولیه نمایشگر در هنگام راه اندازی
  • نمایشگر در زمان اجرا اضافه شد
  • نمایشگر در زمان اجرا حذف شد

وقتی System UI اضافه شدن یک نمایشگر را قبل از WindowManager تشخیص می‌دهد، یک شرط مسابقه ایجاد می‌کند. هنگامی که نمایشگری به جای اشتراک در رویدادهای DisplayManager .DisplayListener اضافه می شود، می توان با اجرای یک پاسخ تماس سفارشی از WindowManager به System UI اجتناب کرد. برای اجرای مرجع، CommandQueue.Callbacks#onDisplayReady برای پشتیبانی از نوار ناوبری و WallpaperManagerInternal#onDisplayReady برای تصاویر پس زمینه ببینید.

علاوه بر این، اندروید 10 این به روز رسانی ها را ارائه می دهد:

  • کلاس NavigationBarController تمام عملکردهای مخصوص نوارهای ناوبری را کنترل می کند.
  • برای مشاهده نوار پیمایش سفارشی شده، CarStatusBar ببینید.
  • TYPE_NAVIGATION_BAR دیگر محدود به یک نمونه نیست و می‌تواند در هر نمایشگر استفاده شود.
  • IWindowManager#hasNavigationBar() به‌روزرسانی می‌شود تا پارامتر displayId را فقط برای System UI شامل شود.

پرتاب کننده

در Android 10، هر صفحه نمایشی که برای پشتیبانی از تزئینات سیستم پیکربندی شده است، به طور پیش‌فرض دارای یک پشته خانه اختصاصی برای فعالیت‌های راه‌انداز با نوع WindowConfiguration#ACTIVITY_TYPE_HOME است. هر نمایشگر از یک نمونه جداگانه از فعالیت راه‌انداز استفاده می‌کند.

شکل 1. نمونه راه‌انداز چند نمایشگر برای platform/development/samples/MultiDisplay

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

<activity>
    ...
    <intent-filter>
        <category android:name="android.intent.category.SECONDARY_HOME" />
        ...
    </intent-filter>
</activity>

فعالیت باید حالت راه اندازی داشته باشد که از چندین نمونه جلوگیری نمی کند و انتظار می رود با اندازه های مختلف صفحه سازگار شود. حالت راه اندازی نمی تواند singleInstance یا singleTask باشد.

پیاده سازی

در اندروید 10، RootActivityContainer#startHomeOnDisplay() به طور خودکار مؤلفه و هدف مورد نظر را بسته به نمایشگری که در آن صفحه اصلی راه اندازی می شود، انتخاب می کند. RootActivityContainer#resolveSecondaryHomeActivity() حاوی منطق جستجوی مؤلفه فعالیت راه‌انداز بسته به راه‌انداز فعلی انتخاب شده است و در صورت نیاز می‌تواند از پیش‌فرض سیستم استفاده کند (به ActivityTaskManagerService#getSecondaryHomeIntent() ) مراجعه کنید.

محدودیت های امنیتی

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

تصاویر پس زمینه

در اندروید 10 (و بالاتر)، تصاویر پس زمینه در نمایشگرهای ثانویه پشتیبانی می شوند:

شکل 2. تصویر زمینه زنده در نمایشگرهای داخلی (بالا) و خارجی (زیر)

توسعه دهندگان می توانند با ارائه android:supportsMultipleDisplays="true" در تعریف WallpaperInfo XML از ویژگی تصویر زمینه حمایت کنند. همچنین از توسعه دهندگان کاغذ دیواری انتظار می رود که دارایی ها را با استفاده از زمینه نمایش در WallpaperService.Engine#getDisplayContext() بارگیری کنند.

چارچوب در هر نمایشگر یک نمونه WallpaperService.Engine ایجاد می کند، بنابراین هر موتور سطح و زمینه نمایش خود را دارد. توسعه دهنده باید مطمئن شود که هر موتور می تواند به طور مستقل، با نرخ فریم های مختلف، با رعایت VSYNC طراحی کند.

تصاویر پس زمینه را برای هر صفحه نمایش انتخاب کنید

اندروید 10 برای انتخاب تصاویر پس زمینه برای هر صفحه نمایش پشتیبانی نمی کند. برای انجام این کار، به یک شناسه نمایشگر پایدار برای تداوم تنظیمات کاغذدیواری در هر نمایشگر نیاز است. Display#getDisplayId() پویا است، بنابراین هیچ تضمینی وجود ندارد که یک نمایشگر فیزیکی پس از راه اندازی مجدد همان شناسه را داشته باشد.

با این حال، Android 10 DisplayInfo.mAddress اضافه کرد که حاوی شناسه های پایدار برای نمایشگرهای فیزیکی است و می تواند برای اجرای کامل در آینده استفاده شود. متاسفانه برای پیاده سازی منطق اندروید 10 خیلی دیر شده است. راه حل پیشنهادی:

  1. از WallpaperManager API برای تنظیم تصاویر پس زمینه استفاده کنید.
  2. WallpaperManager از یک شی Context بدست می آید و هر شی Context اطلاعاتی در مورد نمایش مربوطه دارد ( Context#getDisplay()/getDisplayId() ). بنابراین، می‌توانید displayId از یک نمونه WallpaperManager بدون اضافه کردن روش‌های جدید دریافت کنید.
  3. در سمت چارچوب، از displayId به دست آمده از یک شی Context استفاده کنید و آن را به یک شناسه ثابت (مانند یک پورت نمایش فیزیکی) نگاشت کنید. از شناسه ثابت برای ماندگاری تصویر زمینه انتخابی استفاده کنید.

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

اگر نیاز به تنظیم کاغذ دیواری برای نمایشگری غیر از نمایشگر فعلی وجود دارد، سپس یک شی Context جدید برای نمایشگر هدف ایجاد کنید ( Context#createDisplayContext ) و نمونه WallpaperManager از آن نمایشگر دریافت کنید.

محدودیت های امنیتی

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

پیاده سازی

در اندروید 10، رابط های IWallpaperConnection#attachEngine() و IWallpaperService#attach() پارامتر displayId را برای ایجاد اتصالات هر نمایشگر می پذیرند. WallpaperManagerService.DisplayConnector یک موتور کاغذ دیواری و اتصال به ازای هر نمایشگر را در بر می گیرد. در WindowManager، به جای یک WallpaperController برای همه نمایشگرها، برای هر شی DisplayContent در هنگام ساخت، کنترل‌کننده‌های کاغذدیواری ایجاد می‌شوند.

برخی از پیاده سازی های عمومی متد WallpaperManager (مانند WallpaperManager#getDesiredMinimumWidth() ) برای محاسبه و ارائه اطلاعات برای نمایشگرهای مربوطه به روز شدند. WallpaperInfo#supportsMultipleDisplays() و یک ویژگی منبع مربوطه اضافه شد، به طوری که توسعه دهندگان برنامه می توانند گزارش دهند که کدام والپیپرها برای چندین صفحه آماده هستند.

اگر سرویس کاغذدیواری نشان داده شده در نمایشگر پیش‌فرض از نمایشگرهای متعدد پشتیبانی نمی‌کند، سیستم تصویر زمینه پیش‌فرض را روی نمایشگرهای ثانویه نشان می‌دهد.

شکل 3. منطق بازگشتی کاغذ دیواری برای نمایشگرهای ثانویه

،

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

تزئینات سیستم

اندروید 10 از پیکربندی نمایشگرهای ثانویه برای نمایش تزئینات خاص سیستم مانند کاغذ دیواری، نوار ناوبری و راه‌انداز پشتیبانی می‌کند. به‌طور پیش‌فرض، نمایشگر اصلی تمام تزئینات سیستم را نشان می‌دهد و نمایشگرهای ثانویه مواردی را که به صورت اختیاری فعال هستند نشان می‌دهند. پشتیبانی از یک ویرایشگر روش ورودی (IME) را می توان جدا از سایر تزئینات سیستم تنظیم کرد.

از DisplayWindowSettings#setShouldShowSystemDecorsLocked() برای اضافه کردن پشتیبانی از تزئینات سیستم در یک نمایشگر خاص یا ارائه یک مقدار پیش فرض در /data/system/display_settings.xml استفاده کنید. برای مثال، تنظیمات پنجره نمایش را ببینید.

پیاده سازی

DisplayWindowSettings#setShouldShowSystemDecorsLocked() نیز در WindowManager#setShouldShowSystemDecors() برای آزمایش نمایش داده می شود. راه‌اندازی این روش با هدف فعال کردن دکورهای سیستم، پنجره‌های دکوری را که قبلاً گم شده بودند اضافه نمی‌کند، یا اگر قبلاً وجود داشته‌اند، آن‌ها را حذف نمی‌کند. در بیشتر موارد، تغییر پشتیبانی از تزئینات سیستم تنها پس از راه‌اندازی مجدد دستگاه کاملاً تأثیر می‌گذارد.

بررسی‌های پشتیبانی از تزئینات سیستم در پایگاه کد WindowManager معمولاً از طریق DisplayContent#supportsSystemDecorations() انجام می‌شود، در حالی که بررسی‌های مربوط به سرویس‌های خارجی (مانند رابط کاربری سیستم برای بررسی اینکه آیا نوار پیمایش باید نشان داده شود) از WindowManager#shouldShowSystemDecors() استفاده می‌کند. برای درک اینکه چه چیزی توسط این تنظیم کنترل می شود، نقاط تماس این روش ها را بررسی کنید.

پنجره های دکور رابط کاربری سیستم

Android 10 پشتیبانی از پنجره تزئینی سیستم را فقط برای نوار پیمایش اضافه می کند، زیرا نوار پیمایش برای پیمایش بین فعالیت ها و برنامه ها ضروری است. به طور پیش‌فرض، نوار پیمایش هزینه‌های بازگشت و خانه را نشان می‌دهد. این فقط در صورتی گنجانده می شود که نمایشگر هدف از تزئینات سیستم پشتیبانی کند (به DisplayWindowSettings مراجعه کنید).

نوار وضعیت یک پنجره سیستم پیچیده‌تر است، زیرا شامل Notification Shade، تنظیمات سریع و Lock Screen نیز می‌شود. در اندروید 10، نوار وضعیت در نمایشگرهای ثانویه پشتیبانی نمی شود. بنابراین، اعلان ها، تنظیمات و یک صفحه کلید کامل فقط در صفحه نمایش اصلی در دسترس هستند.

پنجره سیستم نمای کلی/اخیرا در صفحه‌های ثانویه پشتیبانی نمی‌شود. در اندروید 10، AOSP فقط Recents را در نمایشگر پیش‌فرض نمایش می‌دهد و شامل فعالیت‌هایی از همه نمایشگرها است. هنگامی که از Recents راه اندازی می شود، فعالیتی که در یک نمایشگر ثانویه بود به طور پیش فرض در جلوی آن نمایشگر آورده می شود. این رویکرد دارای برخی مشکلات شناخته شده است، مانند عدم به روز رسانی فوری زمانی که برنامه ها در صفحه های دیگر ظاهر می شوند.

پیاده سازی

برای پیاده‌سازی ویژگی‌های اضافی System UI، سازندگان دستگاه باید از یک جزء سیستم UI استفاده کنند که به اضافه/حذف نمایشگرها گوش می‌دهد و محتوای مناسب را ارائه می‌کند.

یک مؤلفه رابط کاربری سیستم که از چند نمایشگر (MD) پشتیبانی می کند باید موارد زیر را مدیریت کند:

  • مقداردهی اولیه نمایشگر در هنگام راه اندازی
  • صفحه نمایش در زمان اجرا اضافه شده است
  • نمایشگر در زمان اجرا حذف شد

وقتی System UI اضافه شدن یک نمایشگر را قبل از WindowManager تشخیص می‌دهد، یک شرط مسابقه ایجاد می‌کند. هنگامی که نمایشگری به جای اشتراک در رویدادهای DisplayManager .DisplayListener اضافه می شود، می توان با اجرای یک پاسخ تماس سفارشی از WindowManager به System UI اجتناب کرد. برای اجرای مرجع، CommandQueue.Callbacks#onDisplayReady برای پشتیبانی از نوار ناوبری و WallpaperManagerInternal#onDisplayReady برای تصاویر پس زمینه ببینید.

علاوه بر این، اندروید 10 این به روز رسانی ها را ارائه می دهد:

  • کلاس NavigationBarController تمام عملکردهای مخصوص نوارهای ناوبری را کنترل می کند.
  • برای مشاهده نوار پیمایش سفارشی شده، CarStatusBar ببینید.
  • TYPE_NAVIGATION_BAR دیگر محدود به یک نمونه نیست و می‌تواند در هر نمایشگر استفاده شود.
  • IWindowManager#hasNavigationBar() به‌روزرسانی می‌شود تا پارامتر displayId را فقط برای System UI شامل شود.

پرتاب کننده

در Android 10، هر صفحه نمایشی که برای پشتیبانی از تزئینات سیستم پیکربندی شده است، به طور پیش‌فرض دارای یک پشته خانه اختصاصی برای فعالیت‌های راه‌انداز با نوع WindowConfiguration#ACTIVITY_TYPE_HOME است. هر نمایشگر از یک نمونه جداگانه از فعالیت راه‌انداز استفاده می‌کند.

شکل 1. نمونه راه‌انداز چند نمایشگر برای platform/development/samples/MultiDisplay

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

<activity>
    ...
    <intent-filter>
        <category android:name="android.intent.category.SECONDARY_HOME" />
        ...
    </intent-filter>
</activity>

فعالیت باید حالت راه اندازی داشته باشد که از چندین نمونه جلوگیری نمی کند و انتظار می رود با اندازه های مختلف صفحه سازگار شود. حالت راه اندازی نمی تواند singleInstance یا singleTask باشد.

پیاده سازی

در اندروید 10، RootActivityContainer#startHomeOnDisplay() به طور خودکار مؤلفه و هدف مورد نظر را بسته به نمایشگری که در آن صفحه اصلی راه اندازی می شود، انتخاب می کند. RootActivityContainer#resolveSecondaryHomeActivity() حاوی منطق جستجوی مؤلفه فعالیت راه‌انداز بسته به راه‌انداز فعلی انتخاب شده است و در صورت نیاز می‌تواند از پیش‌فرض سیستم استفاده کند (به ActivityTaskManagerService#getSecondaryHomeIntent() ) مراجعه کنید.

محدودیت های امنیتی

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

تصاویر پس زمینه

در اندروید 10 (و بالاتر)، تصاویر پس زمینه در نمایشگرهای ثانویه پشتیبانی می شوند:

شکل 2. تصویر زمینه زنده در نمایشگرهای داخلی (بالا) و خارجی (زیر)

توسعه دهندگان می توانند با ارائه android:supportsMultipleDisplays="true" در تعریف WallpaperInfo XML از ویژگی تصویر زمینه حمایت کنند. همچنین از توسعه دهندگان کاغذ دیواری انتظار می رود که دارایی ها را با استفاده از زمینه نمایش در WallpaperService.Engine#getDisplayContext() بارگیری کنند.

این چارچوب در هر نمایشگر یک نمونه WallpaperService.Engine ایجاد می کند، بنابراین هر موتور سطح و زمینه نمایش خود را دارد. توسعه‌دهنده باید مطمئن شود که هر موتور می‌تواند به‌طور مستقل، با نرخ فریم‌های مختلف، با رعایت VSYNC طراحی کند.

تصاویر پس زمینه را برای هر صفحه نمایش انتخاب کنید

اندروید 10 برای انتخاب تصاویر پس زمینه برای هر صفحه نمایش پشتیبانی نمی کند. برای انجام این کار، به یک شناسه نمایشگر پایدار برای تداوم تنظیمات کاغذدیواری در هر نمایشگر نیاز است. Display#getDisplayId() پویا است، بنابراین هیچ تضمینی وجود ندارد که یک نمایشگر فیزیکی پس از راه اندازی مجدد همان شناسه را داشته باشد.

با این حال، Android 10 DisplayInfo.mAddress اضافه کرد که حاوی شناسه های پایدار برای نمایشگرهای فیزیکی است و می تواند برای اجرای کامل در آینده استفاده شود. متاسفانه برای پیاده سازی منطق اندروید 10 خیلی دیر شده است. راه حل پیشنهادی:

  1. از WallpaperManager API برای تنظیم تصاویر پس زمینه استفاده کنید.
  2. WallpaperManager از یک شی Context بدست می آید و هر شی Context اطلاعاتی در مورد نمایش مربوطه دارد ( Context#getDisplay()/getDisplayId() ). بنابراین، می‌توانید displayId از یک نمونه WallpaperManager بدون اضافه کردن روش‌های جدید دریافت کنید.
  3. در سمت چارچوب، از displayId به دست آمده از یک شی Context استفاده کنید و آن را به یک شناسه ثابت (مانند یک پورت نمایش فیزیکی) نگاشت کنید. از شناسه ثابت برای ماندگاری تصویر زمینه انتخابی استفاده کنید.

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

اگر نیاز به تنظیم کاغذ دیواری برای نمایشگری غیر از نمایشگر فعلی وجود دارد، سپس یک شی Context جدید برای نمایشگر هدف ایجاد کنید ( Context#createDisplayContext ) و نمونه WallpaperManager از آن نمایشگر دریافت کنید.

محدودیت های امنیتی

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

پیاده سازی

در اندروید 10، رابط های IWallpaperConnection#attachEngine() و IWallpaperService#attach() پارامتر displayId را برای ایجاد اتصالات هر نمایشگر می پذیرند. WallpaperManagerService.DisplayConnector یک موتور کاغذ دیواری و اتصال به ازای هر نمایشگر را در بر می گیرد. در WindowManager، به جای یک WallpaperController برای همه نمایشگرها، برای هر شی DisplayContent در هنگام ساخت، کنترل‌کننده‌های کاغذ دیواری ایجاد می‌شوند.

برخی از پیاده سازی های عمومی متد WallpaperManager (مانند WallpaperManager#getDesiredMinimumWidth() ) برای محاسبه و ارائه اطلاعات برای نمایشگرهای مربوطه به روز شدند. WallpaperInfo#supportsMultipleDisplays() و یک ویژگی منبع مربوطه اضافه شد، به طوری که توسعه دهندگان برنامه می توانند گزارش دهند که کدام والپیپرها برای چندین صفحه آماده هستند.

اگر سرویس کاغذدیواری نشان داده شده در نمایشگر پیش‌فرض از نمایشگرهای متعدد پشتیبانی نمی‌کند، سیستم تصویر زمینه پیش‌فرض را روی نمایشگرهای ثانویه نشان می‌دهد.

شکل 3. منطق بازگشتی کاغذ دیواری برای نمایشگرهای ثانویه