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
34namespace android {
35namespace hardware {
36namespace graphics {
37namespace mapper {
38namespace V2_0 {
39namespace passthrough {
40
41class GrallocImportedBufferPool {
42   public:
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
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
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
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
84template <typename T>
85class GrallocMapper : public T {
86   protected:
87    void* addImportedBuffer(native_handle_t* bufferHandle) override {
88        return GrallocImportedBufferPool::getInstance().add(bufferHandle);
89    }
90
91    native_handle_t* removeImportedBuffer(void* buffer) override {
92        return GrallocImportedBufferPool::getInstance().remove(buffer);
93    }
94
95    const native_handle_t* getImportedBuffer(void* buffer) const override {
96        return GrallocImportedBufferPool::getInstance().get(buffer);
97    }
98};
99
100class GrallocLoader {
101   public:
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
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
127    static int getModuleMajorApiVersion(const hw_module_t* module) {
128        return (module->module_api_version >> 8) & 0xff;
129    }
130
131    // create a MapperHal instance
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
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