إضافات WindowManager

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

‫WindowManager Extensions (الإضافات) هي وحدة نظام أساسي لنظام التشغيل Android تحتاج إلى تفعيل، وهي تسمح بمجموعة متنوعة من ميزات Jetpack WindowManager. يتم تنفيذ الوحدة في 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، ولكن لم تعُد وحدة Sidecar قيد الصيانة.

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

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

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

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

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

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

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

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

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

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

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

يسرد الجدول التالي إصدارات androidx.window.extensions API لإصدارات 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

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

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

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

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

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

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

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

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

الأداء

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

الوحدات

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

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

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

إعداد الجهاز

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

معلومات عن تنسيق النافذة

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

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

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

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

إعداد الجهاز

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

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

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

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

  • حدِّد موضع ميزات العرض في موارد السلسلة com.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: لا تتضمّن الولاية ميزات قابلة للطي للإبلاغ عنها. على سبيل المثال، يمكن أن تكون الحالة المغلقة لجهاز folded typical الذي يتم فتحه على شكل لوحة مع الشاشة الرئيسية على الجانب الداخلي.
    • COMMON_STATE_HALF_OPENED = 2: ميزة الطي مفتوحة جزئيًا.
    • COMMON_STATE_FLAT = 3: ميزة الطي مسطّحة. على سبيل المثال، يمكن أن يمثّل الحالة المفتوحة للجهاز التقليدي القابل للطي مع الشاشة الرئيسية على الجانب الداخلي.
    • COMMON_STATE_USE_BASE_STATE = 1000: في الإصدار 14 من نظام التشغيل Android، قيمة يمكن استخدامها لحالات الأداء المُحاكي التي يتم فيها اشتقاق حالة المفصل باستخدام الحالة الأساسية، كما هو محدّد في 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 (على النحو المحدّد في مستند CDD الخاص بنظام التشغيل 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. افتح وحدة تخزين مؤقتة في الدليل الجذر لمستودع androidx.
  4. غيِّر الدليل إلى framework/support.
  5. شغِّل الأمر التالي: ./gradlew window:window:connectedAndroidTest.
  6. تحليل النتائج

لإجراء الاختبارات من Android Studio، اتّبِع الخطوات التالية:

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

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

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