إضافات WindowManager

تتيح مكتبة Jetpack WindowManager لمطوّري التطبيقات إمكانية توفير الدعم لأشكال الأجهزة الجديدة وبيئات النوافذ المتعددة.

‫WindowManager Extensions (الإضافات) هي وحدة نظام أساسي اختيارية في Android تتيح مجموعة متنوعة من ميزات Jetpack WindowManager. يتم تنفيذ الوحدة في "مشروع Android المفتوح المصدر" ‏(AOSP) في frameworks/base/libs/WindowManager/Jetpack ويتم شحنها على الأجهزة التي تتوافق مع ميزات WindowManager.

توزيع وحدة الإضافات

يتم تجميع الإضافات في مكتبة .jar ووضعها في قسم system_ext على الجهاز إذا تم تفعيل الإضافات في ملف makefile الخاص بالجهاز.

لتفعيل الإضافات على جهاز، أضِف ما يلي إلى ملف makefile الخاص بالجهاز:

$(call inherit-product, $(SRC_TARGET_DIR)/product/window_extensions.mk)

يؤدي ذلك إلى تفعيل حِزم androidx.window.extensions وandroidx.window.sidecar على الجهاز وضبط السمة persist.wm.extensions.enabled. وتؤدي إضافة هذه الحِزم إلى ملف makefile إلى وضع التصريحات في etc/permissions/، ما يتيح استخدامها في عمليات التطبيق. يتم عادةً تحميل الوحدات وتنفيذها كجزء من عملية التطبيق في وقت التشغيل عند استخدامها من خلال مكتبة Jetpack WindowManager، ما يجعل طريقة عملها مشابهة لرمز إطار العمل من جهة العميل، كما هو موضّح في الشكل التالي:

الشكل 1. يتم تحميل إضافات WindowManager في عملية التطبيق بشكل مشابه لرمز النظام الأساسي.

الوحدة androidx.window.extensions هي وحدة الإضافات الحالية التي يتم تطويرها بشكل نشط. الوحدة androidx.window.sidecar هي وحدة قديمة مضمّنة لتحقيق التوافق مع أقدم إصدارات Jetpack WindowManager، ولكن لم يعُد يتم صيانتها بشكل نشط.

يوضّح الشكل التالي منطق تحديد استخدام androidx.window.extensions أو androidx.window.sidecar.

الشكل 2. شجرة القرارات للوصول إلى androidx.window.extensions أو androidx.window.sidecar

وحدات الإضافات

توفّر الإضافات ميزات العرض في نوافذ للأجهزة القابلة للطي ذات الشاشات الكبيرة والأجهزة التي تتيح العرض في نوافذ على شاشات خارجية. تشمل مجالات الميزة ما يلي:

يمكن أن توفّر عمليات تنفيذ الإضافات من قِبل المصنّعين الأصليين للأجهزة مكوّنات فارغة أو مكوّنات تتضمّن عمليات تنفيذ تلقائية أو صورية للطُرق في واجهة WindowExtensions إذا كان جهاز الجهاز لا يتوافق مع الميزات المقابلة، ما لم يتم طلب الميزة تحديدًا في مستند تعريف التوافق (CDD).

الإضافات وواجهات برمجة التطبيقات في Jetpack

يوفّر وحدة WindowManager Extensions مساحة خاصة لواجهة برمجة التطبيقات بالإضافة إلى واجهات برمجة التطبيقات العامة للنظام الأساسي. يتم تطوير وحدة Extensions علنًا في مكتبة Jetpack androidx.window.extensions غير المخصّصة للمطوّرين، ليتمكّن Jetpack WindowManager (androidx.window) من الربط بها في وقت الترجمة. عادةً ما يوفّر سطح Extensions API واجهات برمجة تطبيقات ذات مستوى أدنى.

تهدف واجهات برمجة التطبيقات التي توفّرها الإضافات إلى أن تستخدمها مكتبة Jetpack WindowManager فقط. لا يُفترض أن يستدعي مطوّرو التطبيقات واجهات برمجة التطبيقات للإضافات مباشرةً. يجب عدم إضافة مكتبة Extensions كعنصر تابع لتطبيق في ملف الإصدار Gradle لضمان عملها بشكل صحيح. تجنَّب تجميع مكتبة Extensions مسبقًا في تطبيق بشكل مباشر، وبدلاً من ذلك، اعتمد على التحميل في وقت التشغيل لتجنُّب تحميل مزيج من فئات Extensions المجمّعة مسبقًا والموفّرة في وقت التشغيل.

من المفترض إضافة Jetpack WindowManager (androidx.window) كعنصر تابع للتطبيق، وهو يوفّر واجهات برمجة التطبيقات العامة المتاحة للمطوّرين، بما في ذلك واجهات برمجة التطبيقات الخاصة بميزات WindowManager Extensions. تحمّل مكتبة WindowManager تلقائيًا حِزم Extensions في عملية التطبيق، وتغلّف واجهات برمجة التطبيقات الخاصة بحِزم Extensions ذات المستوى الأدنى في تجريدات ذات مستوى أعلى وواجهات أكثر تركيزًا. تتّبع واجهات برمجة التطبيقات WindowManager Jetpack معايير تطوير تطبيقات Android الحديثة، وهي مصمَّمة لتوفير إمكانية تشغيل تفاعلي مريحة من خلال التكامل بشكل جيد مع قواعد الرموز البرمجية التي تستخدم مكتبات AndroidX الأخرى.

إصدارات الإضافات وتحديثاتها

يمكن تحديث وحدة "الإضافات" مع تحديثات منصة Android السنوية أو الربع سنوية. تتيح التحديثات الفصلية زيادة مستوى واجهة برمجة التطبيقات للإضافات بين تحديثات واجهة برمجة التطبيقات لمنصة Android، ما يتيح تكرارًا أسرع ويوفر لمصنّعي المعدات الأصلية فرصة لإضافة إمكانية الوصول الرسمية إلى واجهة برمجة التطبيقات للميزات الجديدة بالقرب من عمليات إطلاق الأجهزة.

يسرد الجدول التالي إصدارات واجهة برمجة التطبيقات androidx.window.extensions لإصدارات Android المختلفة.

إصدار نظام Android الأساسي مستوى واجهة برمجة التطبيقات WindowManager Extensions إصدار واجهة برمجة التطبيقات androidx.window.extensions
Android 15 6 ‫1.5.0 (ستتوفّر قريبًا)
‫Android 14 QPR3 5 ‫1.4.0 (ستتوفّر قريبًا)
‫Android 14 QPR1 4 1.3.0
Android 14 3 ‫1.2.0
‫Android 13 QPR3 2 1.1.0
Android 13 1 1.0.0
‫Android 12L 1 1.0.0

يتم رفع مستوى واجهة برمجة التطبيقات للإضافات (العمود الأوسط) في كل مرة تتم فيها إضافة إلى مساحة واجهة برمجة التطبيقات الثابتة الحالية (العمود الأيسر).

التوافق مع الإصدارات السابقة والإصدارات الأحدث

تتولّى مكتبة Jetpack WindowManager التعامل مع تعقيدات التوافق مع الإصدارات القديمة والتطوير السريع لواجهة برمجة التطبيقات والتحديثات المتكررة لمستوى واجهة برمجة التطبيقات. عند تنفيذ رمز المكتبة في عملية التطبيق، تتحقّق المكتبة من مستوى واجهة برمجة التطبيقات Extensions API المُعلن عنه وتوفّر إمكانية الوصول إلى الميزات وفقًا للمستوى المُعلن عنه.

لحماية التطبيق من التعطُّل أثناء وقت التشغيل، يجري WindowManager أيضًا عملية فحص انعكاس Java أثناء وقت التشغيل لواجهات برمجة التطبيقات المتاحة للإضافات وفقًا لمستوى واجهة برمجة التطبيقات للإضافات المحدّد. في حال عدم التطابق، يمكن لـ WindowManager إيقاف استخدام الإضافات (جزئيًا أو كليًا) وإبلاغ التطبيق بأنّ الميزات ذات الصلة غير متاحة.

يتم تنفيذ إضافات WindowManager كوحدة system_ext تستخدم واجهات برمجة تطبيقات خاصة بالنظام الأساسي للوصول إلى الوظائف الأساسية في WindowManager، DeviceStateManager، وخدمات النظام الأخرى في تنفيذ ميزات الإضافات.

قد لا يتم الحفاظ على التوافق مع الإصدارات التجريبية من حِزم SDK قبل الإصدارات الفصلية أو السنوية المقابلة لمنصة Android التي يتم فيها وضع اللمسات النهائية على الإصدارات. يمكن العثور على السجلّ الكامل لواجهات برمجة التطبيقات الخاصة بالإضافات في ملفات window:extensions:extensions النصية لواجهة برمجة التطبيقات في فرع الإصدار.

يجب أن تواصل الإصدارات الأحدث من Extensions العمل مع الإصدارات الأقدم من WindowManager التي تم تجميعها في التطبيقات للحفاظ على التوافق مع الإصدارات الأحدث. ولضمان ذلك، يضيف أي إصدار جديد من Extensions API واجهات برمجة تطبيقات جديدة فقط ولا يزيل الإصدارات القديمة. نتيجةً لذلك، يمكن للتطبيقات التي تستخدم إصدارات قديمة من WindowManager مواصلة استخدام واجهات برمجة التطبيقات القديمة للإضافات التي تم تجميع التطبيقات باستخدامها.

يضمن اختبار التوافق مع نظام التشغيل Android (CTS) أنّه بالنسبة إلى أي إصدار معلن من واجهات برمجة التطبيقات Extensions API على الجهاز، تتوفّر جميع واجهات برمجة التطبيقات لهذا الإصدار والإصدارات السابقة وتعمل بشكل سليم.

الأداء

يتم تخزين وحدة "الإضافات" مؤقتًا في أدوات تحميل فئات النظام غير التابعة لـ bootclasspath تلقائيًا بدءًا من Android 14 (المستوى 34 من واجهة برمجة التطبيقات)، لذلك لن يكون هناك أي تأثير في الأداء بسبب تحميل الوحدة إلى الذاكرة عند بدء تشغيل التطبيق. قد يكون لاستخدام ميزات الوحدات الفردية تأثير طفيف على خصائص الأداء للتطبيقات عند إجراء طلبات إضافية للاتصال بين العمليات (IPC) بين العميل والخادم.

الوحدات

تضمين الأنشطة

يتيح مكوّن تضمين الأنشطة للتطبيقات تحسين واجهة المستخدم الخاصة بها للأجهزة ذات الشاشات الكبيرة وشاشات العرض الخارجية. تتيح ميزة "تضمين الأنشطة" عرض نشاطَين جنبًا إلى جنب في تصميم متعدد اللوحات، ما يسهّل تطوير تطبيقات متوافقة مع الأجهزة المختلفة للتطبيقات القديمة.

يجب أن يتوفّر مكوّن تضمين النشاط على جميع الأجهزة التي تتضمّن شاشة مدمجة بحجم sw600dp أو أكبر. يجب أيضًا تفعيل ميزة "تضمين النشاط" على الأجهزة التي تتيح توصيل شاشات خارجية، لأنّه قد يتم عرض التطبيق بحجم أكبر عند توصيل شاشات خارجية أثناء وقت التشغيل.

إعداد الجهاز

ليس من الضروري إجراء أي إعدادات خاصة بالجهاز، باستثناء تفعيل وحدة "الإضافات" كما هو موضّح في قسم توزيع وحدة "الإضافات". ننصحك بتفعيل الإضافات على جميع الأجهزة التي تتوافق مع وضع النوافذ المتعددة. من المرجّح أن تتطلّب إصدارات Android المستقبلية استخدام الإضافات في إعدادات الأجهزة الشائعة المحمولة والأجهزة ذات الشاشات الكبيرة.

معلومات عن تخطيط النوافذ

يحدّد مكوّن معلومات تخطيط النافذة موضع المفصلة وحالتها على جهاز قابل للطي عندما تعبر المفصلة نافذة أحد التطبيقات. تتيح معلومات تخطيط النافذة للتطبيقات الاستجابة وعرض تخطيطات محسّنة في وضع "التثبيت على سطح مستوٍ" على الأجهزة القابلة للطي. اطّلِع على جعل تطبيقك متوافقًا مع الأجهزة القابلة للطي لمعرفة تفاصيل الاستخدام.

يجب أن توفّر أجهزة Android القابلة للطي التي تتضمّن مفصّلة تربط بين مناطق لوحة العرض المنفصلة أو المتواصلة معلومات عن المفصّلة للتطبيقات من خلال WindowLayoutComponent.

يجب الإبلاغ عن موضع المفصل وحدوده بالنسبة إلى نافذة التطبيق المحدّدة بواسطة Context تم تمريرها إلى واجهة برمجة التطبيقات. إذا لم تتقاطع حدود نافذة التطبيق مع حدود المفصلة، يجب عدم الإبلاغ عن DisplayFeature المفصلة. ويُسمح أيضًا بعدم الإبلاغ عن ميزات العرض عندما يتعذّر الإبلاغ عن موضعها بشكل موثوق، مثلاً عندما يتمكّن المستخدم من نقل نافذة التطبيق بحرية في وضع النوافذ المتعدّدة أو وضع التوافق مع عرض الصورة داخل إطار.

بالنسبة إلى الميزات القابلة للطي، يجب إعداد تقارير عن تعديلات الحالة عند تغيير موضع المفصلة بين الحالات الثابتة. في حالة العرض المسطّح التلقائية، يجب أن تعرض واجهة برمجة التطبيقات القيمة FoldingFeature.State.FLAT. إذا كان يمكن ترك معدّات الجهاز في وضع نصف مطوي بشكل ثابت، يجب أن تعرض واجهة برمجة التطبيقات القيمة FoldingFeature.State.HALF_OPENED. لا تتوفّر حالة مغلقة في واجهة برمجة التطبيقات، لأنّه في هذه الحالة، لن تكون نافذة التطبيق مرئية أو لن تتجاوز حدود المفصلة.

إعداد الجهاز

لدعم تنفيذ ميزة الطي، على الشركات المصنّعة للمعدات الأصلية إجراء ما يلي:

  • اضبط حالات الجهاز في device_state_configuration.xml ليتم استخدامها من قِبل DeviceStateManagerService. يمكنك الاطّلاع على DeviceStateProviderImpl.java للحصول على مرجع.

    إذا لم تكن عمليات التنفيذ التلقائية للدالتَين DeviceStateProvider أو DeviceStatePolicy مناسبة للجهاز، يمكن استخدام عملية تنفيذ مخصّصة.

  • فعِّل وحدة "الإضافات" كما هو موضّح في قسم توزيع وحدة "الإضافات".

  • حدِّد موقع ميزات العرض في com.android.internal.R.string.config_display_featuresstring resourcecom.android.internal.R.string.config_display_features (عادةً في frameworks/base/core/res/res/values/config.xml في تراكب الجهاز).

    التنسيق المتوقّع للسلسلة هو:

    <type>-[<left>,<top>,<right>,<bottom>]

    يمكن أن تكون قيمة type إما fold أو hinge. قيم left وtop وright وbottom هي إحداثيات بكسل عددية صحيحة في مساحة إحداثيات العرض باتجاه العرض الطبيعي. يمكن أن تحتوي سلسلة الإعداد على ميزات عرض متعددة مفصولة بفواصل منقوطة.

    مثلاً:

    <!-- Jetpack WindowManager display features -->
    <string name="config_display_features" translatable="false">fold-[1000,0,1000,2000]</string>
    
  • حدِّد عملية الربط بين معرّفات حالة الجهاز الداخلية المستخدَمة في DeviceStateManager وثوابت الحالة العلنية التي يتم إرسالها إلى المطوّرين في com.android.internal.R.array.config_device_state_postures.

    التنسيق المتوقّع لكل إدخال هو:

    <device_specific_state_identifier>:<Jetpack WindowManager state identifier>

    في ما يلي معرّفات الولايات المتوافقة:

    • COMMON_STATE_NO_FOLDING_FEATURES = 1: لا تتضمّن الحالة أي ميزات قابلة للطي يمكن الإبلاغ عنها. على سبيل المثال، يمكن أن تكون الحالة المغلقة للجهاز العادي القابل للطي للداخل مع وجود الشاشة الرئيسية على الجانب الداخلي.
    • COMMON_STATE_HALF_OPENED = 2: ميزة الطي مفتوحة جزئيًا.
    • COMMON_STATE_FLAT = 3: ميزة الطي مسطّحة. على سبيل المثال، يمكن أن تكون الحالة المفتوحة لجهاز الطي الداخلي التقليدي مع الشاشة الرئيسية على الجانب الداخلي.
    • COMMON_STATE_USE_BASE_STATE = 1000: في نظام التشغيل Android 14، هي قيمة يمكن استخدامها للحالات المحاكية التي يتم فيها استنتاج حالة المفصلة باستخدام الحالة الأساسية، كما هو محدّد في CommonFoldingFeature.java

    يمكنك الاطّلاع على DeviceStateManager.DeviceStateCallback#onBaseStateChanged(int) لمزيد من المعلومات.

    مثلاً:

    <!-- Map of System DeviceState supplied by DeviceStateManager to WindowManager posture.-->
    <string-array name="config_device_state_postures" translatable="false">
      <item>0:1</item>    <!-- CLOSED       : COMMON_STATE_NO_FOLDING_FEATURES -->
      <item>1:2</item>    <!-- HALF_OPENED  : COMMON_STATE_HALF_OPENED -->
      <item>2:3</item>    <!-- OPENED       : COMMON_STATE_FLAT -->
      <item>3:1</item>    <!-- REAR_DISPLAY : COMMON_STATE_NO_FOLDING_FEATURES -->
      <item>4:1000</item> <!-- CONCURRENT   : COMMON_STATE_USE_BASE_STATE -->
    </string-array>
    

مساحة النافذة

يوفر مكوّن مساحة النافذة مجموعة من الميزات التي تتيح للتطبيقات الوصول إلى شاشات عرض ومساحات عرض إضافية على بعض الأجهزة القابلة للطي والأجهزة التي تتضمّن شاشات عرض متعدّدة.

يتيح وضع الشاشة الخلفية لأحد التطبيقات عرض واجهة مستخدم معاينة الكاميرا على الشاشة الخارجية لجهاز قابل للطي للسماح باستخدام كاميرا الجهاز الرئيسية لالتقاط صور سيلفي وتسجيل فيديوهات. يجب أن تتيح الأجهزة التي تتضمّن شاشة متوافقة مع Android (على النحو المحدّد في مستند تعريف التوافق مع Android من حيث السمات، مثل الحجم والكثافة وأدوات التنقّل المتاحة) وشاشة غطاء تتوافق مع كاميرات الجهاز الخلفية إمكانية الوصول إلى وضع الشاشة الخلفية.

في نظام التشغيل Android 14، يتيح وضع الشاشة المزدوجة للتطبيقات التي تعمل على الشاشة الداخلية لجهاز قابل للطي عرض محتوى إضافي على الشاشة الخارجية المواجهة للمستخدمين الآخرين، مثلاً، يمكن أن تعرض الشاشة الخارجية معاينة الكاميرا للشخص الذي يتم تصويره أو تسجيله.

إعداد الجهاز

لدعم تنفيذ ميزة الطي، على الشركات المصنّعة للمعدات الأصلية إجراء ما يلي:

  • اضبط حالات الجهاز في device_state_configuration.xml ليتم استخدامها من قِبل DeviceStateManagerService. يمكنك الاطّلاع على DeviceStateProviderImpl.java لمزيد من المعلومات.

    إذا لم يكن التنفيذ التلقائي للوظيفتَين DeviceStateProvider أو DeviceStatePolicy مناسبًا للجهاز، يمكن استخدام تنفيذ مخصّص.

  • بالنسبة إلى الأجهزة القابلة للطي التي تتيح وضع الفتح أو الوضع المسطّح، حدِّد معرّفات الحالة المناسبة في com.android.internal.R.array.config_openDeviceStates.

  • بالنسبة إلى الأجهزة القابلة للطي من الداخل التي تتيح استخدام حالات الطي، أدرِج معرّفات الحالة المناسبة في com.android.internal.R.array.config_foldedDeviceStates.

  • بالنسبة إلى الأجهزة القابلة للطي إلى الداخل التي تتيح الطي بمقدار النصف (المفصلة مفتوحة بمقدار النصف مثل الكمبيوتر المحمول)، أدرِج الحالات المقابلة في com.android.internal.R.array.config_halfFoldedDeviceStates.

  • بالنسبة إلى الأجهزة التي تتوافق مع وضع الشاشة الخلفية:

    • أدرِج الولايات المعنية في com.android.internal.R.array.config_rearDisplayDeviceStates مقابل DeviceStateManager.
    • حدِّد عنوان العرض الفعلي للشاشة الخلفية في com.android.internal.R.string.config_rearDisplayPhysicalAddress.
    • حدِّد معرّف الحالة في com.android.internal.R.integer.config_deviceStateRearDisplay الذي ستستخدمه الإضافات.
    • أضِف معرّف الحالة في com.android.internal.R.array.config_deviceStatesAvailableForAppRequests لإتاحته للتطبيقات.
  • على أجهزة Android 14 التي تتوافق مع وضع العرض المزدوج (المتزامن):

    • اضبط قيمة com.android.internal.R.bool.config_supportsConcurrentInternalDisplays على true.
    • حدِّد عنوان العرض الفعلي للشاشة الخلفية في com.android.internal.R.config_deviceStateConcurrentRearDisplay.
    • حدِّد معرّف الحالة في com.android.internal.R.integer.config_deviceStateConcurrentRearDisplay الذي ستستخدمه الإضافات إذا كان من المفترض أن يكون المعرّف متاحًا للتطبيقات.
    • أضِف معرّف الحالة في com.android.internal.R.array.config_deviceStatesAvailableForAppRequests لإتاحته للتطبيقات.

إثبات الملكية

على الشركات المصنّعة للأجهزة الأصلية التحقّق من عمليات التنفيذ للتأكّد من السلوك المتوقّع في السيناريوهات الشائعة. تتوفّر اختبارات CTS والاختبارات التي تستخدم Jetpack WindowManager لمصنّعي المعدات الأصلية لاختبار عمليات التنفيذ.

اختبارات مجموعة أدوات اختبار التوافق (CTS)

لتشغيل اختبارات CTS، يُرجى الاطّلاع على تشغيل اختبارات CTS. تندرج اختبارات CTS ذات الصلة بمكتبة Jetpack WindowManager ضمن cts/tests/framework/base/windowmanager/jetpack/. اسم وحدة الاختبار هو CtsWindowManagerJetpackTestCases.

اختبارات WindowManager

لتنزيل اختبارات Jetpack WindowManager، اتّبِع تعليمات Android Jetpack. تتوفّر الاختبارات في مكتبة النوافذ ضمن الوحدة window:window: window/window/src/androidTest/.

لتشغيل اختبارات الجهاز لوحدة window:window من سطر الأوامر، اتّبِع الخطوات التالية:

  1. وصِّل جهازًا تم تفعيل خيارات المطوّرين وتصحيح الأخطاء عبر USB عليه.
  2. السماح لجهاز الكمبيوتر بتصحيح أخطاء الجهاز
  3. افتح نافذة shell في الدليل الجذر لمستودع androidx.
  4. غيِّر الدليل إلى framework/support.
  5. نفِّذ الأمر التالي: ./gradlew window:window:connectedAndroidTest.
  6. حلِّل النتائج.

لتشغيل الاختبارات من "استوديو Android"، اتّبِع الخطوات التالية:

  1. افتح "استوديو Android".
  2. وصِّل جهازًا تم تفعيل خيارات المطوّرين وتصحيح الأخطاء عبر USB عليه.
  3. السماح لجهاز الكمبيوتر بتصحيح أخطاء الجهاز
  4. انتقِل إلى اختبار ضمن مكتبة النوافذ في وحدة النوافذ.
  5. افتح صفًا تجريبيًا وشغِّله باستخدام الأسهم الخضراء على يسار المحرّر.

بدلاً من ذلك، يمكنك إنشاء إعداد في Android Studio لتنفيذ طريقة اختبار أو فئة اختبار أو جميع الاختبارات في وحدة.

يمكن تحليل النتائج يدويًا من خلال الاطّلاع على ناتج الصدفة. يتم تخطّي بعض الاختبارات إذا لم يستوفِ الجهاز بعض الافتراضات. يتم حفظ النتائج في موقع جغرافي عادي، ويمكن للمحللين كتابة نص برمجي لأتمتة تحليل النتائج.