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 add(native_handle_t * bufferHandle)59 void* add(native_handle_t* bufferHandle) { 60 std::lock_guard<std::mutex> lock(mMutex); 61 return mBufferHandles.insert(bufferHandle).second ? bufferHandle : nullptr; 62 } 63 remove(void * buffer)64 native_handle_t* remove(void* buffer) { 65 auto bufferHandle = static_cast<native_handle_t*>(buffer); 66 67 std::lock_guard<std::mutex> lock(mMutex); 68 return mBufferHandles.erase(bufferHandle) == 1 ? bufferHandle : nullptr; 69 } 70 get(void * buffer)71 const native_handle_t* get(void* buffer) { 72 auto bufferHandle = static_cast<const native_handle_t*>(buffer); 73 74 std::lock_guard<std::mutex> lock(mMutex); 75 return mBufferHandles.count(bufferHandle) == 1 ? bufferHandle : nullptr; 76 } 77 78 private: 79 std::mutex mMutex; 80 std::unordered_set<const native_handle_t*> mBufferHandles; 81 }; 82 83 // Inherit from V2_*::hal::Mapper and override imported buffer management functions 84 template <typename T> 85 class GrallocMapper : public T { 86 protected: addImportedBuffer(native_handle_t * bufferHandle)87 void* addImportedBuffer(native_handle_t* bufferHandle) override { 88 return GrallocImportedBufferPool::getInstance().add(bufferHandle); 89 } 90 removeImportedBuffer(void * buffer)91 native_handle_t* removeImportedBuffer(void* buffer) override { 92 return GrallocImportedBufferPool::getInstance().remove(buffer); 93 } 94 getImportedBuffer(void * buffer)95 const native_handle_t* getImportedBuffer(void* buffer) const override { 96 return GrallocImportedBufferPool::getInstance().get(buffer); 97 } 98 }; 99 100 class GrallocLoader { 101 public: load()102 static IMapper* load() { 103 const hw_module_t* module = loadModule(); 104 if (!module) { 105 return nullptr; 106 } 107 auto hal = createHal(module); 108 if (!hal) { 109 return nullptr; 110 } 111 return createMapper(std::move(hal)); 112 } 113 114 // load the gralloc module loadModule()115 static const hw_module_t* loadModule() { 116 const hw_module_t* module; 117 int error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); 118 if (error) { 119 ALOGE("failed to get gralloc module"); 120 return nullptr; 121 } 122 123 return module; 124 } 125 126 // return the major api version of the module getModuleMajorApiVersion(const hw_module_t * module)127 static int getModuleMajorApiVersion(const hw_module_t* module) { 128 return (module->module_api_version >> 8) & 0xff; 129 } 130 131 // create a MapperHal instance createHal(const hw_module_t * module)132 static std::unique_ptr<hal::MapperHal> createHal(const hw_module_t* module) { 133 int major = getModuleMajorApiVersion(module); 134 switch (major) { 135 case 1: { 136 auto hal = std::make_unique<Gralloc1Hal>(); 137 return hal->initWithModule(module) ? std::move(hal) : nullptr; 138 } 139 case 0: { 140 auto hal = std::make_unique<Gralloc0Hal>(); 141 return hal->initWithModule(module) ? std::move(hal) : nullptr; 142 } 143 default: 144 ALOGE("unknown gralloc module major version %d", major); 145 return nullptr; 146 } 147 } 148 149 // create an IAllocator instance createMapper(std::unique_ptr<hal::MapperHal> hal)150 static IMapper* createMapper(std::unique_ptr<hal::MapperHal> hal) { 151 auto mapper = std::make_unique<GrallocMapper<hal::Mapper>>(); 152 return mapper->init(std::move(hal)) ? mapper.release() : nullptr; 153 } 154 }; 155 156 } // namespace passthrough 157 } // namespace V2_0 158 } // namespace mapper 159 } // namespace graphics 160 } // namespace hardware 161 } // namespace android 162