التوافق مع نظام إصدار VNDK

في الإصدار 8.1 من نظام التشغيل Android والإصدارات الأحدث، يتضمّن نظام الإنشاء دعمًا مضمّنًا لـ VNDK. عند تفعيل ميزة دعم حِزم VNDK، يتحقّق نظام الإنشاء من التبعيات بين الوحدات، وينشئ إصدارًا خاصًا بالمورّد لوحدات المورّد، ويُثبِّت هذه الوحدات تلقائيًا في الأدلة المحدّدة.

مثال على دعم إنشاء مجموعة تطوير أصلية للمورّدين (VNDK)

في هذا المثال، يحدِّد تعريف الوحدة Android.bp مكتبة باسم libexample. تشير السمة vendor_available إلى أنّ وحدات إطار العمل ووحدات المورّدين قد تعتمد على libexample:

libexample vendor_available:true and vndk.enabled:true

تم تفعيل دعم الشكل 1..

يعتمد كل من الملف التنفيذي للإطار /system/bin/foo والملف التنفيذي الخاص بالمورّد /vendor/bin/bar على libexample ويحتويان على libexample في سمات shared_libs.

إذا كان libexample يُستخدَم من قِبل كلّ من وحدات الإطار العمل ووحدات العميل ، يتمّ إنشاء نسختَين من libexample. يتم استخدام الصيغة الأساسية (التي تحمل اسم libexample) من قِبل وحدات إطار العمل، ويتم استخدام صيغة المورّد (التي تحمل اسم libexample.vendor) من قِبل وحدات المورّد. تم تثبيت السعرَين المتغيرَين في أدلة مختلفة:

  • يتم تثبيت السعر الأساسي في /system/lib[64]/libexample.so.
  • تم تثبيت إصدار المورّد في VNDK APEX لأنّه vndk.enabled هو true.

لمزيد من التفاصيل، يُرجى الاطّلاع على تعريف الوحدة.

إعداد دعم الإصدار

لإتاحة الدعم الكامل لنظام الإصدار لجهاز ما، أضِف BOARD_VNDK_VERSION إلى BoardConfig.mk:

BOARD_VNDK_VERSION := current

يكون لهذا الإعداد تأثير عام: عند تحديده في BoardConfig.mk، يتم التحقّق من جميع الوحدات. وبسبب عدم توفُّر آلية لإدراج وحدة مسيئة في القائمة السوداء أو القائمة البيضاء، عليك إزالة جميع العناصر الاعتمادية غير الضرورية قبل إضافة BOARD_VNDK_VERSION. يمكنك اختبار وحدة وتجميعها من خلال ضبط BOARD_VNDK_VERSION فيvariab

$ BOARD_VNDK_VERSION=current m module_name.vendor

عند تفعيل BOARD_VNDK_VERSION، يتم إزالة العديد من مسارات البحث التلقائية عن العنوان العميق المشترَك. ومن بينها:

  • frameworks/av/include
  • frameworks/native/include
  • frameworks/native/opengl/include
  • hardware/libhardware/include
  • hardware/libhardware_legacy/include
  • hardware/ril/include
  • libnativehelper/include
  • libnativehelper/include_deprecated
  • system/core/include
  • system/media/audio/include

إذا كانت إحدى الوحدات تعتمد على الرؤوس من هذه الأدلة، يجب تحديد (بشكل صريح) التبعيات باستخدام header_libs و/أو static_libs و/أو shared_libs.

حزمة VNDK APEX

في الإصدار 10 من نظام Android والإصدارات الأقدم، تم تثبيت الوحدات التي تحتوي على vndk.enabled في /system/lib[64]/vndk[-sp]-${VER}. في الإصدار 11 من نظام التشغيل Android والإصدارات الأحدث، يتم تجميع مكتبات VNDK بتنسيق APEX، ويكون اسم VNDK APEX هو com.android.vndk.v${VER}. استنادًا إلى إعدادات الجهاز، يكون حِزمة VNDK APEX مسطّحة أو غير مسطّحة وتتوفّر من المسار الأساسي /apex/com.android.vndk.v${VER}.

حزمة VNDK APEX

الشكل 2: مجموعة تطوير أصلية للمورّدين (VNDK) APEX

تعريف الوحدة

لإنشاء نظام Android باستخدام BOARD_VNDK_VERSION، عليك مراجعة تعريف الوحدة في Android.mk أو Android.bp. يوضّح هذا القسم أنواعًا مختلفة من تعريفات الوحدات والعديد من سمات الوحدات ذات الصلة بمجموعة تطوير البرامج (VNDK) وعمليات التحقّق من تبعية الوحدات التي يتم تنفيذها في نظام الإنشاء.

وحدات المورّدين

وحدات المورّدين هي ملفات تنفيذية أو مكتبات مشترَكة خاصة بالمورّد يجب تثبيتها في قسم خاص بالمورّد. في ملفات Android.bp، يجب أن تضبط وحدات المورّدين سمة المورّد أو السمة الخاصة بالملكية على true. في ملفات Android.mk، يجب أن تضبط وحدات المورّدين قيمة LOCAL_VENDOR_MODULE أو LOCAL_PROPRIETARY_MODULE على true.

في حال تحديد BOARD_VNDK_VERSION، لا يسمح نظام الإنشاء بإنشاء التبعيات بين وحدات المورّدين ووحدات إطار العمل، ويُرسِل أخطاء في الحالات التالية:

  • وحدة بدون vendor:true تعتمد على وحدة تحتوي على vendor:true
  • وحدة تحتوي على vendor:true تعتمد على وحدة غير llndk_library لا تحتوي على vendor:true أو vendor_available:true

ينطبق التحقّق من التبعية على header_libs static_libs وshared_libs في Android.bp وعلى LOCAL_HEADER_LIBRARIES LOCAL_STATIC_LIBRARIES وLOCAL_SHARED_LIBRARIES في Android.mk.

LL-NDK

المكتبات المشتركة في LL-NDK هي مكتبات مشتركة تتضمّن واجهات برمجة تطبيقات ثابتة. تتشارك كلّ من وحدات الإطار العمل ووحدات المورّدين أحدث عملية تنفيذ. لكل مكتبة مشترَكة LL-NDK، تحتوي cc_library على سمة llndk تتضمّن ملف رمز:

cc_library {
    name: "libvndksupport",
    llndk: {
        symbol_file: "libvndksupport.map.txt",
    },
}

يصف ملف الرموز الرموز الظاهرة في وحدات المورّدين. مثلاً:

LIBVNDKSUPPORT {
  global:
    android_load_sphal_library; # llndk
    android_unload_sphal_library; # llndk
  local:
    *;
};

استنادًا إلى ملف الرموز، ينشئ نظام التصميم مكتبة مشتركة بديلة لوحدات المورّدين، والتي يتم ربطها بهذه المكتبات عند تفعيل BOARD_VNDK_VERSION. لا يتم تضمين رمز في المكتبة المشتركة لطلب البحث إلا في حال:

  • لم يتم تحديدها في نهاية القسم باستخدام _PRIVATE أو _PLATFORM
  • عدم احتوائها على علامة #platform-only
  • لا تحتوي على علامات #introduce* أو تتطابق العلامة مع الوجهة

الدونغ الفيتنامي (VNDK)

في ملفات Android.bp، تتيح تعريفات الوحدات cc_library cc_library_static وcc_library_shared cc_library_headers استخدام ثلاث سمات مرتبطة بمجموعة تطوير البرامج (VNDK): vendor_available وvndk.enabled vndk.support_system_process.

إذا كان vendor_available أو vndk.enabled هو true، قد يتم إنشاء خيارَين (core وvendor). يجب التعامل مع السعر الأساسي كوحدة إطار عمل، ويجب التعامل مع السعر الخاص بالمورّد كوحدة مورّد. إذا كانت بعض وحدات إطار العمل تعتمد على هذه الوحدة، سيتم إنشاء الصيغة الأساسية. إذا كانت بعض وحدات المورّدين تعتمد على هذه الوحدة، يتم إنشاء السعر المتغير الخاص بالمورّد. يفرض نظام الإنشاء عمليات التحقّق من التبعية التالية:

  • يكون الصيغة الأساسية متاحة دائمًا للإطار فقط ولا يمكن للوحدات الخاصة بالمورّدين الوصول إليها.
  • لا يمكن دائمًا الوصول إلى الصيغة الخاصة بالمورّد من خلال وحدات إطار العمل.
  • يجب أن تكون جميع التبعيات لخيار المورّد، والتي يتم تحديدها في header_libs و/أو static_libs و/أو shared_libs، إما llndk_library أو وحدة تحتوي على vendor_available أو vndk.enabled.
  • إذا كانت قيمة vendor_available هي true، يمكن لجميع وحدات المورّدين الوصول إلى خيار المورّد.
  • إذا كان vendor_available هو false، لا يمكن الوصول إلى الصيغة الخاصة بالمورّد إلا من خلال وحدات VNDK أو VNDK-SP الأخرى (أي أنّ الوحدات التي تحتوي على vendor:true لا يمكنها ربط وحدات vendor_available:false ).

يتم تحديد مسار التثبيت التلقائي لتطبيق cc_library أو cc_library_shared من خلال القواعد التالية:

  • تم تثبيت السعر الأساسي على /system/lib[64].
  • قد يختلف مسار تثبيت الإصدار المخصّص للمورّد:
    • إذا كانت قيمة السمة vndk.enabled هي false، سيتم تثبيت صيغة المورّد في /vendor/lib[64].
    • إذا كانت قيمة السمة vndk.enabled هي true، يتم تثبيت صيغة المورّد في VNDK APEX(com.android.vndk.v${VER}).

يلخِّص الجدول التالي كيفية تعامل نظام الإنشاء مع الأسعار المتغيرة حسب المورّد:

vendor_available vndk
enabled
vndk
support_same_process
أوصاف الصيغ من المورّد
true false false تكون خيارات المورِّد VND-ONLY. يتم تثبيت المكتبات المشتركة في /vendor/lib[64].
true غير صالح (خطأ في عملية الإنشاء)
true false خيارات المورِّد هي VNDK. يتم تثبيت المكتبات المشتركة في VNDK APEX.
true خيارات المورِّد هي VNDK-SP. ويتم تثبيت المكتبات المشتركة على VNDK APEX.

false

false

false

ما مِن صِيَغ مورّد. هذه الوحدة مخصّصة للاستخدام فقط مع الأجهزة الجوّالة.

true غير صالح (خطأ في عملية الإنشاء)
true false تكون خيارات المورّد هي VNDK-private. يتم تثبيت المكتبات المشتركة على VNDK APEX. ويجب ألّا يتم استخدامها مباشرةً من خلال وحدات المورّدين.
true تكون خيارات المورِّد هي VNDK-SP-private. يتم تثبيت المكتبات المشترَكة في VNDK APEX. ويجب ألّا يتم استخدامها مباشرةً من خلال وحدات المورّدين.

إضافات مجموعة تطوير البرامج الأصلية للمورّدين (VNDK)

إضافات VNDK هي مكتبات VNDK المشتركة التي تتضمّن واجهات برمجة تطبيقات إضافية. يتم تثبيت الإضافات على /vendor/lib[64]/vndk[-sp] (بدون إضافة اللاحقة للإصدار) وتتجاهل المكتبات المشتركة الأصلية لنظام التشغيل VNDK أثناء التشغيل.

تحديد إضافات VNDK

في الإصدار 9 من نظام Android والإصدارات الأحدث، يتوافق Android.bp في الأصل مع إضافات VNDK. لإنشاء إضافة VNDK، حدِّد وحدة أخرى باستخدام السمة vendor:true والسمة extends:

cc_library {
    name: "libvndk",
    vendor_available: true,
    vndk: {
        enabled: true,
    },
}

cc_library {
    name: "libvndk_ext",
    vendor: true,
    vndk: {
        enabled: true,
        extends: "libvndk",
    },
}

تحدِّد الوحدة التي تحتوي على السمات vendor:true وvndk.enabled:true و extends إضافة VNDK:

  • يجب أن تحدّد السمة extends اسم مكتبة مشتركة أساسيًا في VNDK (أو اسم المكتبة المشتركة VNDK-SP).
  • يتم تسمية ملحقات VNDK (أو ملحقات VNDK-SP) باسم الوحدات الأساسية التي تمتد منها. على سبيل المثال، القيمة الثنائية الناتجة عن libvndk_ext هي libvndk.so بدلاً من libvndk_ext.so.
  • يتم تثبيت إضافات VNDK في /vendor/lib[64]/vndk.
  • تم تثبيت إضافات VNDK-SP في /vendor/lib[64]/vndk-sp.
  • يجب أن تحتوي المكتبات المشتركة الأساسية على كل من vndk.enabled:true وvendor_available:true.

يجب أن تأتي إضافة VNDK-SP من مكتبة مشتركة VNDK-SP (يجب أن يكون vndk.support_system_process مساويًا):

cc_library {
    name: "libvndk_sp",
    vendor_available: true,
    vndk: {
        enabled: true,
        support_system_process: true,
    },
}

cc_library {
    name: "libvndk_sp_ext",
    vendor: true,
    vndk: {
        enabled: true,
        extends: "libvndk_sp",
        support_system_process: true,
    },
}

قد تعتمد إضافات VNDK (أو إضافات VNDK-SP) على مكتبات مشتركة أخرى من المورّدين:

cc_library {
    name: "libvndk",
    vendor_available: true,
    vndk: {
        enabled: true,
    },
}

cc_library {
    name: "libvndk_ext",
    vendor: true,
    vndk: {
        enabled: true,
        extends: "libvndk",
    },
    shared_libs: [
        "libvendor",
    ],
}

cc_library {
    name: "libvendor",
    vendor: true,
}

استخدام إضافات VNDK

إذا كانت وحدة المورّد تعتمد على واجهات برمجة تطبيقات إضافية تحدّدها إضافات VNDK، يجب أن تحدّد الوحدة اسم إضافة VNDK في سمة shared_libs:

// A vendor shared library example
cc_library {
    name: "libvendor",
    vendor: true,
    shared_libs: [
        "libvndk_ext",
    ],
}

// A vendor executable example
cc_binary {
    name: "vendor-example",
    vendor: true,
    shared_libs: [
        "libvndk_ext",
    ],
}

إذا كانت وحدة المورّد تعتمد على إضافات VNDK، يتم تثبيت إضافات VNDK هذه على /vendor/lib[64]/vndk[-sp] تلقائيًا. إذا لم تعُد إحدى الوحدات تعتمد على إضافة VNDK، أضِف خطوة تنظيف إلى CleanSpec.mk لإزالة المكتبة المشتركة. مثلاً:

$(call add-clean-step, rm -rf $(TARGET_OUT_VENDOR)/lib/libvndk.so)

التجميع المشروط

يوضّح هذا القسم كيفية التعامل مع الاختلافات الدقيقة (مثل إضافة ميزة أو إزالتها من أحد الصيغ) بين مكتبات VNDK المشتركة التالية:

  • السعر الأساسي (مثل /system/lib[64]/libexample.so)
  • السعر المتغير للمورّد (مثل /apex/com.android.vndk.v${VER}/lib[64]/libexample.so)
  • إضافة مجموعة تطوير أصلية للمورّدين (VNDK) (مثل /vendor/lib[64]/vndk[-sp]/libexample.so)

علامات المُجمِّع الشَرطية

يحدِّد نظام إنشاء Android __ANDROID_VNDK__ لأنواع المورّد وإضافات VNDK تلقائيًا. يمكنك حماية الرمز باستخدام أدوات التحكّم في المعالجة المسبقة في C:

void all() { }

#if !defined(__ANDROID_VNDK__)
void framework_only() { }
#endif

#if defined(__ANDROID_VNDK__)
void vndk_only() { }
#endif

بالإضافة إلى __ANDROID_VNDK__، قد يتم تحديد cflags أو cppflags مختلفَين في Android.bp. إنّ قيمة cflags أو cppflags المحدّدة في target.vendor هي خاصة بخيار المورّد.

على سبيل المثال، تحدّد السمة Android.bp التالية الترميزَين libexample وlibexample_ext:

cc_library {
    name: "libexample",
    srcs: ["src/example.c"],
    vendor_available: true,
    vndk: {
        enabled: true,
    },
    target: {
        vendor: {
            cflags: ["-DLIBEXAMPLE_ENABLE_VNDK=1"],
        },
    },
}

cc_library {
    name: "libexample_ext",
    srcs: ["src/example.c"],
    vendor: true,
    vndk: {
        enabled: true,
        extends: "libexample",
    },
    cflags: [
        "-DLIBEXAMPLE_ENABLE_VNDK=1",
        "-DLIBEXAMPLE_ENABLE_VNDK_EXT=1",
    ],
}

في ما يلي قائمة الرموز الخاصة بـ src/example.c:

void all() { }

#if !defined(LIBEXAMPLE_ENABLE_VNDK)
void framework_only() { }
#endif

#if defined(LIBEXAMPLE_ENABLE_VNDK)
void vndk() { }
#endif

#if defined(LIBEXAMPLE_ENABLE_VNDK_EXT)
void vndk_ext() { }
#endif

وفقًا لهذين الملفَّين، ينشئ نظام الإنشاء مكتبات مشترَكة باستخدام الرموز المصدَّرة التالية:

مسار التثبيت الرموز التي تم تصديرها
/system/lib[64]/libexample.so all، framework_only
/apex/com.android.vndk.v${VER}/lib[64]/libexample.so all، vndk
/vendor/lib[64]/vndk/libexample.so "all" و"vndk" و"vndk_ext"

متطلبات الرموز التي يتم تصديرها

يقارن أداة التحقّق من واجهة التطبيق الثنائية (ABI) لنظام التشغيل VNDK واجهة ABI لـ خيارات المورّد لنظام التشغيل VNDK و إضافات نظام التشغيل VNDK ببيانات واجهة ABI المرجعية ضمن prebuilts/abi-dumps/vndk.

  • يجب أن تكون الرموز التي يتم تصديرها من خلال نُسخ مورّدي VNDK (مثل /apex/com.android.vndk.v${VER}/lib[64]/libexample.so) متطابقة مع الرموز المحدّدة في عمليات تفريغ ABI (وليس المجموعات الفائقة).
  • إنّ الرموز التي يتم تصديرها باستخدام إضافات VNDK (مثل /vendor/lib[64]/vndk/libexample.so) يجب أن تكون رموزًا رئيسية للرموز المحدّدة في ملفات تفريغ ABI.

إذا لم تلتزم صيغ مورّدي حِزم VNDK أو إضافات حِزم VNDK بالمتطلبات المذكورة أعلاه، سيُرسِل مدقّق ABI لحِزم VNDK أخطاء في عملية الإنشاء ويوقف عملية الإنشاء.

استبعاد الملفات المصدر أو المكتبات المشتركة من الأسعار المتغيرة الخاصة بالمورّد

لاستبعاد ملفات المصدر من صيغة المورّد، أضِفها إلى السمة exclude_srcs. وبالمثل، لضمان عدم ربط المكتبات المشترَكة بنوع المورّد، أضِف هذه المكتبات إلى الموقع الإلكتروني exclude_shared_libs. مثلاً:

cc_library {
    name: "libexample_cond_exclude",
    srcs: ["fwk.c", "both.c"],
    shared_libs: ["libfwk_only", "libboth"],
    vendor_available: true,
    target: {
        vendor: {
            exclude_srcs: ["fwk.c"],
            exclude_shared_libs: ["libfwk_only"],
        },
    },
}

في هذا المثال، يتضمّن الصيغة الأساسية من libexample_cond_exclude الرمز البرمجي من fwk.c وboth.c ويعتمد على المكتبتَين المشترَكتَين libfwk_only وlibboth. لا يتضمّن نوع المورّد من libexample_cond_exclude سوى الرمز من both.c لأنّ fwk.c يتم استبعاده من الموقع exclude_srcs. وبالمثل، يعتمد التطبيق على المكتبة المشتركة libboth فقط لأنّ libfwk_only يتم استبعاده من خلال الخاصية exclude_shared_libs.

تصدير العناوين من إضافات VNDK

قد تضيف إضافة VNDK صفوفًا جديدة أو دوال جديدة إلى مكتبة VNDK المشتركة. يُنصح بالاحتفاظ بهذه البيانات في رؤوس مستقلة وتجنُّب تغيير الرؤوس الحالية.

على سبيل المثال، يتم إنشاء ملف عنوان جديد include-ext/example/ext/feature_name.h لإمتداد VNDK libexample_ext:

  • Android.bp
  • include-ext/example/ext/feature_name.h
  • include/example/example.h
  • src/example.c
  • src/ext/feature_name.c

في Android.bp التالي، تُصدِّر libexample include فقط، في حين تُصدِّر libexample_ext كلاً من include وinclude-ext. يضمن ذلك عدم تضمين feature_name.h بشكل غير صحيح من قِبل مستخدمي libexample:

cc_library {
    name: "libexample",
    srcs: ["src/example.c"],
    export_include_dirs: ["include"],
    vendor_available: true,
    vndk: {
        enabled: true,
    },
}

cc_library {
    name: "libexample_ext",
    srcs: [
        "src/example.c",
        "src/ext/feature_name.c",
    ],
    export_include_dirs: [
        "include",
        "include-ext",
    ],
    vendor: true,
    vndk: {
        enabled: true,
        extends: "libexample",
    },
}

إذا لم يكن من الممكن فصل الإضافات إلى ملفات رؤوس مستقلة، يمكن استخدام البديل وهو إضافة #ifdef أدوات حماية. واحرِص على أن يضيف جميع مستخدمي إضافة VNDK علامات التعريف. ويمكنك تحديد cc_defaults لإضافة علامات تعريف إلى cflags وربط المكتبات المشتركة باستخدام shared_libs.

على سبيل المثال، لإضافة دالة عضو جديدة Example2::get_b() إلى إضافة VNDK libexample2_ext، عليك تعديلملف الرأس الحالي وإضافة #ifdef حارس:

#ifndef LIBEXAMPLE2_EXAMPLE_H_
#define LIBEXAMPLE2_EXAMPLE_H_

class Example2 {
 public:
  Example2();

  void get_a();

#ifdef LIBEXAMPLE2_ENABLE_VNDK_EXT
  void get_b();
#endif

 private:
  void *impl_;
};

#endif  // LIBEXAMPLE2_EXAMPLE_H_

تم تحديد cc_defaults باسم libexample2_ext_defaults لمستخدمي libexample2_ext:

cc_library {
    name: "libexample2",
    srcs: ["src/example2.cpp"],
    export_include_dirs: ["include"],
    vendor_available: true,
    vndk: {
        enabled: true,
    },
}

cc_library {
    name: "libexample2_ext",
    srcs: ["src/example2.cpp"],
    export_include_dirs: ["include"],
    vendor: true,
    vndk: {
        enabled: true,
        extends: "libexample2",
    },
    cflags: [
        "-DLIBEXAMPLE2_ENABLE_VNDK_EXT=1",
    ],
}

cc_defaults {
    name: "libexample2_ext_defaults",
    shared_libs: [
        "libexample2_ext",
    ],
    cflags: [
        "-DLIBEXAMPLE2_ENABLE_VNDK_EXT=1",
    ],
}

يمكن لمستخدمي libexample2_ext تضمين libexample2_ext_defaults في موقعهم الإلكتروني defaults:

cc_binary {
    name: "example2_user_executable",
    defaults: ["libexample2_ext_defaults"],
    vendor: true,
}

حِزم المنتجات

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

في حال تفعيل BOARD_VNDK_VERSION، تتلقّى الوحدات التي تحتوي على vendor_available أو vndk.enabled معاملة خاصة. إذا كانت وحدة إطار عمل تعتمد على وحدة تحتوي على vendor_available أو vndk.enabled، يتم تضمين الصيغة الأساسية في مجموعة التثبيت الانتقالي. إذا كانت وحدة المورّد تعتمد على وحدة تحتوي على vendor_available، يتم تضمين الصيغة الخاصة بالمورّد في مجموعة التثبيت التحويلي. في المقابل، يتم تثبيت صيغ المورّدين من الوحدات التي تتضمّن vndk.enabled سواء تم استخدامها من خلال وحدات المورّدين أم لا.

عندما تكون التبعيات غير مرئية لنظام الإنشاء (مثل المكتبات المشترَكة التي يمكن فتحها باستخدام dlopen() في وقت التشغيل)، يجب تحديد أسماء الوحدات في PRODUCT_PACKAGES لتثبيت هذه الوحدات بشكل صريح.

إذا كانت الوحدة تحتوي على vendor_available أو vndk.enabled، يشير اسم الوحدة إلى الصيغة الأساسية لها. لتحديد خيار المورّد بشكل صريح في PRODUCT_PACKAGES، أضِف اللاحقة .vendor إلى اسم الوحدة. مثلاً:

cc_library {
    name: "libexample",
    srcs: ["example.c"],
    vendor_available: true,
}

في هذا المثال، يشير الرمز libexample إلى /system/lib[64]/libexample.so ويشير الرمز libexample.vendor إلى /vendor/lib[64]/libexample.so. لتثبيت /vendor/lib[64]/libexample.so، أضِف libexample.vendor إلى PRODUCT_PACKAGES:

PRODUCT_PACKAGES += libexample.vendor