Das HIDL MemoryBlock ist eine abstrakte Ebene, die auf hidl_memory, HIDL
@1.0::IAllocator und HIDL @1.0::IMapper basiert. Es ist für HIDL-Dienste konzipiert, die mehrere Speicherblöcke haben, um einen einzelnen Speicher-Heap zu teilen.
Leistungsverbesserungen
Die Verwendung von MemoryBlock in Apps kann die Anzahl der mmap-/munmap- und Nutzerbereichs-Segmentierungsfehler erheblich reduzieren und so die Leistung verbessern.
Beispiel:
- Die Verwendung von „per hidl_memory“ für jede Pufferzuweisung dauert durchschnittlich 238 Mikrosekunden pro Zuweisung.
- Bei Verwendung von MemoryBlockund Freigabe einer einzelnenhidl_memorysind durchschnittlich 2,82 µs/Zuweisung erforderlich.
Architektur
Die HIDL-Architektur MemoryBlock umfasst HIDL-Dienste mit mehreren Speicherblöcken, die sich einen einzelnen Speicher-Heap teilen:
 
 
Abbildung 1: HIDL-MemoryBlock-Architektur
Normale Nutzung
In diesem Abschnitt wird ein Beispiel für die Verwendung von MemoryBlock gezeigt. Dazu wird zuerst die HAL deklariert und dann implementiert.
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);
};
Der 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:
- Rufen Sie die - hidl_memoryab (weitere Informationen finden Sie 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 }));
- Erstellen Sie eine - HidlMemoryDealer-Instanz mit dem abgerufenen- 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);
- Weisen Sie - MemoryBlockzu. Dies ist eine mit HIDL definierte Struktur.- Beispiel - MemoryBlock:- struct MemoryBlock { IMemoryToken token; uint64_t size; uint64_t offset; };- Beispiel für die Zuweisung einer - MemoryBlockmit- MemoryDealer:- #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); ...
- MemoryBlockfreigeben:- Return<void> Foo::giveBack(const MemoryBlock& block) { memory_dealer->deallocate(block.offset); ...
- Daten bearbeiten: - #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()));
- Konfiguration - Android.bp:- shared_libs: [ "android.hidl.memory@1.0", "android.hidl.memory.block@1.0" "android.hidl.memory.token@1.0", "libhidlbase", "libhidlmemory",
- Prüfen Sie den Ablauf, um festzustellen, ob Sie - lockMemorymüssen.- Normalerweise verwendet - MemoryBlockdie Referenzanzahl, um die gemeinsam genutzte- hidl_memorybeizubehalten, die beim ersten Mal, wenn eine ihrer- MemoryBlock instances is mapped and ismunmap()- -ed when nothing refers to it. To keephidl_memory- always mapped, you can uselockMemory- , a RAII style object that keeps the correspondinghidl_memory` während des gesamten Sperrlebenszyklus zugeordnet wird,- mmap()-ed wird. 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.
Verwenden der Referenzanzahl zum Verwalten von MemoryBlock
In den meisten Situationen ist es am effizientesten, MemoryBlock explizit zuzuweisen bzw. freizugeben. Bei komplexen Apps kann es jedoch besser sein, die Referenzzählung für die Garbage Collection zu verwenden. Um die Referenzanzahl für MemoryBlock zu ermitteln, können Sie MemoryBlock an ein Binder-Objekt binden. So können die Referenzen gezählt und MemoryBlock freigegeben werden, wenn die Anzahl auf null sinkt.
HAL deklarieren
Beschreiben Sie beim Deklarieren des HAL eine HIDL-Struktur, die eine MemoryBlock-Instanz und eine IBase enthält:
import android.hidl.memory.block@1.0::MemoryBlock;
struct MemoryBlockAllocation {
    MemoryBlock block;
    IBase refcnt;
};
Verwenden Sie MemoryBlockAllocation, um MemoryBlock zu ersetzen, und entfernen Sie die Methode, um MemoryBlock zurückzugeben. Der Speicher wird durch Referenzzählung mit MemoryBlockAllocation freigegeben. Beispiel:
interface IFoo {
    allocateSome() generates(MemoryBlockAllocation allocation);
};
HAL implementieren
Beispiel für die serverseitige 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 der HAL:
ifoo->allocateSome([&](const MemoryBlockAllocation& allocation){
    ...
);
Metadaten anhängen und abrufen
Für einige Apps sind zusätzliche Daten erforderlich, um sie mit dem zugewiesenen MemoryBlock zu verknüpfen.
Sie haben zwei Möglichkeiten, Metadaten anzuhängen und abzurufen:
- Wenn die App so oft auf die Metadaten zugreift wie auf den Block selbst, hängen Sie die Metadaten an und übergeben Sie sie alle in einer Struktur. 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 der Block, ist es effizienter, die Metadaten passiv über eine Schnittstelle zu übergeben. Beispiel: - import android.hidl.memory.block@1.0::MemoryBlock; struct MemoryBlockWithMetaData{ MemoryBlock block; IMetaData metaData; };- Binden Sie als Nächstes die Metadaten mit - MemoryBlockmithilfe von- MemoryDealer. Beispiel:- MemoryBlockWithMetaData memory_block; memory_block.block = dealer->allocate(size); if(HidlMemoryDealer::isOk(block)){ memory_block.metaData = new MetaData(...);
