Blok Memori HIDL

MemoryBlock HIDL adalah lapisan abstrak yang dibuat pada hidl_memory, HIDL @1.0::IAllocator, dan HIDL @1.0::IMapper. Dirancang untuk layanan HIDL yang memiliki beberapa blok memori untuk berbagi satu heap memori.

Peningkatan performa

Menggunakan MemoryBlock di aplikasi dapat mengurangi jumlah mmap/munmap dan kesalahan segmentasi ruang pengguna, sehingga meningkatkan performa. Contoh:

  • Penggunaan per hidl_memory untuk setiap alokasi buffer memiliki rata-rata 238 us/1 alokasi.
  • Menggunakan MemoryBlock dan membagikan satu hidl_memory menghasilkan rata-rata 2,82 us/1 alokasi.

Arsitektur

Arsitektur MemoryBlock HIDL mencakup layanan HIDL dengan beberapa memori blok yang berbagi satu heap memori:

Blok Memori HIDL

Gambar 1. Arsitektur HIDL MemoryBlock

Penggunaan normal

Bagian ini memberikan contoh penggunaan MemoryBlock dengan mendeklarasikan terlebih dahulu HAL lalu menerapkan HAL.

Mendeklarasikan HAL

Untuk contoh berikut IFoo HAL:

import android.hidl.memory.block@1.0::MemoryBlock;

interface IFoo {
    getSome() generates(MemoryBlock block);
    giveBack(MemoryBlock block);
};

Android.bp adalah sebagai berikut:

hidl_interface {
    ...
    srcs: [
        "IFoo.hal",
    ],
    interfaces: [
        "android.hidl.memory.block@1.0",
        ...
};

Mengimplementasikan HAL

Untuk menerapkan contoh HAL:

  1. Mendapatkan hidl_memory (untuk mengetahui detailnya, lihat HIDL C++).

    #include <android/hidl/allocator/1.0/IAllocator.h>
    
    using ::android::hidl::allocator::V1_0::IAllocator;
    using ::android::hardware::hidl_memory;
    ...
      sp<IAllocator> allocator = IAllocator::getService("ashmem");
      allocator->allocate(2048, [&](bool success, const hidl_memory& mem)
      {
            if (!success) { /* error */ }
            // you can now use the hidl_memory object 'mem' or pass it
      }));
    
  2. Buat instance HidlMemoryDealer dengan hidl_memory yang diperoleh:

    #include <hidlmemory/HidlMemoryDealer.h>
    
    using ::android::hardware::HidlMemoryDealer
    /* The mem argument is acquired in the Step1, returned by the ashmemAllocator->allocate */
    sp<HidlMemoryDealer> memory_dealer = HidlMemoryDealer::getInstance(mem);
    
  3. Alokasikan MemoryBlock, yang merupakan struct yang ditentukan dengan HIDL.

    Contoh MemoryBlock:

    struct MemoryBlock {
    IMemoryToken token;
    uint64_t size;
    uint64_t offset;
    };
    

    Contoh menggunakan MemoryDealer untuk mengalokasikan MemoryBlock:

    #include <android/hidl/memory/block/1.0/types.h>
    
    using ::android::hidl::memory::block::V1_0::MemoryBlock;
    
    Return<void> Foo::getSome(getSome_cb _hidl_cb) {
        MemoryBlock block = memory_dealer->allocate(1024);
        if(HidlMemoryDealer::isOk(block)){
            _hidl_cb(block);
        ...
    
  4. Hapus alokasi MemoryBlock:

    Return<void> Foo::giveBack(const MemoryBlock& block) {
        memory_dealer->deallocate(block.offset);
    ...
    
  5. Memanipulasi data:

    #include <hidlmemory/mapping.h>
    #include <android/hidl/memory/1.0/IMemory.h>
    
    using ::android::hidl::memory::V1_0::IMemory;
    
    sp<IMemory> memory = mapMemory(block);
    uint8_t* data =
    
    static_cast<uint8_t*>(static_cast<void*>(memory->getPointer()));
    
  6. Konfigurasi Android.bp:

    shared_libs: [
            "android.hidl.memory@1.0",
    
            "android.hidl.memory.block@1.0"
    
            "android.hidl.memory.token@1.0",
            "libhidlbase",
            "libhidlmemory",
    
  7. Tinjau alurnya untuk menentukan apakah Anda perlu lockMemory.

    Biasanya, MemoryBlock menggunakan jumlah referensi untuk mempertahankan hidl_memory yang mmap()-di-ed saat pertama kali salah satu MemoryBlock instances is mapped and ismunmap()-ed when nothing refers to it. To keephidl_memoryalways mapped, you can uselockMemory, a RAII style object that keeps the correspondinghidl_memory` dipetakan di seluruh kunci siklus proses. Contoh:

    #include <hidlmemory/mapping.h>
    
    sp<RefBase> lockMemory(const sp<IMemoryToken> key);
    

Penggunaan yang diperpanjang

Bagian ini memberikan detail tentang perpanjangan penggunaan MemoryBlock.

Menggunakan jumlah referensi untuk mengelola MemoryBlock

Dalam sebagian besar situasi, cara paling efisien untuk menggunakan MemoryBlock adalah dengan alokasikan/dealokasikan. Namun, di aplikasi rumit yang menggunakan jumlah referensi untuk pembersihan sampah memori mungkin adalah ide yang lebih baik. Untuk mengaktifkan jumlah referensi MemoryBlock, Anda dapat mengikat MemoryBlock dengan objek binder, yang membantu menghitung referensi dan membatalkan alokasi MemoryBlock saat jumlahnya berkurang ke nol.

Mendeklarasikan HAL

Saat mendeklarasikan HAL, jelaskan struct HIDL yang berisi MemoryBlock dan IBase:

import android.hidl.memory.block@1.0::MemoryBlock;

struct MemoryBlockAllocation {
    MemoryBlock block;
    IBase refcnt;
};

Gunakan MemoryBlockAllocation untuk mengganti MemoryBlock dan menghapus metode untuk mengembalikan dana sebesar MemoryBlock. Paket tersebut dibatalkan alokasinya berdasarkan penghitungan referensi dengan MemoryBlockAllocation. Contoh:

interface IFoo {
    allocateSome() generates(MemoryBlockAllocation allocation);
};

Mengimplementasikan HAL

Contoh implementasi HAL sisi layanan:

class MemoryBlockRefCnt: public virtual IBase {
   MemoryBlockRefCnt(uint64_t offset, sp<MemoryDealer> dealer)
     : mOffset(offset), mDealer(dealer) {}
   ~MemoryBlockRefCnt() {
       mDealer->deallocate(mOffset);
   }
 private:
   uint64_t mOffset;
   sp<MemoryDealer> mDealer;
};

Return<void> Foo::allocateSome(allocateSome_cb _hidl_cb) {
    MemoryBlockAllocation allocation;
    allocation.block = memory_dealer->allocate(1024);
    if(HidlMemoryDealer::isOk(block)){
        allocation.refcnt= new MemoryBlockRefCnt(...);
        _hidl_cb(allocation);

Contoh implementasi HAL sisi klien:

ifoo->allocateSome([&](const MemoryBlockAllocation& allocation){
    ...
);

Melampirkan dan mengambil metadata

Beberapa aplikasi memerlukan data tambahan untuk mengikat dengan MemoryBlock yang dialokasikan. Anda dapat menambahkan dan mengambil metadata menggunakan dua metode:

  • Jika aplikasi mengakses metadata sesering blok itu sendiri, menambahkan {i>metadata<i} dan meneruskan semuanya dalam sebuah struct. Contoh:

    import android.hidl.memory.block@1.0::MemoryBlock;
    
    struct MemoryBlockWithMetaData{
        MemoryBlock block;
        MetaDataStruct metaData;
    };
    
  • Jika aplikasi jauh lebih jarang mengakses metadata daripada Namun, akan lebih efisien untuk meneruskan metadata secara pasif dengan dalam antarmuka berbasis web yang sederhana. Contoh:

    import android.hidl.memory.block@1.0::MemoryBlock;
    
    struct MemoryBlockWithMetaData{
        MemoryBlock block;
        IMetaData metaData;
    };
    

    Selanjutnya, ikat metadata dengan MemoryBlock menggunakan MemoryDealer. Contoh:

    MemoryBlockWithMetaData memory_block;
    memory_block.block = dealer->allocate(size);
    if(HidlMemoryDealer::isOk(block)){
        memory_block.metaData = new MetaData(...);