Allocator

整体

Allocator是干什么的

Gralloc 是申请和释放内存的模块,由硬件驱动提供实现,为BufferQueue机制提供了基础,且分配的图形Buffer是进程间共享的。Gralloc分为两部分:内存申请allocator(AllocMem) 和 其它内存接口mapper(FreeMem、Mamp、UnMap等)。其中内存申请接口(AllocMem)设计为跨进程调用,实现进程隔离,满足安全要求;而其余内存映射等接口则为Passthrough方式,因为Map、free等接口涉及访问的内核节点安全权限要求低,甚至不涉及内核节点,而且Map接口返回的是虚拟地址,无法跨进程调用,所以此类接口设计为Passthrough模式。

上层是怎么与 Allocator 对接的

流程图

img

说明

Stub 跟 Proxy 是一对,俗称“代理-桩”,一般用在远程方法调用。
Proxy 相当于是拿在手里的遥控器,而 Stub 相当于长在电视机里的遥控接收器,它们有着一一对应的接口方法,但操作的方向刚好相反。
Proxy 的接口供客户端程序调用,然后它内部会把信息包装好,以某种方式(比如 RMI)传递给 Stub,而后者通过对应的接口作用于服务端系统,从而完成了“远程调用”。
一般不同进程间通信的时候都会用到这种模式。

Stub(存根)

定义:Stub是服务端的接口实现,继承自IBinder接口。它代表了服务端暴露给客户端调用的接口。
功能:Stub负责接收来自客户端的请求,通过onTransact方法处理客户端的调用请求。在这个方法中,Stub会根据不同的请求码(code)执行对应的服务逻辑,并通过Parcel对象传递参数和返回值。
生成:通常,使用IDL(Interface Definition Language)文件定义接口时,编译器会自动为服务端生成Stub类的实现。

Proxy(代理)

定义:Proxy是客户端侧的Stub的本地代理,同样继承自IBinder接口。它是Stub的一个远程代理对象,使得客户端可以像调用本地对象一样调用远程服务的方法。
功能:当客户端调用Proxy上的方法时,Proxy会将调用序列化(通过Parcel对象),然后通过Binder驱动发送到服务端。同时,Proxy还会监听来自服务端的返回结果,并将其反序列化后返回给客户端。
生成:同样,使用IDL定义接口时,编译器也会为客户端自动生成一个Proxy类

接口流程梳理

img

Allocator (AllocMem)

内存申请接口只在requestbuffer时用到了,下面通过requestbuffer流程来看下它是如何使用的

1.应用创建RT进程,Render中调用 ProcessRootRenderNode,申请buffer(rsSurface->RequestFrame)

void RSRenderThreadVisitor::ProcessRootRenderNode(RSRootRenderNode& node)
{
    ...
#ifdef ROSEN_OHOS
    auto surfaceFrame = rsSurface->RequestFrame(bufferWidth, bufferHeight, uiTimestamp_);
#else
    auto surfaceFrame = rsSurface->RequestFrame(std::round(bufferWidth), std::round(bufferHeight), uiTimestamp_);
#endif
    ...
}

2. 上层跳转到 bufferquene 的 RequestBuffer 接口

GSError BufferQueueProducer::RequestBuffer(const BufferRequestConfig &config, sptr<BufferExtraData> &bedata,
                                           RequestBufferReturnValue &retval)
{
    ...
    return bufferQueue_->RequestBuffer(config, bedata, retval);
}

3. bufferquene 调用到 SurfaceBufferImpl 中

GSError BufferQueue::AllocBuffer(sptr<SurfaceBuffer> &buffer,
    const BufferRequestConfig &config)
{
    ScopedBytrace func(__func__);
    sptr<SurfaceBuffer> bufferImpl = new SurfaceBufferImpl();
    uint32_t sequence = bufferImpl->GetSeqNum();

    BufferRequestConfig updateConfig = config;
    updateConfig.usage |= defaultUsage;

    GSError ret = bufferImpl->Alloc(updateConfig);
    if (ret != GSERROR_OK) {
        BLOGN_FAILURE_ID_API(sequence, Alloc, ret);
        return ret;
    }

    ...
}

4. SurfaceBufferImpl 初始化 GetDisPlayBuffer

GSError SurfaceBufferImpl::Alloc(const BufferRequestConfig &config)
{
    ...

    BufferHandle *handle = nullptr;
    OHOS::HDI::Display::Buffer::V1_0::AllocInfo info = {config.width, config.height, config.usage, config.format};
    auto dret = g_displayBuffer->AllocMem(info, handle);
    ...
}

5.g_displayBuffer通过 IDisplayBuffer *Get()初始化


IDisplayBufferSptr GetDisplayBufferLocked()
{
    ...
    g_displayBuffer.reset(OHOS::HDI::Display::Buffer::V1_2::IDisplayBuffer::Get());
    ...
}

// drivers/interface/display/buffer/v1_1/hdi_impl/display_buffer_hdi_impl.cpp
namespace OHOS {
namespace HDI {
namespace Display {
namespace Buffer {
namespace V1_1 {
using namespace OHOS::HDI::Display::Buffer::V1_1;
IDisplayBuffer *IDisplayBuffer::Get()
{
    IDisplayBuffer *instance = new V1_1::HdiDisplayBufferImpl();
    if (instance == nullptr) {
        return nullptr;
    }
    return instance;
}

} // namespace V1_1
} // namespace Buffer
} // namespace Display
} // namespace HDI
} // namespace OHOS

6.IDisplayBuffer *Get() 初始化了一个HdiDisplayBufferImpl类实例

namespace OHOS {
namespace HDI {
namespace Display {
namespace Buffer {
namespace V1_1 {
template<typename Interface>
class DisplayBufferHdiImpl : public V1_0::DisplayBufferHdiImpl<Interface> {
public:
    ...
private:
    using BaseType1_0 = V1_0::DisplayBufferHdiImpl<Interface>;
    using BaseType1_0::WAIT_TIME_INTERVAL;
protected:
    sptr<IMetadata> metadata_;
};
using HdiDisplayBufferImpl = DisplayBufferHdiImpl<V1_1::IDisplayBuffer>;
} // namespace V1_1
} // namespace Buffer
} // namespace Display
} // namespace HDI
} // namespace OHOS

#endif // OHOS_HDI_DISPLAY_V1_1_DISPLAY_BUFFER_HDI_IMPL_H

7. DisplayBufferHdiImpl 中的alloca接口,其中allocator_的IAllocator类通过IDL文件编译生成的


class DisplayBufferHdiImpl : public Interface {
public:
    explicit DisplayBufferHdiImpl(bool isAllocLocal = false) : allocator_(nullptr),
        mapper_(nullptr), recipient_(nullptr)
    {
        while ((allocator_ = IAllocator::Get(isAllocLocal)) == nullptr) {
            // Waiting for allocator service ready
            usleep(WAIT_TIME_INTERVAL);
        }
        while ((mapper_ = IMapper::Get(true)) == nullptr) {
            // Waiting for mapper IF ready
            usleep(WAIT_TIME_INTERVAL);
        }
    }


int32_t AllocMem(const AllocInfo& info, BufferHandle*& handle) const override
{
    CHECK_NULLPOINTER_RETURN_VALUE(allocator_, HDF_FAILURE);
    sptr<NativeBuffer> hdiBuffer;
    int32_t ret = allocator_->AllocMem(info, hdiBuffer);
    if ((ret == HDF_SUCCESS) && (hdiBuffer != nullptr)) {
        handle = hdiBuffer->Move();
    } else {
        handle = nullptr;
        if (ret == HDF_SUCCESS) {
            ret = HDF_FAILURE;
        }
        HDF_LOGE("%{public}s: AllocMem error", __func__);
    }
    return ret;
}

8. IAllocator 类的构成

class IAllocator : public HdiBase {
public:
    DECLARE_HDI_DESCRIPTOR(u"ohos.hdi.display.buffer.v1_0.IAllocator");

    virtual ~IAllocator() = default;

    static sptr<OHOS::HDI::Display::Buffer::V1_0::IAllocator> Get(bool isStub = false);
    static sptr<OHOS::HDI::Display::Buffer::V1_0::IAllocator> Get(const std::string &serviceName, bool isStub = false);

    virtual int32_t AllocMem(const OHOS::HDI::Display::Buffer::V1_0::AllocInfo& info, sptr<NativeBuffer>& handle) = 0;

    virtual int32_t GetVersion(uint32_t& majorVer, uint32_t& minorVer)
    {
        majorVer = 1;
        minorVer = 0;
        return HDF_SUCCESS;
    }

    virtual bool IsProxy()
    {
        return false;
    }

    virtual const std::u16string GetDesc()
    {
        return metaDescriptor_;
    }
};

9. IAllocator::Get 为了满足安全要求,isStub = false,IAllocator走的是 Proxy——Stub 模式,核心代码如下

sptr<OHOS::HDI::Display::Buffer::V1_0::IAllocator> OHOS::HDI::Display::Buffer::V1_0::IAllocator::Get(bool isStub)
{
    return IAllocator::Get("allocator_service", isStub);
}

sptr<OHOS::HDI::Display::Buffer::V1_0::IAllocator> OHOS::HDI::Display::Buffer::V1_0::IAllocator::Get(const std::string& serviceName, bool isStub)
{
    if (isStub) {
        std::string desc = Str16ToStr8(OHOS::HDI::Display::Buffer::V1_0::IAllocator::GetDescriptor());
        void *impl = LoadHdiImpl(desc.c_str(), serviceName == "allocator_service" ? "service" : serviceName.c_str());
        if (impl == nullptr) {
            HDF_LOGE("failed to load hdi impl %{public}s", desc.data());
            return nullptr;
        }
        return reinterpret_cast<OHOS::HDI::Display::Buffer::V1_0::IAllocator *>(impl);
    }

    using namespace OHOS::HDI::ServiceManager::V1_0;
    auto servMgr = IServiceManager::Get();
    if (servMgr == nullptr) {
        HDF_LOGE("%{public}s:get IServiceManager failed!", __func__);
        return nullptr;
    }

    sptr<IRemoteObject> remote = servMgr->GetService(serviceName.c_str());
    if (remote == nullptr) {
        HDF_LOGE("%{public}s:get remote object failed!", __func__);
        return nullptr;
    }

    sptr<OHOS::HDI::Display::Buffer::V1_0::AllocatorProxy> proxy = new OHOS::HDI::Display::Buffer::V1_0::AllocatorProxy(remote);
    if (proxy == nullptr) {
        HDF_LOGE("%{public}s:iface_cast failed!", __func__);
        return nullptr;
    }

    proxy->servMgr_ = OHOS::HDI::hdi_objcast<IServiceManager>(servMgr);
    proxy->deathRecipient_ = new OHOS::HDI::Display::Buffer::V1_0::AllocatorProxy::IServiceManagerDeathRecipient(proxy);
    proxy->servMgr_->AddDeathRecipient(proxy->deathRecipient_);
    proxy->isReconnected_ = false;
    proxy->serviceName_ = serviceName;
    uint32_t serMajorVer = 0;
    uint32_t serMinorVer = 0;
    int32_t allocatorRet = proxy->GetVersion(serMajorVer, serMinorVer);
    if (allocatorRet != HDF_SUCCESS) {
        HDF_LOGE("%{public}s:get version failed!", __func__);
        return nullptr;
    }

    if (serMajorVer != 1) {
        HDF_LOGE("%{public}s:check version failed! version of service:%u.%u, version of client:1.0", __func__, serMajorVer, serMinorVer);
        return nullptr;
    }

    return proxy;
}

Mmap (Free、flush、map...)

内存映射等接口以Flush举例,完整流程如下

1.应用创建RT进程,Render中调用 ProcessRootRenderNode,flushbuffer(rsSurface->FlushFrame)

void RSRenderThreadVisitor::ProcessRootRenderNode(RSRootRenderNode& node)
{
    ...
#ifdef NEW_RENDER_CONTEXT
    rsSurface->FlushFrame(uiTimestamp_);
#else
    rsSurface->FlushFrame(surfaceFrame, uiTimestamp_);
#endif
    ...
}

2.上层跳转到 bufferquene 的 FlushBuffers 接口

GSError BufferQueueProducer::FlushBuffer(uint32_t sequence, sptr<BufferExtraData> bedata,
                                         sptr<SyncFence> fence, BufferFlushConfigWithDamages &config)
{
    if (bufferQueue_ == nullptr) {
        return SURFACE_ERROR_UNKOWN;
    }
    return bufferQueue_->FlushBuffer(sequence, bedata, fence, config);
}

3.与上面rquest流程一致,bufferquene 调用到 SurfaceBufferImpl 中

4.SurfaceBufferImpl 初始化 GetDisPlayBuffer

GSError SurfaceBufferImpl::FlushCache()
{
    std::lock_guard<std::mutex> bufferLock(g_displayBufferMutex);
    if (GetDisplayBufferLocked() == nullptr) {
        return SURFACE_ERROR_UNKOWN;
    }
    std::lock_guard<std::mutex> lock(mutex_);
    if (handle_ == nullptr) {
        return GSERROR_INVALID_OPERATING;
    }
    auto dret = g_displayBuffer->FlushCache(*handle_);
    if (dret == GRAPHIC_DISPLAY_SUCCESS) {
        return GSERROR_OK;
    }
    BLOGW("Failed with %{public}d", dret);
    return GenerateError(GSERROR_API_FAILED, dret);
}

5.6流程与上面一致, 初始化了一个HdiDisplayBufferImpl类实例

7. DisplayBufferHdiImpl 中的flush接口,其中mapper_的IMapper类通过IDL文件编译生成的


class DisplayBufferHdiImpl : public Interface {
public:
    explicit DisplayBufferHdiImpl(bool isAllocLocal = false) : allocator_(nullptr),
        mapper_(nullptr), recipient_(nullptr)
    {
        while ((allocator_ = IAllocator::Get(isAllocLocal)) == nullptr) {
            // Waiting for allocator service ready
            usleep(WAIT_TIME_INTERVAL);
        }
        while ((mapper_ = IMapper::Get(true)) == nullptr) {
            // Waiting for mapper IF ready
            usleep(WAIT_TIME_INTERVAL);
        }
    }


int32_t FlushCache(const BufferHandle& handle) const override
{
    CHECK_NULLPOINTER_RETURN_VALUE(mapper_, HDF_FAILURE);
    sptr<NativeBuffer> hdiBuffer = new NativeBuffer();
    CHECK_NULLPOINTER_RETURN_VALUE(hdiBuffer, HDF_FAILURE);
    hdiBuffer->SetBufferHandle(const_cast<BufferHandle*>(&handle));
    int32_t ret = mapper_->FlushCache(hdiBuffer);
    return ret;
}

8. IMapper 类的构成

class IMapper : public HdiBase {
public:
    DECLARE_HDI_DESCRIPTOR(u"ohos.hdi.display.buffer.v1_0.IMapper");

    virtual ~IMapper() = default;

    static sptr<OHOS::HDI::Display::Buffer::V1_0::IMapper> Get(bool isStub = false);
    static sptr<OHOS::HDI::Display::Buffer::V1_0::IMapper> Get(const std::string &serviceName, bool isStub = false);

    virtual int32_t FreeMem(const sptr<NativeBuffer>& handle) = 0;

    virtual int32_t Mmap(const sptr<NativeBuffer>& handle) = 0;

    virtual int32_t Unmap(const sptr<NativeBuffer>& handle) = 0;

    virtual int32_t FlushCache(const sptr<NativeBuffer>& handle) = 0;

    virtual int32_t InvalidateCache(const sptr<NativeBuffer>& handle) = 0;

    virtual int32_t GetVersion(uint32_t& majorVer, uint32_t& minorVer)
    {
        majorVer = 1;
        minorVer = 0;
        return HDF_SUCCESS;
    }

    virtual bool IsProxy()
    {
        return false;
    }

    virtual const std::u16string GetDesc()
    {
        return metaDescriptor_;
    }
};

9. IMapper::Get 不涉及到安全内核节点 isStub = true,IMapper走的是直通模式,直接加载到so,核心代码如下

sptr<OHOS::HDI::Display::Buffer::V1_0::IMapper> OHOS::HDI::Display::Buffer::V1_0::IMapper::Get(bool isStub)
{
    return IMapper::Get("mapper_service", isStub);
}

sptr<OHOS::HDI::Display::Buffer::V1_0::IMapper> OHOS::HDI::Display::Buffer::V1_0::IMapper::Get(const std::string& serviceName, bool isStub)
{
    if (isStub) {
        std::string desc = Str16ToStr8(OHOS::HDI::Display::Buffer::V1_0::IMapper::GetDescriptor());
        void *impl = LoadHdiImpl(desc.c_str(), serviceName == "mapper_service" ? "service" : serviceName.c_str());
        if (impl == nullptr) {
            HDF_LOGE("failed to load hdi impl %{public}s", desc.data());
            return nullptr;
        }
        return reinterpret_cast<OHOS::HDI::Display::Buffer::V1_0::IMapper *>(impl);
    }
    ...
}

服务启动流程

img

1. allocator_driver 和 mapper_driver

代码路径 drivers/peripheral/display/buffer/hdi_service/src

// allocator_driver
static int HdfAllocatorDriverBind(struct HdfDeviceObject* deviceObject)
{
    ...
    auto serviceImpl = IAllocator::Get(true);
    if (serviceImpl == nullptr) {
        HDF_LOGE("%{public}s: failed to get the implement of service", __func__);
        delete hdfAllocatorHost;
        return HDF_FAILURE;
    }

    hdfAllocatorHost->stub =
        OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl, IAllocator::GetDescriptor());
    if (hdfAllocatorHost->stub == nullptr) {
        HDF_LOGE("%{public}s: failed to get stub object", __func__);
        delete hdfAllocatorHost;
        return HDF_FAILURE;
    }

    deviceObject->service = &hdfAllocatorHost->ioService;
    return HDF_SUCCESS;
}

// mapper_driver
static int HdfMapperDriverBind(struct HdfDeviceObject* deviceObject)
{
    ...
    auto serviceImpl = Display::Buffer::V1_2::IMapper::Get(true);
    if (serviceImpl == nullptr) {
        HDF_LOGE("%{public}s: failed to get the implement of service", __func__);
        delete hdfMapperHost;
        return HDF_FAILURE;
    }

    hdfMapperHost->stub =
        OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl,
        Display::Buffer::V1_2::IMapper::GetDescriptor());
    if (hdfMapperHost->stub == nullptr) {
        HDF_LOGE("%{public}s: failed to get stub object", __func__);
        delete hdfMapperHost;
        return HDF_FAILURE;
    }

    deviceObject->service = &hdfMapperHost->ioService;
    return HDF_SUCCESS;
}

2.初始化 Stub 并加载对应的 HdiIpml

代码路径 out/oriole/gen/drivers/interface/display/buffer/v1_0

//allocator_stub 初始化
sptr<OHOS::HDI::Display::Buffer::V1_0::IAllocator> OHOS::HDI::Display::Buffer::V1_0::IAllocator::Get(bool isStub)
{
    return OHOS::HDI::Display::Buffer::V1_0::IAllocator::Get("allocator_service", isStub);
}

sptr<OHOS::HDI::Display::Buffer::V1_0::IAllocator> OHOS::HDI::Display::Buffer::V1_0::IAllocator::Get(const std::string& serviceName, bool isStub)
{
    if (!isStub) {
        return nullptr;
    }
    std::string desc = Str16ToStr8(OHOS::HDI::Display::Buffer::V1_0::IAllocator::GetDescriptor());
    void *impl = LoadHdiImpl(desc.c_str(), serviceName == "allocator_service" ? "service" : serviceName.c_str());
    if (impl == nullptr) {
        HDF_LOGE("failed to load hdi impl %{public}s", desc.c_str());
        return nullptr;
    }
    return reinterpret_cast<OHOS::HDI::Display::Buffer::V1_0::IAllocator *>(impl);
}
//mapper_stub 初始化
sptr<OHOS::HDI::Display::Buffer::V1_0::IMapper> OHOS::HDI::Display::Buffer::V1_0::IMapper::Get(bool isStub)
{
    return OHOS::HDI::Display::Buffer::V1_0::IMapper::Get("mapper_service", isStub);
}

sptr<OHOS::HDI::Display::Buffer::V1_0::IMapper> OHOS::HDI::Display::Buffer::V1_0::IMapper::Get(const std::string& serviceName, bool isStub)
{
    if (!isStub) {
        return nullptr;
    }
    std::string desc = Str16ToStr8(OHOS::HDI::Display::Buffer::V1_0::IMapper::GetDescriptor());
    void *impl = LoadHdiImpl(desc.c_str(), serviceName == "mapper_service" ? "service" : serviceName.c_str());
    if (impl == nullptr) {
        HDF_LOGE("failed to load hdi impl %{public}s", desc.c_str());
        return nullptr;
    }
    return reinterpret_cast<OHOS::HDI::Display::Buffer::V1_0::IMapper *>(impl);
}

3. 拼接得到对应的 serviceImplGetInstance

void *LoadHdiImpl(const char *desc, const char *serviceName)
{
    ...
    std::string symName = interfaceName + "ImplGetInstance";
    hdiImpl.constructor = reinterpret_cast<HdiImplInstanceFunc>(dlsym(hdiImpl.handler, symName.data()));
    ...
    return implInstance;
}

4. service加载vdi,对接到vdiIpml

代码路径 drivers/peripheral/display/buffer/hdi_service/src/

//allocactor_service
extern "C" IAllocator* AllocatorImplGetInstance(void)
{
    return new (std::nothrow) AllocatorService();
}

AllocatorService::AllocatorService()
    : libHandle_(nullptr),
    vdiImpl_(nullptr),
    createVdi_(nullptr),
    destroyVdi_(nullptr)
{
    int32_t ret = LoadVdi();
    if (ret == HDF_SUCCESS) {
        vdiImpl_ = createVdi_();
        CHECK_NULLPOINTER_RETURN(vdiImpl_);
    } else {
        HDF_LOGE("%{public}s: Load buffer VDI failed", __func__);
    }
}

int32_t AllocatorService::LoadVdi()
{
    ...
    createVdi_ = reinterpret_cast<CreateDisplayBufferVdiFunc>(dlsym(libHandle_, "CreateDisplayBufferVdi"));
    ...
    return HDF_SUCCESS;
}

extern "C" Buffer::V1_2::IMapper* MapperImplGetInstance(void)
{
    return new (std::nothrow) MapperService();
}


//mapper_service
MapperService::MapperService()
    : libHandle_(nullptr),
    vdiImpl_(nullptr),
    createVdi_(nullptr),
    destroyVdi_(nullptr)
{
    int32_t ret = LoadVdi();
    if (ret == HDF_SUCCESS) {
        vdiImpl_ = createVdi_();
        CHECK_NULLPOINTER_RETURN(vdiImpl_);
    } else {
        HDF_LOGE("%{public}s: Load buffer VDI failed", __func__);
    }
}

int32_t MapperService::LoadVdi()
{
    ...
    createVdi_ = reinterpret_cast<CreateDisplayBufferVdiFunc>(dlsym(libHandle_, "CreateDisplayBufferVdi"));
    ...
    return HDF_SUCCESS;
}

5. 通过vdiImpl_调用device接口

int32_t AllocatorService::AllocMem(const AllocInfo& info, sptr<NativeBuffer>& handle)
{
    BufferHandle* buffer = nullptr;
    CHECK_NULLPOINTER_RETURN_VALUE(vdiImpl_, HDF_FAILURE);
    int32_t ec = vdiImpl_->AllocMem(info, buffer);
    if (ec != HDF_SUCCESS) {
        HDF_LOGE("%{public}s: AllocMem failed, ec = %{public}d", __func__, ec);
        return ec;
    }
    CHECK_NULLPOINTER_RETURN_VALUE(buffer, HDF_DEV_ERR_NO_MEMORY);

    handle = new NativeBuffer();
    if (handle == nullptr) {
        HDF_LOGE("%{public}s: new NativeBuffer failed", __func__);
        delete handle;
        vdiImpl_->FreeMem(*buffer);
        return HDF_FAILURE;
    }

    handle->SetBufferHandle(buffer, true, [this](BufferHandle* freeBuffer) {
        vdiImpl_->FreeMem(*freeBuffer);
    });
    return HDF_SUCCESS;
}

int32_t MapperService::FlushCache(const sptr<NativeBuffer>& handle)
{
    DISPLAY_TRACE;
    CHECK_NULLPOINTER_RETURN_VALUE(handle, HDF_FAILURE);
    CHECK_NULLPOINTER_RETURN_VALUE(vdiImpl_, HDF_FAILURE);

    BufferHandle* buffer = handle->GetBufferHandle();
    CHECK_NULLPOINTER_RETURN_VALUE(buffer, HDF_FAILURE);
    int32_t ret = vdiImpl_->FlushCache(*buffer);
    DISPLAY_CHK_RETURN(ret != HDF_SUCCESS, HDF_FAILURE, DISPLAY_LOGE(" fail"));
    return ret;
}

Device对外提供了哪些接口

1. AllocMem 申请内存

int32_t Allocator::AllocMem(const AllocInfo &info, BufferHandle **handle)
{
    int ret;
    DISPLAY_LOGD();
    BufferInfo bufferInfo;
    ret = ConvertToBufferInfo(bufferInfo, info);
    DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_NOT_SUPPORT, DISPLAY_LOGE("failed to convert to bufferInfo"));

    BufferHandle *priBuffer = nullptr;
    ret = Allocate(bufferInfo, &priBuffer);
    if (ret != DISPLAY_SUCCESS) {
        DISPLAY_LOGE("AllocMem failed");
        return ret;
    }
    *handle = priBuffer;
    DumpBufferHandle(*priBuffer);

    return DISPLAY_SUCCESS;
}

2. FreeMem 释放内存

int32_t Allocator::FreeMem(BufferHandle *handle)
{
    DISPLAY_LOGD();
    DISPLAY_CHK_RETURN((handle == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("buffer is null"));
    if (handle->fd >= 0) {
        DISPLAY_LOGD("release the fd is %{public}d", handle->fd);
        close(handle->fd);
        handle->fd = -1;
    }
    const uint32_t reserveFds = handle->reserveFds;
    for (uint32_t i = 0; i < reserveFds; i++) {
        if (handle->reserve[i] >= 0) {
            DISPLAY_LOGD("release the fd is %{public}d", handle->reserve[i]);
            close(handle->reserve[i]);
            handle->reserve[i] = -1;
        }
    }
    free(handle);
    return DISPLAY_SUCCESS;
}

3. Mmap 内存映射

void *Allocator::Mmap(BufferHandle *handle)
{
    DISPLAY_LOGD();
    void *virAddr = nullptr;
    if (handle->virAddr != nullptr) {
        DISPLAY_LOGW("the buffer has virtual addr");
        return handle->virAddr;
    }
    DISPLAY_LOGI("buffer handle size %{public}d, width %{public}d, height %{public}d, stride %{public}d, fd %{public}d, format: %d, "
                 "phy 0x%{public}" PRIx64 ", usage 0x%{public}" PRIx64 ", viraddr 0x%{public}p",
        handle->size, handle->width, handle->height, handle->stride, handle->fd, handle->format, handle->phyAddr,
        handle->usage, handle->virAddr);
    virAddr = mmap(nullptr, handle->size, PROT_READ | PROT_WRITE, MAP_SHARED, handle->fd, 0);
    if (virAddr == MAP_FAILED) {
        DISPLAY_LOGE("mmap failed errno %{public}d:%{public}s, fd : %{public}d", errno, strerror(errno), handle->fd);
        handle->virAddr = nullptr;
        return nullptr;
    }
    handle->virAddr = virAddr;
    return virAddr;
}

4. Unmap 解除内存映射

int32_t Allocator::Unmap(BufferHandle *handle)
{
    if (handle->virAddr == nullptr) {
        DISPLAY_LOGE("virAddr is nullptr , has not map the buffer");
        return DISPLAY_PARAM_ERR;
    }
    int ret = munmap(handle->virAddr, handle->size);
    if (ret != 0) {
        DISPLAY_LOGE("munmap failed err: %{public}d", errno);
        return DISPLAY_FAILURE;
    }
    handle->virAddr = nullptr;
    return DISPLAY_SUCCESS;
}

5. FlushCache 刷新缓存 将cache数据写进memory后使缓存失效

int32_t Allocator::FlushCache(BufferHandle *handle)
{
    DISPLAY_LOGD();
    return DmaBufferSync(*handle, DMA_BUF_SYNC_START);
}

6. InvalidateCache 使缓存失效 将cache数据设置为无效(即discard cache中的数据),不会将cache数据写入memory

int32_t Allocator::InvalidateCache(BufferHandle *handle)
{
    DISPLAY_LOGD();
    return DmaBufferSync(*handle, DMA_BUF_SYNC_END);
}

Device层 serviceManger 调用各自实现

int32_t AllocatorManager::Init()
{
    DISPLAY_LOGD("AllocatorManager::Init");
    if (init_) {
        DISPLAY_LOGW("allocator has initialized");
        return DISPLAY_SUCCESS;
    }
    // first use sprd allocator
    std::shared_ptr<Allocator> sprdAllocator = std::make_shared<SprdAllocator>();
    int ret = sprdAllocator->Init();
    if (ret == DISPLAY_SUCCESS) {
        frameBufferAllocator_ = sprdAllocator;
        allocator_ = sprdAllocator;
    } else {
        std::shared_ptr<Allocator> drmAllocator = std::make_shared<DrmAllocator>();
        int ret = drmAllocator->Init();
        if (ret == DISPLAY_SUCCESS) {
            frameBufferAllocator_ = drmAllocator;
            allocator_ = drmAllocator;
        } else {
            std::shared_ptr<Allocator> fbAllocator = std::make_shared<FramebufferAllocator>();
            ret = fbAllocator->Init();
            DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE,
                DISPLAY_LOGE("Failed init framebuffer allocator"));

            std::shared_ptr<Allocator> dmaBufferallocator = std::make_shared<DmaBufferHeapAllocator>();
            ret = dmaBufferallocator->Init();
            DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE,
                DISPLAY_LOGE("Failed init Dmabuffer allocator"));

            frameBufferAllocator_ = fbAllocator;
            allocator_ = dmaBufferallocator;
        }
    }

    init_ = true;
    DISPLAY_LOGD("init success");
    return DISPLAY_SUCCESS;
}
Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐