Home | History | Annotate | Download | only in libhidlcache
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "HidlMemoryCache"
     18 #include "HidlMemoryCache.h"
     19 #include <android/hidl/memory/1.0/IMemory.h>
     20 #include <android/hidl/memory/token/1.0/IMemoryToken.h>
     21 #include <hidlmemory/mapping.h>
     22 #include <sys/mman.h>
     23 #include <utils/Log.h>
     24 
     25 namespace android {
     26 namespace hardware {
     27 
     28 using IMemoryToken = ::android::hidl::memory::token::V1_0::IMemoryToken;
     29 using IMemory = ::android::hidl::memory::V1_0::IMemory;
     30 
     31 class IMemoryDecorator : public virtual IMemory {
     32    public:
     33     IMemoryDecorator(sp<IMemory> heap) : mHeap(heap) {}
     34     virtual ~IMemoryDecorator(){};
     35     Return<void> update() override { return mHeap->update(); }
     36     Return<void> read() override { return mHeap->read(); };
     37     Return<void> updateRange(uint64_t start, uint64_t length) override {
     38         return mHeap->updateRange(start, length);
     39     }
     40     Return<void> readRange(uint64_t start, uint64_t length) override {
     41         return mHeap->readRange(start, length);
     42     }
     43     Return<void> commit() override { return mHeap->commit(); }
     44 
     45     Return<void*> getPointer() override { return mHeap->getPointer(); }
     46     Return<uint64_t> getSize() override { return mHeap->getSize(); }
     47 
     48    protected:
     49     sp<IMemory> mHeap;
     50 };
     51 
     52 class IMemoryCacheable : public virtual IMemoryDecorator {
     53    public:
     54     IMemoryCacheable(sp<IMemory> heap, sp<IMemoryToken> key) : IMemoryDecorator(heap), mKey(key) {}
     55     virtual ~IMemoryCacheable() { HidlMemoryCache::getInstance()->flush(mKey); }
     56 
     57    protected:
     58     sp<IMemoryToken> mKey;
     59 };
     60 
     61 class IMemoryBlock : public virtual IMemoryDecorator {
     62    public:
     63     IMemoryBlock(sp<IMemory> heap, uint64_t size, uint64_t offset)
     64         : IMemoryDecorator(heap), mSize(size), mOffset(offset), mHeapSize(heap->getSize()) {}
     65     bool validRange(uint64_t start, uint64_t length) {
     66         return (start + length < mSize) && (start + length >= start) &&
     67                (mOffset + mSize < mHeapSize);
     68     }
     69     Return<void> readRange(uint64_t start, uint64_t length) {
     70         if (!validRange(start, length)) {
     71             ALOGE("IMemoryBlock::readRange: out of range");
     72             Status status;
     73             status.setException(Status::EX_ILLEGAL_ARGUMENT, "out of range");
     74             return Return<void>(status);
     75         }
     76         return mHeap->readRange(mOffset + start, length);
     77     }
     78     Return<void> updateRange(uint64_t start, uint64_t length) override {
     79         if (!validRange(start, length)) {
     80             ALOGE("IMemoryBlock::updateRange: out of range");
     81             return Void();
     82         }
     83         return mHeap->updateRange(mOffset + start, length);
     84     }
     85     Return<uint64_t> getSize() override { return mSize; }
     86     Return<void*> getPointer() override {
     87         void* p = mHeap->getPointer();
     88         return (static_cast<char*>(p) + mOffset);
     89     }
     90 
     91    protected:
     92     uint64_t mSize;
     93     uint64_t mOffset;
     94     uint64_t mHeapSize;
     95 };
     96 
     97 sp<HidlMemoryCache> HidlMemoryCache::getInstance() {
     98     static sp<HidlMemoryCache> instance = new HidlMemoryCache();
     99     return instance;
    100 }
    101 
    102 sp<IMemory> HidlMemoryCache::fillLocked(const sp<IMemoryToken>& key) {
    103     sp<IMemory> memory = nullptr;
    104     Return<void> ret = key->get(
    105         [&](const hidl_memory& mem) { memory = new IMemoryCacheable(mapMemory(mem), key); });
    106     if (!ret.isOk()) {
    107         ALOGE("HidlMemoryCache::fill: cannot IMemoryToken::get.");
    108         return nullptr;
    109     }
    110     mCached[key] = memory;
    111     return memory;
    112 }
    113 
    114 sp<IMemory> HidlMemoryCache::map(const MemoryBlock& memblk) {
    115     sp<IMemoryToken> token = memblk.token;
    116     sp<IMemory> heap = fetch(token);
    117     if (heap == nullptr) {
    118         return nullptr;
    119     }
    120     return new IMemoryBlock(heap, memblk.size, memblk.offset);
    121 }
    122 
    123 }  // namespace hardware
    124 }  // namespace android
    125