/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "HidlMemoryCache" #include "HidlMemoryCache.h" #include #include #include #include #include namespace android { namespace hardware { using IMemoryToken = ::android::hidl::memory::token::V1_0::IMemoryToken; using IMemory = ::android::hidl::memory::V1_0::IMemory; class MemoryDecorator : public virtual IMemory { public: MemoryDecorator(const sp& heap) : mHeap(heap) {} virtual ~MemoryDecorator() {} Return update() override { return mHeap->update(); } Return read() override { return mHeap->read(); } Return updateRange(uint64_t start, uint64_t length) override { return mHeap->updateRange(start, length); } Return readRange(uint64_t start, uint64_t length) override { return mHeap->readRange(start, length); } Return commit() override { return mHeap->commit(); } Return getPointer() override { return mHeap->getPointer(); } Return getSize() override { return mHeap->getSize(); } protected: sp mHeap; }; class MemoryCacheable : public virtual MemoryDecorator { public: MemoryCacheable(const sp& heap, sp key) : MemoryDecorator(heap), mKey(key) {} virtual ~MemoryCacheable() { HidlMemoryCache::getInstance()->flush(mKey); } protected: sp mKey; }; class MemoryBlockImpl : public virtual IMemory { public: MemoryBlockImpl(const sp& heap, uint64_t size, uint64_t offset) : mHeap(heap), mSize(size), mOffset(offset), mHeapSize(heap->getSize()) {} bool validRange(uint64_t start, uint64_t length) { return (start + length <= mSize) && (start + length >= start) && (mOffset + mSize <= mHeapSize); } Return readRange(uint64_t start, uint64_t length) override { if (!validRange(start, length)) { ALOGE("IMemoryBlock::readRange: out of range"); return Void(); } return mHeap->readRange(mOffset + start, length); } Return updateRange(uint64_t start, uint64_t length) override { if (!validRange(start, length)) { ALOGE("IMemoryBlock::updateRange: out of range"); return Void(); } return mHeap->updateRange(mOffset + start, length); } Return read() override { return this->readRange(0, mSize); } Return update() override { return this->updateRange(0, mSize); } Return commit() override { return mHeap->commit(); } Return getSize() override { return mSize; } Return getPointer() override { void* p = mHeap->getPointer(); return (static_cast(p) + mOffset); } protected: sp mHeap; uint64_t mSize; uint64_t mOffset; uint64_t mHeapSize; }; sp HidlMemoryCache::getInstance() { static sp instance = new HidlMemoryCache(); return instance; } sp HidlMemoryCache::fillLocked(const sp& key) { sp memory = nullptr; Return ret = key->get( [&](const hidl_memory& mem) { memory = new MemoryCacheable(mapMemory(mem), key); }); if (!ret.isOk()) { ALOGE("HidlMemoryCache::fill: cannot IMemoryToken::get."); return nullptr; } mCached[key] = memory; return memory; } sp HidlMemoryCache::map(const MemoryBlock& memblk) { sp token = memblk.token; sp heap = fetch(token); if (heap == nullptr) { return nullptr; } return new MemoryBlockImpl(heap, memblk.size, memblk.offset); } } // namespace hardware } // namespace android