MemoryBlock
HIDL adalah lapisan abstrak yang dibuat pada hidl_memory
, HIDL
@1.0::IAllocator
, dan HIDL @1.0::IMapper
. Dirancang untuk layanan HIDL
yang memiliki beberapa blok memori untuk
berbagi satu heap memori.
Peningkatan performa
Menggunakan MemoryBlock
di aplikasi dapat mengurangi jumlah
mmap
/munmap
dan kesalahan segmentasi ruang pengguna, sehingga meningkatkan performa.
Contoh:
- Penggunaan per
hidl_memory
untuk setiap alokasi buffer memiliki rata-rata 238 us/1 alokasi. - Menggunakan
MemoryBlock
dan membagikan satuhidl_memory
menghasilkan rata-rata 2,82 us/1 alokasi.
Arsitektur
Arsitektur MemoryBlock
HIDL mencakup layanan HIDL dengan beberapa memori
blok yang berbagi satu heap memori:
Gambar 1. Arsitektur HIDL MemoryBlock
Penggunaan normal
Bagian ini memberikan contoh penggunaan MemoryBlock
dengan mendeklarasikan terlebih dahulu
HAL lalu menerapkan HAL.
Mendeklarasikan HAL
Untuk contoh berikut IFoo HAL:
import android.hidl.memory.block@1.0::MemoryBlock;
interface IFoo {
getSome() generates(MemoryBlock block);
giveBack(MemoryBlock block);
};
Android.bp
adalah sebagai berikut:
hidl_interface {
...
srcs: [
"IFoo.hal",
],
interfaces: [
"android.hidl.memory.block@1.0",
...
};
Mengimplementasikan HAL
Untuk menerapkan contoh HAL:
Mendapatkan
hidl_memory
(untuk mengetahui detailnya, lihat 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 }));
Buat instance
HidlMemoryDealer
denganhidl_memory
yang diperoleh:#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);
Alokasikan
MemoryBlock
, yang merupakan struct yang ditentukan dengan HIDL.Contoh
MemoryBlock
:struct MemoryBlock { IMemoryToken token; uint64_t size; uint64_t offset; };
Contoh menggunakan
MemoryDealer
untuk mengalokasikanMemoryBlock
:#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); ...
Hapus alokasi
MemoryBlock
:Return<void> Foo::giveBack(const MemoryBlock& block) { memory_dealer->deallocate(block.offset); ...
Memanipulasi data:
#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()));
Konfigurasi
Android.bp
:shared_libs: [ "android.hidl.memory@1.0", "android.hidl.memory.block@1.0" "android.hidl.memory.token@1.0", "libhidlbase", "libhidlmemory",
Tinjau alurnya untuk menentukan apakah Anda perlu
lockMemory
.Biasanya,
MemoryBlock
menggunakan jumlah referensi untuk mempertahankanhidl_memory
yangmmap()
-di-ed saat pertama kali salah satuMemoryBlock instances is mapped and is
munmap()-ed when nothing refers to it. To keep
hidl_memoryalways mapped, you can use
lockMemory, a RAII style object that keeps the corresponding
hidl_memory` dipetakan di seluruh kunci siklus proses. Contoh:#include <hidlmemory/mapping.h> sp<RefBase> lockMemory(const sp<IMemoryToken> key);
Penggunaan yang diperpanjang
Bagian ini memberikan detail tentang perpanjangan penggunaan MemoryBlock
.
Menggunakan jumlah referensi untuk mengelola MemoryBlock
Dalam sebagian besar situasi, cara paling efisien untuk menggunakan MemoryBlock
adalah dengan
alokasikan/dealokasikan. Namun, di aplikasi rumit yang menggunakan jumlah referensi
untuk pembersihan sampah memori
mungkin adalah ide yang lebih baik. Untuk mengaktifkan jumlah referensi
MemoryBlock
, Anda dapat mengikat MemoryBlock
dengan objek binder, yang membantu
menghitung referensi dan membatalkan alokasi MemoryBlock
saat jumlahnya berkurang
ke nol.
Mendeklarasikan HAL
Saat mendeklarasikan HAL, jelaskan struct HIDL yang berisi MemoryBlock
dan IBase:
import android.hidl.memory.block@1.0::MemoryBlock;
struct MemoryBlockAllocation {
MemoryBlock block;
IBase refcnt;
};
Gunakan MemoryBlockAllocation
untuk mengganti MemoryBlock
dan menghapus metode
untuk mengembalikan dana sebesar MemoryBlock
. Paket tersebut dibatalkan alokasinya berdasarkan penghitungan referensi
dengan MemoryBlockAllocation
. Contoh:
interface IFoo {
allocateSome() generates(MemoryBlockAllocation allocation);
};
Mengimplementasikan HAL
Contoh implementasi HAL sisi layanan:
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);
Contoh implementasi HAL sisi klien:
ifoo->allocateSome([&](const MemoryBlockAllocation& allocation){
...
);
Melampirkan dan mengambil metadata
Beberapa aplikasi memerlukan data tambahan untuk mengikat dengan MemoryBlock
yang dialokasikan.
Anda dapat menambahkan dan mengambil metadata menggunakan dua metode:
Jika aplikasi mengakses metadata sesering blok itu sendiri, menambahkan {i>metadata<i} dan meneruskan semuanya dalam sebuah struct. Contoh:
import android.hidl.memory.block@1.0::MemoryBlock; struct MemoryBlockWithMetaData{ MemoryBlock block; MetaDataStruct metaData; };
Jika aplikasi jauh lebih jarang mengakses metadata daripada Namun, akan lebih efisien untuk meneruskan metadata secara pasif dengan dalam antarmuka berbasis web yang sederhana. Contoh:
import android.hidl.memory.block@1.0::MemoryBlock; struct MemoryBlockWithMetaData{ MemoryBlock block; IMetaData metaData; };
Selanjutnya, ikat metadata dengan
MemoryBlock
menggunakanMemoryDealer
. Contoh:MemoryBlockWithMetaData memory_block; memory_block.block = dealer->allocate(size); if(HidlMemoryDealer::isOk(block)){ memory_block.metaData = new MetaData(...);