1 /*
2  * Copyright 2017 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 #pragma once
18 
19 #ifndef LOG_TAG
20 #warning "GrallocLoader.h included without LOG_TAG"
21 #endif
22 
23 #include <memory>
24 #include <mutex>
25 #include <unordered_set>
26 
27 #include <hardware/gralloc.h>
28 #include <hardware/hardware.h>
29 #include <log/log.h>
30 #include <mapper-hal/2.0/Mapper.h>
31 #include <mapper-passthrough/2.0/Gralloc0Hal.h>
32 #include <mapper-passthrough/2.0/Gralloc1Hal.h>
33 
34 namespace android {
35 namespace hardware {
36 namespace graphics {
37 namespace mapper {
38 namespace V2_0 {
39 namespace passthrough {
40 
41 class GrallocImportedBufferPool {
42    public:
getInstance()43     static GrallocImportedBufferPool& getInstance() {
44         // GraphicBufferMapper in framework is expected to be valid (and
45         // leaked) during process termination.  We need to make sure IMapper,
46         // and in turn, GrallocImportedBufferPool is valid as well.  Create
47         // imported buffer pool on the heap (and let it leak) for the purpose.
48         // Besides, all IMapper instances must share the same pool.  Make it a
49         // singleton.
50         //
51         // However, there is no way to make sure gralloc0/gralloc1 are valid
52         // during process termination.  Any use of static/global object in
53         // gralloc0/gralloc1 that may be destructed during process termination
54         // is potentially broken.
55         static GrallocImportedBufferPool* singleton = new GrallocImportedBufferPool;
56         return *singleton;
57     }
58 
getMutex()59     std::mutex* getMutex() { return &mMutex; }
60 
add(native_handle_t * bufferHandle)61     void* add(native_handle_t* bufferHandle) {
62         std::lock_guard<std::mutex> lock(mMutex);
63         return mBufferHandles.insert(bufferHandle).second ? bufferHandle : nullptr;
64     }
65 
removeLocked(native_handle * bufferHandle)66     void removeLocked(native_handle* bufferHandle) { mBufferHandles.erase(bufferHandle); }
67 
get(void * buffer)68     native_handle_t* get(void* buffer) {
69         auto bufferHandle = static_cast<native_handle_t*>(buffer);
70 
71         std::lock_guard<std::mutex> lock(mMutex);
72         return mBufferHandles.count(bufferHandle) == 1 ? bufferHandle : nullptr;
73     }
74 
getConst(void * buffer)75     const native_handle_t* getConst(void* buffer) {
76         auto bufferHandle = static_cast<const native_handle_t*>(buffer);
77 
78         std::lock_guard<std::mutex> lock(mMutex);
79         return mBufferHandles.count(bufferHandle) == 1 ? bufferHandle : nullptr;
80     }
81 
82    private:
83     std::mutex mMutex;
84     std::unordered_set<const native_handle_t*> mBufferHandles;
85 };
86 
87 // Inherit from V2_*::hal::Mapper and override imported buffer management functions
88 template <typename T>
89 class GrallocMapper : public T {
90    protected:
addImportedBuffer(native_handle_t * bufferHandle)91     void* addImportedBuffer(native_handle_t* bufferHandle) override {
92         return GrallocImportedBufferPool::getInstance().add(bufferHandle);
93     }
94 
freeImportedBuffer(native_handle_t * bufferHandle)95     Error freeImportedBuffer(native_handle_t* bufferHandle) override {
96         std::lock_guard<std::mutex> lock(*GrallocImportedBufferPool::getInstance().getMutex());
97         Error error = this->mHal->freeBuffer(bufferHandle);
98         if (error == Error::NONE) {
99             GrallocImportedBufferPool::getInstance().removeLocked(bufferHandle);
100         }
101         return error;
102     }
103 
getImportedBuffer(void * buffer)104     native_handle_t* getImportedBuffer(void* buffer) const override {
105         return GrallocImportedBufferPool::getInstance().get(buffer);
106     }
107 
getConstImportedBuffer(void * buffer)108     const native_handle_t* getConstImportedBuffer(void* buffer) const override {
109         return GrallocImportedBufferPool::getInstance().getConst(buffer);
110     }
111 };
112 
113 class GrallocLoader {
114    public:
load()115     static IMapper* load() {
116         const hw_module_t* module = loadModule();
117         if (!module) {
118             return nullptr;
119         }
120         auto hal = createHal(module);
121         if (!hal) {
122             return nullptr;
123         }
124         return createMapper(std::move(hal));
125     }
126 
127     // load the gralloc module
loadModule()128     static const hw_module_t* loadModule() {
129         const hw_module_t* module;
130         int error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
131         if (error) {
132             ALOGE("failed to get gralloc module");
133             return nullptr;
134         }
135 
136         return module;
137     }
138 
139     // return the major api version of the module
getModuleMajorApiVersion(const hw_module_t * module)140     static int getModuleMajorApiVersion(const hw_module_t* module) {
141         return (module->module_api_version >> 8) & 0xff;
142     }
143 
144     // create a MapperHal instance
createHal(const hw_module_t * module)145     static std::unique_ptr<hal::MapperHal> createHal(const hw_module_t* module) {
146         int major = getModuleMajorApiVersion(module);
147         switch (major) {
148             case 1: {
149                 auto hal = std::make_unique<Gralloc1Hal>();
150                 return hal->initWithModule(module) ? std::move(hal) : nullptr;
151             }
152             case 0: {
153                 auto hal = std::make_unique<Gralloc0Hal>();
154                 return hal->initWithModule(module) ? std::move(hal) : nullptr;
155             }
156             default:
157                 ALOGE("unknown gralloc module major version %d", major);
158                 return nullptr;
159         }
160     }
161 
162     // create an IAllocator instance
createMapper(std::unique_ptr<hal::MapperHal> hal)163     static IMapper* createMapper(std::unique_ptr<hal::MapperHal> hal) {
164         auto mapper = std::make_unique<GrallocMapper<hal::Mapper>>();
165         return mapper->init(std::move(hal)) ? mapper.release() : nullptr;
166     }
167 };
168 
169 }  // namespace passthrough
170 }  // namespace V2_0
171 }  // namespace mapper
172 }  // namespace graphics
173 }  // namespace hardware
174 }  // namespace android
175