blob: 85a91c3adada661077be3676dfda62a5b179ff3a [file] [log] [blame]
/*
* Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#ifndef LOG_TAG
#warning "GrallocLoader.h included without LOG_TAG"
#endif
#include <memory>
#include <mutex>
#include <unordered_set>
#include <hardware/gralloc.h>
#include <hardware/hardware.h>
#include <log/log.h>
#include <mapper-hal/2.0/Mapper.h>
#include <mapper-passthrough/2.0/Gralloc0Hal.h>
#include <mapper-passthrough/2.0/Gralloc1Hal.h>
namespace android {
namespace hardware {
namespace graphics {
namespace mapper {
namespace V2_0 {
namespace passthrough {
class GrallocImportedBufferPool {
public:
static GrallocImportedBufferPool& getInstance() {
// GraphicBufferMapper in framework is expected to be valid (and
// leaked) during process termination. We need to make sure IMapper,
// and in turn, GrallocImportedBufferPool is valid as well. Create
// imported buffer pool on the heap (and let it leak) for the purpose.
// Besides, all IMapper instances must share the same pool. Make it a
// singleton.
//
// However, there is no way to make sure gralloc0/gralloc1 are valid
// during process termination. Any use of static/global object in
// gralloc0/gralloc1 that may be destructed during process termination
// is potentially broken.
static GrallocImportedBufferPool* singleton = new GrallocImportedBufferPool;
return *singleton;
}
void* add(native_handle_t* bufferHandle) {
std::lock_guard<std::mutex> lock(mMutex);
return mBufferHandles.insert(bufferHandle).second ? bufferHandle : nullptr;
}
native_handle_t* remove(void* buffer) {
auto bufferHandle = static_cast<native_handle_t*>(buffer);
std::lock_guard<std::mutex> lock(mMutex);
return mBufferHandles.erase(bufferHandle) == 1 ? bufferHandle : nullptr;
}
native_handle_t* get(void* buffer) {
auto bufferHandle = static_cast<native_handle_t*>(buffer);
std::lock_guard<std::mutex> lock(mMutex);
return mBufferHandles.count(bufferHandle) == 1 ? bufferHandle : nullptr;
}
const native_handle_t* getConst(void* buffer) {
auto bufferHandle = static_cast<const native_handle_t*>(buffer);
std::lock_guard<std::mutex> lock(mMutex);
return mBufferHandles.count(bufferHandle) == 1 ? bufferHandle : nullptr;
}
private:
std::mutex mMutex;
std::unordered_set<const native_handle_t*> mBufferHandles;
};
// Inherit from V2_*::hal::Mapper and override imported buffer management functions
template <typename T>
class GrallocMapper : public T {
protected:
void* addImportedBuffer(native_handle_t* bufferHandle) override {
return GrallocImportedBufferPool::getInstance().add(bufferHandle);
}
native_handle_t* removeImportedBuffer(void* buffer) override {
return GrallocImportedBufferPool::getInstance().remove(buffer);
}
native_handle_t* getImportedBuffer(void* buffer) const override {
return GrallocImportedBufferPool::getInstance().get(buffer);
}
const native_handle_t* getConstImportedBuffer(void* buffer) const override {
return GrallocImportedBufferPool::getInstance().getConst(buffer);
}
};
class GrallocLoader {
public:
static IMapper* load() {
const hw_module_t* module = loadModule();
if (!module) {
return nullptr;
}
auto hal = createHal(module);
if (!hal) {
return nullptr;
}
return createMapper(std::move(hal));
}
// load the gralloc module
static const hw_module_t* loadModule() {
const hw_module_t* module;
int error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
if (error) {
ALOGE("failed to get gralloc module");
return nullptr;
}
return module;
}
// return the major api version of the module
static int getModuleMajorApiVersion(const hw_module_t* module) {
return (module->module_api_version >> 8) & 0xff;
}
// create a MapperHal instance
static std::unique_ptr<hal::MapperHal> createHal(const hw_module_t* module) {
int major = getModuleMajorApiVersion(module);
switch (major) {
case 1: {
auto hal = std::make_unique<Gralloc1Hal>();
return hal->initWithModule(module) ? std::move(hal) : nullptr;
}
case 0: {
auto hal = std::make_unique<Gralloc0Hal>();
return hal->initWithModule(module) ? std::move(hal) : nullptr;
}
default:
ALOGE("unknown gralloc module major version %d", major);
return nullptr;
}
}
// create an IAllocator instance
static IMapper* createMapper(std::unique_ptr<hal::MapperHal> hal) {
auto mapper = std::make_unique<GrallocMapper<hal::Mapper>>();
return mapper->init(std::move(hal)) ? mapper.release() : nullptr;
}
};
} // namespace passthrough
} // namespace V2_0
} // namespace mapper
} // namespace graphics
} // namespace hardware
} // namespace android