HIDL MemoryBlock

Das HIDL MemoryBlock ist eine abstrakte Ebene, die auf hidl_memory, HIDL @1.0::IAllocator und HIDL @1.0::IMapper basiert. Es wurde für HIDL-Dienste entwickelt. die mehrere Speicherblöcke haben, um sich einen einzelnen Speicher-Heap zu teilen.

Leistungsverbesserungen

Durch die Verwendung von MemoryBlock in Apps kann die Anzahl der mmap/munmap und Nutzerbereich-Segmentierungsfehler, wodurch die Leistung verbessert wird. Beispiel:

  • Die Verwendung pro hidl_memory für jede Pufferzuweisung beträgt durchschnittlich 238 us/1. Zuordnung.
  • Die Nutzung von MemoryBlock und die gemeinsame Nutzung eines einzelnen hidl_memory führt zu durchschnittlich 2,82 uns/1 Zuordnung.

Architektur

Die HIDL-MemoryBlock-Architektur umfasst HIDL-Dienste mit mehreren Arbeitsspeichern die Freigabe eines einzelnen Speicher-Heaps blockieren:

HIDL MemoryBlock

Abbildung 1: HIDL MemoryBlock-Architektur

Normale Nutzung

Dieser Abschnitt enthält ein Beispiel für die Verwendung von MemoryBlock, indem zuerst die Methode HAL und implementiert dann den HAL.

HAL deklarieren

Für das folgende IFoo HAL-Beispiel:

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

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

Android.bp sieht so aus:

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

HAL implementieren

So implementieren Sie das Beispiel-HAL:

  1. Hol dir das hidl_memory (weitere Informationen findest du unter 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. Erstellen Sie eine HidlMemoryDealer-Instanz mit der übernommenen hidl_memory:

    #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. Weisen Sie MemoryBlock zu. Dies ist eine mit HIDL definierte Struktur.

    Beispiel für MemoryBlock:

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

    Beispiel für die Verwendung von MemoryDealer zum Zuweisen einer 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. Zuweisung von MemoryBlock aufheben:

    Return<void> Foo::giveBack(const MemoryBlock& block) {
        memory_dealer->deallocate(block.offset);
    ...
    
  5. So bearbeiten Sie die Daten:

    #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. Konfiguration Android.bp:

    shared_libs: [
            "android.hidl.memory@1.0",
    
            "android.hidl.memory.block@1.0"
    
            "android.hidl.memory.token@1.0",
            "libhidlbase",
            "libhidlmemory",
    
  7. Prüfen Sie den Ablauf, um festzustellen, ob Sie lockMemory.

    Normalerweise verwendet MemoryBlock die Referenzanzahl, um die geteilten Inhalte aufrechtzuerhalten. hidl_memory, das mmap()-ed-Objekt wird, wenn zum ersten Mal eine seiner 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`-Funktion innerhalb der Sperre zugeordnet wird Lebenszyklus. Beispiel:

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

Verlängerte Nutzung

Dieser Abschnitt enthält Details zur erweiterten Nutzung von MemoryBlock.

Referenzanzahl zum Verwalten von MemoryBlock verwenden

In den meisten Situationen ist es am effizientesten, MemoryBlock zu verwenden, Zuweisen/Auflösen. In komplizierten Apps mit der Anzahl der Referenzen für die automatische Speicherbereinigung. Damit die Anzahl der Referenzen MemoryBlock können Sie MemoryBlock mit einem Binderobjekt binden. Verweise zählen und die Zuweisung von MemoryBlock aufheben, wenn die Anzahl sinkt auf null setzen.

HAL deklarieren

Beschreiben Sie beim Deklarieren des HAL eine HIDL-Struktur, die ein MemoryBlock enthält. und eine IBase-Instanz:

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

struct MemoryBlockAllocation {
    MemoryBlock block;
    IBase refcnt;
};

Verwenden Sie MemoryBlockAllocation, um MemoryBlock zu ersetzen und die Methode zu entfernen um MemoryBlock zurückzugeben. Die Freigabe erfolgt durch Referenzzählung. mit MemoryBlockAllocation. Beispiel:

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

HAL implementieren

Beispiel für die dienstseitige Implementierung des HAL:

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);

Beispiel für die clientseitige Implementierung des HAL:

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

Metadaten anhängen und abrufen

Einige Apps benötigen zusätzliche Daten, um sie an die zugewiesene MemoryBlock zu binden. Sie können Metadaten mit zwei Methoden anfügen und abrufen:

  • Greift die App genauso oft auf die Metadaten zu wie der Block selbst, die Metadaten anhängen und sie alle in einer Struktur übergeben. Beispiel:

    import android.hidl.memory.block@1.0::MemoryBlock;
    
    struct MemoryBlockWithMetaData{
        MemoryBlock block;
        MetaDataStruct metaData;
    };
    
  • Wenn die App viel seltener auf die Metadaten zugreift als ist es effizienter, die Metadaten passiv mit einem . Beispiel:

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

    Binden Sie als Nächstes die Metadaten mithilfe von MemoryDealer an MemoryBlock. Beispiel:

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