blob: a23c38838dcfbf1c0270e19c9816e072a4d7ce6c [file] [log] [blame]
Howard Chen4904f962017-12-08 18:11:05 +08001/*
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
25namespace android {
26namespace hardware {
27
28using IMemoryToken = ::android::hidl::memory::token::V1_0::IMemoryToken;
29using IMemory = ::android::hidl::memory::V1_0::IMemory;
30
Howard Chene79b60e2018-07-31 16:16:26 +080031class MemoryDecorator : public virtual IMemory {
Howard Chen4904f962017-12-08 18:11:05 +080032 public:
Howard Chene79b60e2018-07-31 16:16:26 +080033 MemoryDecorator(const sp<IMemory>& heap) : mHeap(heap) {}
34 virtual ~MemoryDecorator() {}
Howard Chen4904f962017-12-08 18:11:05 +080035 Return<void> update() override { return mHeap->update(); }
Bernhard Rosenkränzer0c28fd22018-06-04 16:01:47 +020036 Return<void> read() override { return mHeap->read(); }
Howard Chen4904f962017-12-08 18:11:05 +080037 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
Howard Chene79b60e2018-07-31 16:16:26 +080052class MemoryCacheable : public virtual MemoryDecorator {
Howard Chen4904f962017-12-08 18:11:05 +080053 public:
Howard Chene79b60e2018-07-31 16:16:26 +080054 MemoryCacheable(const sp<IMemory>& heap, sp<IMemoryToken> key)
55 : MemoryDecorator(heap), mKey(key) {}
56 virtual ~MemoryCacheable() { HidlMemoryCache::getInstance()->flush(mKey); }
Howard Chen4904f962017-12-08 18:11:05 +080057
58 protected:
59 sp<IMemoryToken> mKey;
60};
61
Howard Chene79b60e2018-07-31 16:16:26 +080062class MemoryBlockImpl : public virtual IMemory {
Howard Chen4904f962017-12-08 18:11:05 +080063 public:
Howard Chene79b60e2018-07-31 16:16:26 +080064 MemoryBlockImpl(const sp<IMemory>& heap, uint64_t size, uint64_t offset)
65 : mHeap(heap), mSize(size), mOffset(offset), mHeapSize(heap->getSize()) {}
Howard Chen4904f962017-12-08 18:11:05 +080066 bool validRange(uint64_t start, uint64_t length) {
Howard Chene79b60e2018-07-31 16:16:26 +080067 return (start + length <= mSize) && (start + length >= start) &&
68 (mOffset + mSize <= mHeapSize);
Howard Chen4904f962017-12-08 18:11:05 +080069 }
Howard Chene79b60e2018-07-31 16:16:26 +080070 Return<void> readRange(uint64_t start, uint64_t length) override {
Howard Chen4904f962017-12-08 18:11:05 +080071 if (!validRange(start, length)) {
72 ALOGE("IMemoryBlock::readRange: out of range");
Howard Chene79b60e2018-07-31 16:16:26 +080073 return Void();
Howard Chen4904f962017-12-08 18:11:05 +080074 }
75 return mHeap->readRange(mOffset + start, length);
76 }
77 Return<void> updateRange(uint64_t start, uint64_t length) override {
78 if (!validRange(start, length)) {
79 ALOGE("IMemoryBlock::updateRange: out of range");
80 return Void();
81 }
82 return mHeap->updateRange(mOffset + start, length);
83 }
Howard Chene79b60e2018-07-31 16:16:26 +080084 Return<void> read() override { return this->readRange(0, mSize); }
85 Return<void> update() override { return this->updateRange(0, mSize); }
86 Return<void> commit() override { return mHeap->commit(); }
Howard Chen4904f962017-12-08 18:11:05 +080087 Return<uint64_t> getSize() override { return mSize; }
88 Return<void*> getPointer() override {
89 void* p = mHeap->getPointer();
90 return (static_cast<char*>(p) + mOffset);
91 }
92
93 protected:
Howard Chene79b60e2018-07-31 16:16:26 +080094 sp<IMemory> mHeap;
Howard Chen4904f962017-12-08 18:11:05 +080095 uint64_t mSize;
96 uint64_t mOffset;
97 uint64_t mHeapSize;
98};
99
100sp<HidlMemoryCache> HidlMemoryCache::getInstance() {
101 static sp<HidlMemoryCache> instance = new HidlMemoryCache();
102 return instance;
103}
104
105sp<IMemory> HidlMemoryCache::fillLocked(const sp<IMemoryToken>& key) {
106 sp<IMemory> memory = nullptr;
107 Return<void> ret = key->get(
Howard Chene79b60e2018-07-31 16:16:26 +0800108 [&](const hidl_memory& mem) { memory = new MemoryCacheable(mapMemory(mem), key); });
Howard Chen4904f962017-12-08 18:11:05 +0800109 if (!ret.isOk()) {
110 ALOGE("HidlMemoryCache::fill: cannot IMemoryToken::get.");
111 return nullptr;
112 }
113 mCached[key] = memory;
114 return memory;
115}
116
117sp<IMemory> HidlMemoryCache::map(const MemoryBlock& memblk) {
118 sp<IMemoryToken> token = memblk.token;
119 sp<IMemory> heap = fetch(token);
120 if (heap == nullptr) {
121 return nullptr;
122 }
Howard Chene79b60e2018-07-31 16:16:26 +0800123 return new MemoryBlockImpl(heap, memblk.size, memblk.offset);
Howard Chen4904f962017-12-08 18:11:05 +0800124}
125
126} // namespace hardware
127} // namespace android