Hỗ trợ hệ thống xây dựng VNDK

Ở Android 8.1 trở lên, hệ thống build đã tích hợp hỗ trợ VNĐK. Khi bật hỗ trợ VNĐK, hệ thống xây dựng sẽ kiểm tra sự phụ thuộc giữa các mô-đun, xây dựng một biến thể dành riêng cho nhà cung cấp cho các mô-đun của nhà cung cấp và tự động cài đặt các mô-đun đó vào các thư mục được chỉ định.

Ví dụ hỗ trợ xây dựng VNĐK

Trong ví dụ này, định nghĩa mô-đun Android.bp xác định thư viện có tên libexample . Thuộc tính vendor_available cho biết các mô-đun khung và mô-đun nhà cung cấp có thể phụ thuộc vào libexample :

libexample nhà cung cấp_available:true và vndk.enabled:true

Hình 1. Hỗ trợ VNĐK được kích hoạt

Cả khung thực thi /system/bin/foo/vendor/bin/bar thực thi của nhà cung cấp đều phụ thuộc vào libexample và có libexample trong thuộc tính shared_libs của chúng.

Nếu libexample được cả mô-đun khung và mô-đun nhà cung cấp sử dụng thì hai biến thể của libexample sẽ được tạo. Biến thể cốt lõi (được đặt tên theo libexample ) được sử dụng bởi các mô-đun khung và biến thể nhà cung cấp (được đặt tên theo libexample.vendor ) được sử dụng bởi các mô-đun nhà cung cấp. Hai biến thể được cài đặt vào các thư mục khác nhau:

  • Biến thể cốt lõi được cài đặt vào /system/lib[64]/libexample.so .
  • Biến thể của nhà cung cấp được cài đặt vào VNDK APEX vì vndk.enabledtrue .

Để biết thêm chi tiết, xem Định nghĩa mô-đun .

Định cấu hình hỗ trợ xây dựng

Để kích hoạt hỗ trợ hệ thống xây dựng đầy đủ cho một thiết bị sản phẩm, hãy thêm BOARD_VNDK_VERSION vào BoardConfig.mk :

BOARD_VNDK_VERSION := current

Cài đặt này có hiệu lực toàn cầu : Khi được xác định trong BoardConfig.mk , tất cả các mô-đun đều được chọn. Vì không có cơ chế đưa vào danh sách đen hoặc danh sách trắng một mô-đun vi phạm, bạn nên xóa tất cả các phần phụ thuộc không cần thiết trước khi thêm BOARD_VNDK_VERSION . Bạn có thể kiểm tra và biên dịch một mô-đun bằng cách đặt BOARD_VNDK_VERSION trong các biến môi trường của mình:

$ BOARD_VNDK_VERSION=current m module_name.vendor

Khi BOARD_VNDK_VERSION được bật, một số đường dẫn tìm kiếm tiêu đề chung mặc định sẽ bị xóa . Bao gồm các:

  • 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

Nếu một mô-đun phụ thuộc vào các tiêu đề từ các thư mục này, bạn phải chỉ định (rõ ràng) các phần phụ thuộc với header_libs , static_libs và/hoặc shared_libs .

ĐỈNH VNĐK

Trong Android 10 trở xuống, các mô-đun có vndk.enabled đã được cài đặt trong /system/lib[64]/vndk[-sp]-${VER} . Trong Android 11 trở lên, thư viện VNĐK được đóng gói theo định dạng APEX và tên của VNĐK APEX là com.android.vndk.v${VER} . Tùy thuộc vào cấu hình thiết bị, VNDK APEX được làm phẳng hoặc không được làm phẳng và có sẵn từ đường dẫn chuẩn /apex/com.android.vndk.v${VER} .

ĐỈNH VNĐK

Hình 2. ĐỈNH VNĐK

định nghĩa mô-đun

Để xây dựng Android với BOARD_VNDK_VERSION , bạn phải sửa lại định nghĩa mô-đun trong Android.mk hoặc Android.bp . Phần này mô tả các loại định nghĩa mô-đun khác nhau, một số thuộc tính mô-đun liên quan đến VNDK và kiểm tra phụ thuộc được triển khai trong hệ thống xây dựng.

Mô-đun nhà cung cấp

Mô-đun nhà cung cấp là các tệp thực thi hoặc thư viện dùng chung dành riêng cho nhà cung cấp phải được cài đặt vào phân vùng của nhà cung cấp. Trong tệp Android.bp , mô-đun nhà cung cấp phải đặt thuộc tính nhà cung cấp hoặc độc quyền thành true . Trong tệp Android.mk , mô-đun của nhà cung cấp phải đặt LOCAL_VENDOR_MODULE hoặc LOCAL_PROPRIETARY_MODULE thành true .

Nếu BOARD_VNDK_VERSION được xác định, hệ thống xây dựng không cho phép sự phụ thuộc giữa mô-đun nhà cung cấp và mô-đun khung và sẽ phát ra lỗi nếu:

  • một mô-đun không có vendor:true phụ thuộc vào mô-đun có vendor:true hoặc
  • một mô-đun có vendor:true phụ thuộc vào một mô-đun không phải llndk_library không có vendor:true cũng không vendor_available:true .

Kiểm tra phụ thuộc áp dụng cho header_libs , static_libsshared_libs trong Android.bp và cho LOCAL_HEADER_LIBRARIES , LOCAL_STATIC_LIBRARIESLOCAL_SHARED_LIBRARIES trong Android.mk .

LL-NDK

Thư viện chia sẻ LL-NDK là thư viện chia sẻ có ABI ổn định. Cả mô-đun khung và nhà cung cấp đều có chung cách triển khai mới nhất. Đối với mỗi thư viện chia sẻ LL-NDK, cc_library chứa thuộc tính llndk với tệp ký hiệu:

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

Tệp biểu tượng mô tả các ký hiệu hiển thị cho các mô-đun của nhà cung cấp. Ví dụ:

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

Dựa trên tệp ký hiệu, hệ thống xây dựng tạo ra một thư viện chia sẻ sơ khai cho các mô-đun nhà cung cấp, liên kết với các thư viện này khi BOARD_VNDK_VERSION được bật. Một biểu tượng chỉ được đưa vào thư viện chia sẻ sơ khai nếu nó:

  • Không được xác định ở phần cuối bằng _PRIVATE hoặc _PLATFORM ,
  • Không có thẻ #platform-only
  • Không có thẻ #introduce* hoặc thẻ phù hợp với mục tiêu.

VNĐK

Trong các tệp Android.bp , các định nghĩa mô-đun cc_library , cc_library_static , cc_library_sharedcc_library_headers hỗ trợ ba thuộc tính liên quan đến VNDK: vendor_available , vndk.enabledvndk.support_system_process .

Nếu vendor_available hoặc vndk.enabledtrue thì hai biến thể ( coreVendor ) có thể được tạo. Biến thể cốt lõi phải được coi là mô-đun khung và biến thể của nhà cung cấp phải được coi là mô-đun của nhà cung cấp. Nếu một số mô-đun khung phụ thuộc vào mô-đun này thì biến thể cốt lõi sẽ được tạo. Nếu một số mô-đun của nhà cung cấp phụ thuộc vào mô-đun này thì biến thể của nhà cung cấp sẽ được tạo. Hệ thống xây dựng thực thi các kiểm tra phụ thuộc sau:

  • Biến thể cốt lõi luôn chỉ có khung và không thể truy cập được đối với các mô-đun của nhà cung cấp.
  • Biến thể của nhà cung cấp luôn không thể truy cập được vào các mô-đun khung.
  • Tất cả các phần phụ thuộc của biến thể nhà cung cấp, được chỉ định trong header_libs , static_libs và/hoặc shared_libs , phải là llndk_library hoặc một mô-đun có vendor_available hoặc vndk.enabled .
  • Nếu vendor_availabletrue thì tất cả các mô-đun của nhà cung cấp đều có thể truy cập được biến thể của nhà cung cấp.
  • Nếu vendor_availablefalse thì biến thể nhà cung cấp chỉ có thể truy cập được từ các mô-đun VNĐK hoặc VNĐK-SP khác (tức là các mô-đun có vendor:true không thể liên kết các mô- vendor_available:false ).

Đường dẫn cài đặt mặc định cho cc_library hoặc cc_library_shared được xác định theo các quy tắc sau:

  • Biến thể cốt lõi được cài đặt vào /system/lib[64] .
  • Đường dẫn cài đặt biến thể của nhà cung cấp có thể khác nhau:
    • Nếu vndk.enabledfalse , biến thể của nhà cung cấp sẽ được cài đặt vào /vendor/lib[64] .
    • Nếu vndk.enabledtrue , biến thể của nhà cung cấp sẽ được cài đặt vào VNDK APEX( com.android.vndk.v${VER} ).

Bảng bên dưới tóm tắt cách hệ thống xây dựng xử lý các biến thể của nhà cung cấp:

nhà cung cấp_có sẵn vndk
đã bật
vndk
hỗ trợ_same_process
Mô tả biến thể của nhà cung cấp
true false false Các biến thể của nhà cung cấp CHỈ CÓ VNĐ . Thư viện dùng chung được cài đặt vào /vendor/lib[64] .
true Không hợp lệ (Lỗi xây dựng)
true false Các biến thể của nhà cung cấp là VNĐK . Thư viện dùng chung được cài đặt vào VNĐK APEX.
true Các biến thể của nhà cung cấp là VNĐK-SP . Thư viện dùng chung được cài đặt vào VNĐK APEX.

false

false

false

Không có biến thể của nhà cung cấp. Mô-đun này CHỈ FWK .

true Không hợp lệ (Lỗi xây dựng)
true false Các biến thể của nhà cung cấp là VNĐK-Private . Thư viện dùng chung được cài đặt vào VNĐK APEX. Chúng không được sử dụng trực tiếp bởi các mô-đun của nhà cung cấp.
true Các biến thể của nhà cung cấp là VNĐK-SP-Private . Thư viện dùng chung được cài đặt vào VNĐK APEX. Chúng không được sử dụng trực tiếp bởi các mô-đun của nhà cung cấp.

Tiện ích mở rộng VNĐK

Tiện ích mở rộng VNĐK là thư viện chia sẻ VNĐK với các API bổ sung. Tiện ích mở rộng được cài đặt vào /vendor/lib[64]/vndk[-sp] (không có hậu tố phiên bản) và ghi đè thư viện chia sẻ VNĐK gốc khi chạy.

Xác định phần mở rộng VNĐK

Trong Android 9 trở lên, Android.bp vốn hỗ trợ các tiện ích mở rộng VNDK. Để xây dựng tiện ích mở rộng VNDK, hãy xác định một mô-đun khác với thuộc tính vendor:trueextends :

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

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

Một mô-đun có các thuộc tính của vendor:true , vndk.enabled:trueextends xác định tiện ích mở rộng VNĐK:

  • Thuộc tính extends phải chỉ định tên thư viện chia sẻ VNĐK cơ sở (hoặc tên thư viện chia sẻ VNĐK-SP).
  • Tiện ích mở rộng VNDK (hoặc tiện ích mở rộng VNDK-SP) được đặt tên theo tên mô-đun cơ sở mà chúng mở rộng. Ví dụ: nhị phân đầu ra của libvndk_extlibvndk.so thay vì libvndk_ext.so .
  • Tiện ích mở rộng VNDK được cài đặt vào /vendor/lib[64]/vndk .
  • Tiện ích mở rộng VNDK-SP được cài đặt vào /vendor/lib[64]/vndk-sp .
  • Các thư viện chia sẻ cơ sở phải có cả vndk.enabled:truevendor_available:true .

Tiện ích mở rộng VNDK-SP phải mở rộng từ thư viện chia sẻ VNDK-SP ( vndk.support_system_process phải bằng nhau):

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,
    },
}

Tiện ích mở rộng VNDK (hoặc tiện ích mở rộng VNDK-SP) có thể phụ thuộc vào thư viện chia sẻ của nhà cung cấp khác:

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,
}

Sử dụng tiện ích mở rộng VNĐK

Nếu mô-đun nhà cung cấp phụ thuộc vào các API bổ sung được xác định bởi tiện ích mở rộng VNĐK, mô-đun phải chỉ định tên của tiện ích mở rộng VNĐK trong thuộc tính shared_libs của nó:

// 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",
    ],
}

Nếu mô-đun nhà cung cấp phụ thuộc vào tiện ích mở rộng VNĐK, các tiện ích mở rộng VNĐK đó sẽ được cài đặt tự động vào /vendor/lib[64]/vndk[-sp] . Nếu một mô-đun không còn phụ thuộc vào tiện ích mở rộng VNĐK, hãy thêm một bước sạch vào CleanSpec.mk để xóa thư viện dùng chung. Ví dụ:

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

Biên dịch có điều kiện

Phần này mô tả cách giải quyết những khác biệt nhỏ (ví dụ: thêm hoặc xóa một tính năng khỏi một trong các biến thể) giữa ba thư viện chia sẻ VNĐK sau:

  • Biến thể cốt lõi (ví dụ /system/lib[64]/libexample.so )
  • Biến thể của nhà cung cấp (ví dụ /apex/com.android.vndk.v${VER}/lib[64]/libexample.so )
  • Phần mở rộng VNĐK (ví dụ /vendor/lib[64]/vndk[-sp]/libexample.so )

Cờ biên dịch có điều kiện

Hệ thống xây dựng Android xác định __ANDROID_VNDK__ cho các biến thể của nhà cung cấp và tiện ích mở rộng VNĐK theo mặc định. Bạn có thể bảo vệ mã bằng bộ bảo vệ tiền xử lý C:

void all() { }

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

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

Ngoài __ANDROID_VNDK__ , cflags hoặc cppflags khác nhau có thể được chỉ định trong Android.bp . cflags hoặc cppflags được chỉ định trong target.vendor dành riêng cho biến thể của nhà cung cấp.

Ví dụ: Android.bp sau đây định nghĩa libexamplelibexample_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",
    ],
}

Và đây là danh sách mã của 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

Theo hai tệp này, hệ thống xây dựng tạo ra các thư viện dùng chung với các ký hiệu được xuất sau:

Đường dẫn cài đặt Biểu tượng đã xuất
/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

Yêu cầu về các ký hiệu được xuất

Trình kiểm tra ABI của VNĐK so sánh ABI của các biến thể của nhà cung cấp VNĐKphần mở rộng của VNĐK với các kết xuất ABI tham chiếu trong prebuilts/abi-dumps/vndk .

  • Các ký hiệu được xuất bởi các biến thể của nhà cung cấp VNDK (ví dụ /apex/com.android.vndk.v${VER}/lib[64]/libexample.so ) phải giống hệt (không phải tập hợp cha của) các ký hiệu được xác định trong kết xuất ABI.
  • Các ký hiệu được xuất bởi tiện ích mở rộng VNĐK (ví dụ /vendor/lib[64]/vndk/libexample.so ) phải là tập hợp con của các ký hiệu được xác định trong kết xuất ABI.

Nếu các biến thể của nhà cung cấp VNDK hoặc tiện ích mở rộng VNDK không tuân thủ các yêu cầu trên, trình kiểm tra VNDK ABI sẽ phát ra lỗi xây dựng và dừng quá trình xây dựng.

Loại trừ các tệp nguồn hoặc thư viện dùng chung khỏi các biến thể của nhà cung cấp

Để loại trừ các tệp nguồn khỏi biến thể của nhà cung cấp, hãy thêm chúng vào thuộc tính exclude_srcs . Tương tự, để đảm bảo các thư viện dùng chung không được liên kết với biến thể của nhà cung cấp, hãy thêm các thư viện đó vào thuộc tính exclude_shared_libs . Ví dụ:

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"],
        },
    },
}

Trong ví dụ này, biến thể cốt lõi của libexample_cond_exclude bao gồm mã từ fwk.cboth.c và phụ thuộc vào thư viện dùng chung libfwk_onlylibboth . Biến thể nhà cung cấp của libexample_cond_exclude chỉ bao gồm mã từ both.cfwk.c bị thuộc tính exclude_srcs loại trừ. Tương tự, nó chỉ phụ thuộc vào thư viện chia sẻ libbothlibfwk_only bị loại trừ bởi thuộc tính exclude_shared_libs .

Xuất tiêu đề từ tiện ích mở rộng VNĐK

Tiện ích mở rộng VNDK có thể thêm các lớp mới hoặc chức năng mới vào thư viện dùng chung VNDK. Bạn nên giữ những khai báo đó trong các tiêu đề độc lập và tránh thay đổi các tiêu đề hiện có.

Ví dụ: một tệp tiêu đề mới include-ext/example/ext/feature_name.h được tạo cho phần mở rộng VNĐK libexample_ext :

  • Android.bp
  • include-ext/example/ext/feature_name.h
  • bao gồm/example/example.h
  • src/example.c
  • src/ext/feature_name.c

Trong Android.bp sau đây, xuất libexample chỉ include , trong khi xuất libexample_ext cả includeinclude-ext . Điều này đảm bảo feature_name.h sẽ không được người dùng libexample đưa vào không chính xác:

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",
    },
}

Nếu việc tách các phần mở rộng thành các tệp tiêu đề độc lập là không khả thi thì một giải pháp thay thế là thêm các bộ bảo vệ #ifdef . Tuy nhiên, hãy đảm bảo rằng tất cả người dùng tiện ích mở rộng VNDK đều thêm cờ xác định. Bạn có thể xác định cc_defaults để thêm cờ xác định vào cflags và liên kết các thư viện dùng chung với shared_libs .

Ví dụ: để thêm hàm thành viên mới Example2::get_b() vào phần mở rộng VNĐK libexample2_ext , bạn phải sửa đổi tệp tiêu đề hiện có và thêm bộ bảo vệ #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_

Một cc_defaults có tên libexample2_ext_defaults được xác định cho người dùng 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",
    ],
}

Người dùng libexample2_ext có thể chỉ cần đưa libexample2_ext_defaults vào thuộc tính defaults của họ:

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

Gói sản phẩm

Trong hệ thống xây dựng Android, biến PRODUCT_PACKAGES chỉ định các tệp thực thi, thư viện dùng chung hoặc gói sẽ được cài đặt vào thiết bị. Sự phụ thuộc bắc cầu của các mô-đun được chỉ định cũng được cài đặt ngầm vào thiết bị.

Nếu BOARD_VNDK_VERSION được bật, các mô-đun có vendor_available hoặc vndk.enabled sẽ được xử lý đặc biệt. Nếu mô-đun khung phụ thuộc vào mô-đun có vendor_available hoặc vndk.enabled thì biến thể cốt lõi sẽ được bao gồm trong bộ cài đặt bắc cầu. Nếu mô-đun nhà cung cấp phụ thuộc vào mô-đun có vendor_available , thì biến thể của nhà cung cấp sẽ được bao gồm trong bộ cài đặt chuyển tiếp. Tuy nhiên, các biến thể của mô-đun có vndk.enabled được cài đặt cho dù chúng có được mô-đun của nhà cung cấp sử dụng hay không.

Khi hệ thống xây dựng không nhìn thấy được các phần phụ thuộc (ví dụ: các thư viện dùng chung có thể được mở bằng dlopen() trong thời gian chạy), bạn nên chỉ định tên mô-đun trong PRODUCT_PACKAGES để cài đặt các mô-đun đó một cách rõ ràng.

Nếu một mô-đun có vendor_available hoặc vndk.enabled , tên mô-đun là viết tắt của biến thể cốt lõi của nó. Để chỉ định rõ ràng biến thể của nhà cung cấp trong PRODUCT_PACKAGES , hãy thêm hậu tố .vendor vào tên mô-đun. Ví dụ:

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

Trong ví dụ này, libexample là viết tắt của /system/lib[64]/libexample.solibexample.vendor là viết tắt của /vendor/lib[64]/libexample.so . Để cài đặt /vendor/lib[64]/libexample.so , hãy thêm libexample.vendor vào PRODUCT_PACKAGES :

PRODUCT_PACKAGES += libexample.vendor