Google se compromete a impulsar la igualdad racial para las comunidades afrodescendientes. Obtén información al respecto.

Bloque de memoria HIDL

El HIDL MemoryBlock es una capa abstracta construida sobre hidl_memory , HIDL @1.0::IAllocator y HIDL @1.0::IMapper . Está diseñado para servicios HIDL que tienen varios bloques de memoria para compartir un único montón de memoria.

Mejoras de rendimiento

Usando MemoryBlock en aplicaciones puede reducir significativamente el número de mmap / munmap fallas y el espacio de segmentación del usuario, mejorando así el rendimiento. Por ejemplo:

  • El uso por hidl_memory para cada promedios de asignación de memoria intermedia 238 us / 1 de la asignación.
  • Usando MemoryBlock y compartir una sola hidl_memory promedios 2.82 nosotros / 1 de asignación.

Arquitectura

La arquitectura HIDL MemoryBlock incluye servicios HIDL con múltiples bloques de memoria que comparten un único montón de memoria:

Bloque de memoria HIDL

Arquitectura Figura 1. HIDL MemoryBlock

Uso normal

Esta sección proporciona un ejemplo del uso de MemoryBlock declarando primero el HAL y luego implementando el HAL.

Declarando el HAL

Para el siguiente ejemplo IFoo HAL:

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

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

El Android.bp es como sigue:

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

Implementando el HAL

Para implementar el ejemplo HAL:

  1. Obtener el hidl_memory (para más detalles, consulte 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. Hacer una HidlMemoryDealer con lo adquirido 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. Asignar MemoryBlock , que es una estructura definida con HIDL.

    Ejemplo MemoryBlock :

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

    Ejemplo usando el MemoryDealer asignar 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);
        ...
    
  4. Deallocate MemoryBlock :

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

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

    shared_libs: [
            "android.hidl.memory@1.0",
    
            "android.hidl.memory.block@1.0"
    
            "android.hidl.memory.token@1.0",
            "libhidlbase",
            "libhidlmemory",
    
  7. Revisar el flujo para determinar si necesita lockMemory .

    Normalmente, el MemoryBlock utiliza el número de referencia para mantener la compartida hidl_memory que es mmap() -ed la primera época de su MemoryBlock s consigue asignada y es munmap() -ed cuando nada se refiere a ella. Para mantener el hidl_memory siempre asignada, puede utilizar lockMemory , un objeto de estilo RAII que mantiene el correspondiente hidl_memory asignada durante todo el ciclo de vida de bloqueo. Ejemplo:

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

Uso extendido

Esta sección proporciona información sobre el uso prolongado de MemoryBlock .

Usar el recuento de referencias para administrar Memoryblock

En la mayoría de las situaciones, la forma más eficiente de usar MemoryBlock es asignar / desasignar explícitamente. Sin embargo, en aplicaciones complicadas, usar el recuento de referencias para la recolección de basura puede ser una mejor idea. Para tener un recuento de referencias en MemoryBlock, puede vincular MemoryBlock con un objeto de enlace, lo que ayuda a contar las referencias y desasignar el MemoryBlock cuando el recuento desciende a cero.

Declarando el HAL

Al declarar el HAL, describa una estructura HIDL que contenga un MemoryBlock y un IBase:

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

struct MemoryBlockAllocation {
    MemoryBlock block;
    IBase refcnt;
};

Usar la MemoryBlockAllocation para reemplazar MemoryBlock y quitar el método de devolver el MemoryBlock . Se cancela la asignación mediante recuento de referencia con la MemoryBlockAllocation . Ejemplo:

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

Implementación de HAL

Ejemplo de la implementación del lado del servicio de 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);

Ejemplo de la implementación del lado del cliente de HAL:

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

Adjuntar / recuperar metadatos

Algunas aplicaciones necesitan datos adicionales para enlazar con el asignado MemoryBlock . Puede agregar / recuperar metadatos usando dos métodos:

  • Si la aplicación accede a los metadatos con la misma frecuencia que el propio bloque, agregue los metadatos y páselos todos en una estructura. Ejemplo:

    import android.hidl.memory.block@1.0::MemoryBlock;
    
    struct MemoryBlockWithMetaData{
        MemoryBlock block;
        MetaDataStruct metaData;
    };
    
  • Si la aplicación accede a los metadatos con mucha menos frecuencia que el bloque, es más eficiente pasar los metadatos de forma pasiva con una interfaz. Ejemplo:

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

    A continuación, vincule los metadatos con MemoryBlock utilizando Memory Dealer. Ejemplo:

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