Le HIDL MemoryBlock est une couche abstraite basée sur hidl_memory, HIDL
@1.0::IAllocator et HIDL @1.0::IMapper. Il est conçu pour les services HIDL qui comportent plusieurs blocs de mémoire afin de partager un seul tas de mémoire.
Amélioration des performances
L'utilisation de MemoryBlock dans les applications peut réduire considérablement le nombre de mmap/munmap et les erreurs de segmentation de l'espace utilisateur, ce qui améliore les performances.
Exemple :
- L'utilisation de
hidl_memorypar allocation de tampon est en moyenne de 238 µs/1 allocation. - L'utilisation de
MemoryBlocket le partage d'un seulhidl_memoryreprésentent en moyenne 2,82 µs/1 allocation.
Architecture
L'architecture HIDL MemoryBlock inclut des services HIDL avec plusieurs blocs de mémoire partageant un même tas de mémoire :
Figure 1 : Architecture HIDL MemoryBlock
Utilisation normale
Cette section fournit un exemple d'utilisation de MemoryBlock en déclarant d'abord la HAL, puis en l'implémentant.
Déclarer la HAL
Pour l'exemple IFoo HAL suivant :
import android.hidl.memory.block@1.0::MemoryBlock;
interface IFoo {
getSome() generates(MemoryBlock block);
giveBack(MemoryBlock block);
};
La Android.bp est la suivante :
hidl_interface {
...
srcs: [
"IFoo.hal",
],
interfaces: [
"android.hidl.memory.block@1.0",
...
};
Implémenter la HAL
Pour implémenter l'exemple de HAL :
Obtenez le
hidl_memory(pour en savoir plus, consultez 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 }));Créez une instance
HidlMemoryDealeravec lehidl_memoryobtenu :#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);Allouez
MemoryBlock, qui est une structure définie avec HIDL.Exemple
MemoryBlock:struct MemoryBlock { IMemoryToken token; uint64_t size; uint64_t offset; };Exemple d'utilisation de
MemoryDealerpour allouer unMemoryBlock:#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); ...Libérez
MemoryBlock:Return<void> Foo::giveBack(const MemoryBlock& block) { memory_dealer->deallocate(block.offset); ...Manipuler les données :
#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",Examinez le flux pour déterminer si vous devez
lockMemory.Normalement,
MemoryBlockutilise le nombre de références pour maintenir lehidl_memorypartagé, qui estmmap()-ed la première fois que l'un de sesMemoryBlock 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 est mappé tout au long du cycle de vie du verrou. Exemple :#include <hidlmemory/mapping.h> sp<RefBase> lockMemory(const sp<IMemoryToken> key);
Utilisation étendue
Cette section fournit des informations sur l'utilisation étendue de MemoryBlock.
Utiliser le nombre de références pour gérer MemoryBlock
Dans la plupart des cas, le moyen le plus efficace d'utiliser MemoryBlock consiste à allouer/désallouer explicitement. Toutefois, dans les applications complexes, il peut être préférable d'utiliser le décompte de références pour la récupération de mémoire. Pour que le nombre de références soit disponible sur MemoryBlock, vous pouvez associer MemoryBlock à un objet Binder, ce qui permet de comptabiliser les références et de libérer MemoryBlock lorsque le nombre diminue à zéro.
Déclarer la HAL
Lorsque vous déclarez le HAL, décrivez une structure HIDL qui contient une instance MemoryBlock et une IBase :
import android.hidl.memory.block@1.0::MemoryBlock;
struct MemoryBlockAllocation {
MemoryBlock block;
IBase refcnt;
};
Utilisez MemoryBlockAllocation pour remplacer MemoryBlock et supprimez la méthode pour renvoyer MemoryBlock. Il est libéré par comptage des références avec MemoryBlockAllocation. Exemple :
interface IFoo {
allocateSome() generates(MemoryBlockAllocation allocation);
};
Implémenter la HAL
Exemple d'implémentation côté service du 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);
Exemple d'implémentation côté client du HAL :
ifoo->allocateSome([&](const MemoryBlockAllocation& allocation){
...
);
Associer et récupérer des métadonnées
Certaines applications ont besoin de données supplémentaires pour s'associer à l'MemoryBlock attribué.
Vous pouvez ajouter et récupérer des métadonnées de deux manières :
Si l'application accède aux métadonnées aussi souvent que le bloc lui-même, ajoutez les métadonnées et transmettez-les toutes dans une structure. Exemple :
import android.hidl.memory.block@1.0::MemoryBlock; struct MemoryBlockWithMetaData{ MemoryBlock block; MetaDataStruct metaData; };Si l'application accède aux métadonnées beaucoup moins fréquemment que le bloc, il est plus efficace de transmettre les métadonnées de manière passive avec une interface. Exemple :
import android.hidl.memory.block@1.0::MemoryBlock; struct MemoryBlockWithMetaData{ MemoryBlock block; IMetaData metaData; };Ensuite, liez les métadonnées à
MemoryBlockà l'aide deMemoryDealer. Exemple :MemoryBlockWithMetaData memory_block; memory_block.block = dealer->allocate(size); if(HidlMemoryDealer::isOk(block)){ memory_block.metaData = new MetaData(...);