MemoryBlock HIDL è un livello astratto basato su hidl_memory, HIDL
@1.0::IAllocator e HIDL @1.0::IMapper. È progettato per i servizi HIDL
che hanno più blocchi di memoria per condividere un singolo heap di memoria.
Miglioramenti delle prestazioni
L'utilizzo di MemoryBlock nelle app può ridurre significativamente il numero di
mmap/munmap e gli errori di segmentazione dello spazio utente, migliorando così le prestazioni.
Ad esempio:
- L'utilizzo di hidl_memoryper ogni allocazione del buffer è in media di 238 us/1 allocazione.
- L'utilizzo di MemoryBlocke la condivisione di un singolohidl_memoryin media 2,82 us/1 allocazione.
Architettura
L'architettura HIDL MemoryBlock include servizi HIDL con più blocchi di memoria che condividono un singolo heap di memoria:
 
Figura 1. Architettura di MemoryBlock HIDL
Utilizzo normale
Questa sezione fornisce un esempio di utilizzo di MemoryBlock dichiarando prima l'HAL e poi implementandola.
Dichiarare l'HAL
Per il seguente esempio di HAL IFoo:
import android.hidl.memory.block@1.0::MemoryBlock;
interface IFoo {
    getSome() generates(MemoryBlock block);
    giveBack(MemoryBlock block);
};
Il Android.bp è il seguente:
hidl_interface {
    ...
    srcs: [
        "IFoo.hal",
    ],
    interfaces: [
        "android.hidl.memory.block@1.0",
        ...
};
Implementa l'HAL
Per implementare l'HAL di esempio:
- Ottieni - hidl_memory(per i dettagli, consulta 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 }));
- Crea un'istanza - HidlMemoryDealercon il- hidl_memoryacquisito:- #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);
- Alloca - MemoryBlock, che è una struttura definita con HIDL.- Esempio - MemoryBlock:- struct MemoryBlock { IMemoryToken token; uint64_t size; uint64_t offset; };- Esempio di utilizzo di - MemoryDealerper allocare un- 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); ...
- Deallocate - MemoryBlock:- Return<void> Foo::giveBack(const MemoryBlock& block) { memory_dealer->deallocate(block.offset); ...
- Manipola i dati: - #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()));
- Config - Android.bp:- shared_libs: [ "android.hidl.memory@1.0", "android.hidl.memory.block@1.0" "android.hidl.memory.token@1.0", "libhidlbase", "libhidlmemory",
- Esamina il flusso per determinare se devi - lockMemory.- Normalmente, - MemoryBlockutilizza il conteggio dei riferimenti per mantenere la memoria condivisa- hidl_memoryche viene- mmap()-ed la prima volta che una delle sue- 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` viene mappata durante il ciclo di vita del blocco. Esempio:- #include <hidlmemory/mapping.h> sp<RefBase> lockMemory(const sp<IMemoryToken> key);
Utilizzo esteso
Questa sezione fornisce dettagli sull'utilizzo esteso di MemoryBlock.
Utilizzare il conteggio dei riferimenti per gestire MemoryBlock
Nella maggior parte dei casi, il modo più efficiente per utilizzare MemoryBlock è allocare/deallocare
in modo esplicito. Tuttavia, in app complesse l'utilizzo del conteggio dei riferimenti
per la garbage collection potrebbe essere una soluzione migliore. Per avere il conteggio dei riferimenti su
MemoryBlock, puoi associare MemoryBlock a un oggetto binder, che consente di
contare i riferimenti e deallocare MemoryBlock quando il conteggio diminuisce
fino a zero.
Dichiarare l'HAL
Quando dichiari l'HAL, descrivi una struttura HIDL che contiene un'istanza MemoryBlock
e un'interfaccia IBase:
import android.hidl.memory.block@1.0::MemoryBlock;
struct MemoryBlockAllocation {
    MemoryBlock block;
    IBase refcnt;
};
Utilizza MemoryBlockAllocation per sostituire MemoryBlock e rimuovere il metodo
per restituire MemoryBlock. Viene deallocato tramite il conteggio dei riferimenti
con MemoryBlockAllocation. Esempio:
interface IFoo {
    allocateSome() generates(MemoryBlockAllocation allocation);
};
Implementa l'HAL
Esempio di implementazione lato servizio dell'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);
Esempio di implementazione lato client di HAL:
ifoo->allocateSome([&](const MemoryBlockAllocation& allocation){
    ...
);
Allegare e recuperare i metadati
Alcune app hanno bisogno di dati aggiuntivi per essere associate al MemoryBlock allocato.
Puoi aggiungere e recuperare i metadati utilizzando due metodi:
- Se l'app accede ai metadati con la stessa frequenza del blocco stesso, aggiungi i metadati e passali tutti in una struttura. Esempio: - import android.hidl.memory.block@1.0::MemoryBlock; struct MemoryBlockWithMetaData{ MemoryBlock block; MetaDataStruct metaData; };
- Se l'app accede ai metadati con una frequenza molto inferiore rispetto al blocco, è più efficiente trasmetterli passivamente con un'interfaccia. Esempio: - import android.hidl.memory.block@1.0::MemoryBlock; struct MemoryBlockWithMetaData{ MemoryBlock block; IMetaData metaData; };- Successivamente, associa i metadati a - MemoryBlockutilizzando- MemoryDealer. Esempio:- MemoryBlockWithMetaData memory_block; memory_block.block = dealer->allocate(size); if(HidlMemoryDealer::isOk(block)){ memory_block.metaData = new MetaData(...);