HIDL MemoryBlock

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

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

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

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

वास्तुकला

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

HIDL MemoryBlock

पहली इमेज. एचआईडीएल 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",
        ...
};

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

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

  1. hidl_memory पाएं. ज़्यादा जानकारी के लिए, एचआईडीएल 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()-ed किया जाता है, जब इसके 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` इंस्टेंस में से किसी एक को मैप किया जाता है. साथ ही, जब कोई भी इसे रेफ़र नहीं करता, तब इसे `munmap()` किया जाता है. `hidl_memory` को हमेशा मैप करने के लिए, `lockMemory` का इस्तेमाल किया जा सकता है. यह आरएआईआई स्टाइल वाला एक ऑब्जेक्ट है, जो लॉक lifecycle के दौरान, इससे जुड़ी `hidl_memory` को मैप करके रखता है. उदाहरण:

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

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

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

`MemoryBlock` को मैनेज करने के लिए रेफ़रंस काउंट का इस्तेमाल करना

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

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

एचएएल का एलान करते समय, एचआईडीएल स्ट्रक्चर के बारे में बताएं. इसमें MemoryBlock इंस्टेंस और IBase शामिल होता है:

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

struct MemoryBlockAllocation {
    MemoryBlock block;
    IBase refcnt;
};

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

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

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

सेवा की ओर से, एचएएल को लागू करने का उदाहरण:

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