1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "allocator_service.h" 17 18#include <sys/ioctl.h> 19#include <linux/types.h> 20#include <linux/dma-buf.h> 21#include <securec.h> 22#include <dlfcn.h> 23#include <hdf_base.h> 24#include <hdf_log.h> 25#include "display_log.h" 26#include "hdf_trace.h" 27#include "hdf_remote_service.h" 28#include "display_buffer_dfx.h" 29 30#undef LOG_TAG 31#define LOG_TAG "ALLOC_SRV" 32#undef LOG_DOMAIN 33#define LOG_DOMAIN 0xD002515 34#define BUFF_SIZE 16 35 36namespace OHOS { 37namespace HDI { 38namespace Display { 39namespace Buffer { 40namespace V1_0 { 41extern "C" IAllocator* AllocatorImplGetInstance(void) 42{ 43 return new (std::nothrow) AllocatorService(); 44} 45 46AllocatorService::AllocatorService() 47 : libHandle_(nullptr), 48 vdiImpl_(nullptr), 49 createVdi_(nullptr), 50 destroyVdi_(nullptr) 51{ 52 int32_t ret = LoadVdi(); 53 if (ret == HDF_SUCCESS) { 54 vdiImpl_ = createVdi_(); 55 CHECK_NULLPOINTER_RETURN(vdiImpl_); 56 } else { 57 HDF_LOGE("%{public}s: Load buffer VDI failed", __func__); 58 } 59} 60 61AllocatorService::~AllocatorService() 62{ 63 std::lock_guard<std::mutex> lck(mutex_); 64 if (destroyVdi_ != nullptr && vdiImpl_ != nullptr) { 65 destroyVdi_(vdiImpl_); 66 vdiImpl_ = nullptr; 67 destroyVdi_ = nullptr; 68 } 69 if (libHandle_ != nullptr) { 70 dlclose(libHandle_); 71 libHandle_ = nullptr; 72 } 73} 74 75int32_t AllocatorService::LoadVdi() 76{ 77 const char* errStr = dlerror(); 78 if (errStr != nullptr) { 79 HDF_LOGD("%{public}s: allocator load vdi, clear earlier dlerror: %{public}s", __func__, errStr); 80 } 81#ifdef BUFFER_VDI_DEFAULT_LIBRARY_ENABLE 82 libHandle_ = dlopen(DISPLAY_BUFFER_VDI_DEFAULT_LIBRARY, RTLD_LAZY); 83 if (libHandle_ == nullptr) { 84 DISPLAY_LOGE("display buffer load vendor vdi default library failed: %{public}s", DISPLAY_BUFFER_VDI_LIBRARY); 85#endif // BUFFER_VDI_DEFAULT_LIBRARY_ENABLE 86 libHandle_ = dlopen(DISPLAY_BUFFER_VDI_LIBRARY, RTLD_LAZY); 87 DISPLAY_LOGD("display buffer load vendor vdi library: %{public}s", DISPLAY_BUFFER_VDI_LIBRARY); 88#ifdef BUFFER_VDI_DEFAULT_LIBRARY_ENABLE 89 } else { 90 DISPLAY_LOGD("display buffer load vendor vdi default library: %{public}s", DISPLAY_BUFFER_VDI_LIBRARY); 91 } 92#endif // BUFFER_VDI_DEFAULT_LIBRARY_ENABLE 93 CHECK_NULLPOINTER_RETURN_VALUE(libHandle_, HDF_FAILURE); 94 95 createVdi_ = reinterpret_cast<CreateDisplayBufferVdiFunc>(dlsym(libHandle_, "CreateDisplayBufferVdi")); 96 if (createVdi_ == nullptr) { 97 errStr = dlerror(); 98 if (errStr != nullptr) { 99 HDF_LOGE("%{public}s: allocator CreateDisplayBufferVdi dlsym error: %{public}s", __func__, errStr); 100 } 101 dlclose(libHandle_); 102 return HDF_FAILURE; 103 } 104 105 destroyVdi_ = reinterpret_cast<DestroyDisplayBufferVdiFunc>(dlsym(libHandle_, "DestroyDisplayBufferVdi")); 106 if (destroyVdi_ == nullptr) { 107 errStr = dlerror(); 108 if (errStr != nullptr) { 109 HDF_LOGE("%{public}s: allocator DestroyDisplayBufferVdi dlsym error: %{public}s", __func__, errStr); 110 } 111 dlclose(libHandle_); 112 return HDF_FAILURE; 113 } 114 return HDF_SUCCESS; 115} 116 117void AllocatorService::WriteAllocPidToDma(int32_t fd) 118{ 119 pid_t remotePid = HdfRemoteGetCallingPid(); 120 char pidStr[BUFF_SIZE] = { 0 }; 121 if (sprintf_s(pidStr, BUFF_SIZE, "%d", remotePid) >= 0) { 122 ioctl(fd, DMA_BUF_SET_NAME_A, pidStr); 123 } 124} 125 126void AllocatorService::FreeMemVdi(BufferHandle* handle) 127{ 128 DisplayBufferDfx dfxIns("HDI:Display:FreeMemVdi:FreeMem"); 129 dfxIns.SetTimer(); 130 dfxIns.StartTimeStamp(); 131 HdfTrace traceTwo("FreeMem", "HDI:VDI:"); 132 vdiImpl_->FreeMem(*handle); 133} 134 135int32_t AllocatorService::AllocMem(const AllocInfo& info, sptr<NativeBuffer>& handle) 136{ 137 HdfTrace trace(__func__, "HDI:DISP:"); 138 139 BufferHandle* buffer = nullptr; 140 CHECK_NULLPOINTER_RETURN_VALUE(vdiImpl_, HDF_FAILURE); 141 { 142 DisplayBufferDfx dfxIns("HDI:Display:AllocatorService:AllocMem"); 143 dfxIns.SetTimer(); 144 dfxIns.StartTimeStamp(); 145 HdfTrace traceOne("AllocMem-VDI", "HDI:VDI:"); 146 int32_t ec = vdiImpl_->AllocMem(info, buffer); 147 if (ec != HDF_SUCCESS) { 148 HDF_LOGE("%{public}s: AllocMem failed, ec = %{public}d", __func__, ec); 149 return ec; 150 } 151 } 152 153 CHECK_NULLPOINTER_RETURN_VALUE(buffer, HDF_DEV_ERR_NO_MEMORY); 154 WriteAllocPidToDma(buffer->fd); 155 156 handle = new NativeBuffer(); 157 if (handle == nullptr) { 158 HDF_LOGE("%{public}s: new NativeBuffer failed", __func__); 159 FreeMemVdi(buffer); 160 return HDF_FAILURE; 161 } 162 163 handle->SetBufferHandle(buffer, true, [this](BufferHandle* freeBuffer) { 164 FreeMemVdi(freeBuffer); 165 }); 166 return HDF_SUCCESS; 167} 168} // namespace V1_0 169} // namespace Buffer 170} // namespace Display 171} // namespace HDI 172} // namespace OHOS 173