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