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