HIDL MemoryBlock

एचआईडीएल MemoryBlock, hidl_memory, HIDL @1.0::IAllocator, और HIDL @1.0::IMapper पर बनी एक ऐब्स्ट्रैक्ट लेयर है. इसे HIDL सेवाओं के लिए डिज़ाइन किया गया है. इन सेवाओं में एक ही मेमोरी हीप को शेयर करने के लिए, कई मेमोरी ब्लॉक होते हैं.

परफ़ॉर्मेंस में सुधार किए गए

ऐप्लिकेशन में MemoryBlock का इस्तेमाल करने से, mmap/munmap और उपयोगकर्ता स्पेस सेगमेंटेशन फ़ॉल्ट की संख्या में काफ़ी कमी आ सकती है. इससे परफ़ॉर्मेंस बेहतर होती है. उदाहरण के लिए:

  • हर बफ़र के लिए hidl_memory का इस्तेमाल करने पर, हर बफ़र के लिए औसतन 238 माइक्रोसेकंड/1 बंटन का समय लगता है.
  • MemoryBlock का इस्तेमाल करने और एक hidl_memory को शेयर करने पर, हर असाइनमेंट के लिए औसतन 2.82 माइक्रोसेकंड लगते हैं.

भवन निर्माण

HIDL MemoryBlock आर्किटेक्चर में, एक ही मेमोरी हीप को शेयर करने वाले कई मेमोरी ब्लॉक के साथ HIDL सेवाएं शामिल होती हैं:

HIDL MemoryBlock

पहली इमेज. HIDL MemoryBlock आर्किटेक्चर

सामान्य इस्तेमाल

इस सेक्शन में, MemoryBlock का इस्तेमाल करने का उदाहरण दिया गया है. इसमें पहले एचएएल को डिक्लेयर किया गया है. इसके बाद, एचएएल को लागू किया गया है.

एचएएल का एलान करना

IFoo HAL के इस उदाहरण के लिए:

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

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

Android.bp के बारे में यहां बताया गया है:

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

एचएएल लागू करना

उदाहरण के तौर पर दिए गए HAL को लागू करने के लिए:

  1. hidl_memory पाएं. ज़्यादा जानकारी के लिए, 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. हासिल किए गए hidl_memory की मदद से, HidlMemoryDealer इंस्टेंस बनाएं:

    #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. एचआईडीएल के साथ तय किए गए स्ट्रक्चर MemoryBlock को असाइन करें.

    उदाहरण MemoryBlock:

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

    MemoryBlock को असाइन करने के लिए, 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);
        ...
    
  4. MemoryBlock को हटाना:

    Return<void> Foo::giveBack(const MemoryBlock& block) {
        memory_dealer->deallocate(block.offset);
    ...
    
  5. डेटा में बदलाव करना:

    #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. कॉन्फ़िगरेशन Android.bp:

    shared_libs: [
            "android.hidl.memory@1.0",
    
            "android.hidl.memory.block@1.0"
    
            "android.hidl.memory.token@1.0",
            "libhidlbase",
            "libhidlmemory",
    
  7. फ़्लो की समीक्षा करें, ताकि यह पता चल सके कि आपको lockMemory की ज़रूरत है या नहीं.

    आम तौर पर, MemoryBlock शेयर किए गए hidl_memory को बनाए रखने के लिए रेफ़रंस काउंट का इस्तेमाल करता है. इसे पहली बार mmap() किया जाता है, जब इसके MemoryBlock 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` को लॉक के पूरे लाइफ़साइकल के दौरान मैप किया जाता है. उदाहरण:

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

ज़्यादा इस्तेमाल

इस सेक्शन में, MemoryBlock के ज़्यादा इस्तेमाल के बारे में जानकारी दी गई है.

MemoryBlock को मैनेज करने के लिए, रेफ़रंस की संख्या का इस्तेमाल करना

ज़्यादातर मामलों में, MemoryBlock का सबसे सही तरीके से इस्तेमाल करने के लिए, साफ़ तौर पर बंटवारा/अनबंटवारा करें. हालांकि, जटिल ऐप्लिकेशन में गार्बेज कलेक्शन के लिए रेफ़रंस काउंट का इस्तेमाल करना बेहतर हो सकता है. MemoryBlock पर रेफ़रंस की संख्या पाने के लिए, MemoryBlock को बाइंडर ऑब्जेक्ट के साथ बाइंड किया जा सकता है. इससे रेफ़रंस की संख्या को गिनने में मदद मिलती है. साथ ही, जब संख्या घटकर शून्य हो जाती है, तब MemoryBlock को डीऐलोकेट कर दिया जाता है.

एचएएल का एलान करना

HAL का एलान करते समय, एक ऐसे HIDL स्ट्रक्चर के बारे में बताएं जिसमें MemoryBlock instance और IBase शामिल हों:

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

struct MemoryBlockAllocation {
    MemoryBlock block;
    IBase refcnt;
};

MemoryBlockAllocation का इस्तेमाल करके, MemoryBlock को बदलें और MemoryBlock वापस देने के लिए, पेमेंट का तरीका हटाएं. इसे MemoryBlockAllocation के साथ रेफ़रंस काउंटिंग की मदद से डी-एलॉकेट किया जाता है. उदाहरण:

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

एचएएल लागू करना

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);

एचएएल को क्लाइंट साइड पर लागू करने का उदाहरण:

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

मेटाडेटा अटैच करना और उसे वापस पाना

कुछ ऐप्लिकेशन को, असाइन किए गए MemoryBlock से बाइंड करने के लिए अतिरिक्त डेटा की ज़रूरत होती है. मेटाडेटा को जोड़ने और वापस पाने के लिए, इन दो तरीकों का इस्तेमाल किया जा सकता है:

  • अगर ऐप्लिकेशन, ब्लॉक जितनी बार मेटाडेटा ऐक्सेस करता है, तो मेटाडेटा जोड़ें और उन सभी को एक स्ट्रक्चर में पास करें. उदाहरण:

    import android.hidl.memory.block@1.0::MemoryBlock;
    
    struct MemoryBlockWithMetaData{
        MemoryBlock block;
        MetaDataStruct metaData;
    };
    
  • अगर ऐप्लिकेशन, ब्लॉक की तुलना में मेटाडेटा को बहुत कम बार ऐक्सेस करता है, तो इंटरफ़ेस के साथ मेटाडेटा को पैसिव तरीके से पास करना ज़्यादा असरदार होता है. उदाहरण:

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

    इसके बाद, MemoryDealer का इस्तेमाल करके, मेटाडेटा को MemoryBlock से बाइंड करें. उदाहरण:

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