1 /* 2 * Copyright (c) 2022 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 #ifndef OHOS_HDI_DISPLAY_V1_0_DISPLAY_CMD_UTILS_H 17 #define OHOS_HDI_DISPLAY_V1_0_DISPLAY_CMD_UTILS_H 18 19 #include "buffer_handle_utils.h" 20 #include "command_data_packer.h" 21 #include "command_data_unpacker.h" 22 #include "v1_0/display_composer_type.h" 23 24 namespace OHOS { 25 namespace HDI { 26 namespace Display { 27 namespace Composer { 28 namespace V1_0 { 29 using namespace OHOS::HDI::Display::Composer::V1_0; 30 31 class DisplayCmdUtils { 32 public: 33 static constexpr int32_t MAX_INT = 0x7fffffff; 34 static constexpr int32_t MIN_INT = 0x80000000; 35 static constexpr uint32_t ELEMENT_SIZE = sizeof(int32_t); 36 static constexpr uint32_t TRANSFER_WAIT_TIME = 100000000; // ms 37 static constexpr uint32_t INIT_ELEMENT_COUNT = 32 * 1024; 38 39 #define SWITCHCASE(x) case (x): {return #x;} 40 #define PARCEL_OPS_CHECK_RET(fn, arg) \ 41 do { \ 42 bool ret = fn(arg); \ 43 if (ret == false) { \ 44 HDF_LOG("%{public}s: parcel ops failed, line = %{public}d", __func__, __LINE__); \ 45 return HDF_FAILURE; \ 46 } \ 47 } while (0) 48 49 #define PARCEL_OPS_CHECK_WITHOUT_RET(fn, arg, ret) \ 50 do { \ 51 if (ret) { \ 52 ret = fn(arg); \ 53 } else { \ 54 HDF_LOG("%{public}s: parcel ops failed, line = %{public}d", __func__, __LINE__); \ 55 } \ 56 } while (0) 57 CommandToString(int32_t cmdId)58 static const char *CommandToString(int32_t cmdId) 59 { 60 switch (cmdId) { 61 /* request cmd */ 62 SWITCHCASE(REQUEST_CMD_PREPAREDISPLAYLAYERS); 63 SWITCHCASE(REQUEST_CMD_SETDISPLAYCLIENTBUFFER); 64 SWITCHCASE(REQUEST_CMD_SETDISPLAYCLIENTDAMAGE); 65 SWITCHCASE(REQUEST_CMD_COMMIT); 66 SWITCHCASE(REQUEST_CMD_SETLAYERALPHA); 67 SWITCHCASE(REQUEST_CMD_SETLAYERPOSITION); 68 SWITCHCASE(REQUEST_CMD_SETLAYERCROP); 69 SWITCHCASE(REQUEST_CMD_SETLAYERZORDER); 70 SWITCHCASE(REQUEST_CMD_SETLAYERPREMULTI); 71 SWITCHCASE(REQUEST_CMD_SETTRANSFORMMODE); 72 SWITCHCASE(REQUEST_CMD_SETLAYERDIRTYREGION); 73 SWITCHCASE(REQUEST_CMD_SETLAYERVISIBLEREGION); 74 SWITCHCASE(REQUEST_CMD_SETLAYERBUFFER); 75 SWITCHCASE(REQUEST_CMD_SETLAYERCOMPOSITIONTYPE); 76 SWITCHCASE(REQUEST_CMD_SETLAYERBLENDTYPE); 77 SWITCHCASE(REQUEST_CMD_SETLAYERVISIBLE); 78 /* reply cmd */ 79 SWITCHCASE(REPLY_CMD_SETERROR); 80 SWITCHCASE(REPLY_CMD_PREPAREDISPLAYLAYERS); 81 SWITCHCASE(REPLY_CMD_COMMIT); 82 /* pack control cmd */ 83 SWITCHCASE(CONTROL_CMD_REQUEST_BEGIN); 84 SWITCHCASE(CONTROL_CMD_REPLY_BEGIN); 85 SWITCHCASE(CONTROL_CMD_REQUEST_END); 86 SWITCHCASE(CONTROL_CMD_REPLY_END); 87 default: 88 return "unknow command id."; 89 } 90 } 91 StartPack(int32_t cmdId,std::shared_ptr<CommandDataPacker> packer)92 static int32_t StartPack(int32_t cmdId, std::shared_ptr<CommandDataPacker> packer) 93 { 94 return packer->PackBegin(cmdId) ? HDF_SUCCESS : HDF_FAILURE; 95 } 96 EndPack(std::shared_ptr<CommandDataPacker> packer)97 static int32_t EndPack(std::shared_ptr<CommandDataPacker> packer) 98 { 99 return packer->PackEnd(CONTROL_CMD_REQUEST_END) ? HDF_SUCCESS : HDF_FAILURE; 100 } 101 StartSection(int32_t cmdId,std::shared_ptr<CommandDataPacker> packer)102 static int32_t StartSection(int32_t cmdId, std::shared_ptr<CommandDataPacker> packer) 103 { 104 return packer->BeginSection(cmdId) ? HDF_SUCCESS : HDF_FAILURE; 105 } 106 SetupDevice(uint32_t devId,uint32_t layerId,std::shared_ptr<CommandDataPacker> packer)107 static int32_t SetupDevice(uint32_t devId, uint32_t layerId, std::shared_ptr<CommandDataPacker> packer) 108 { 109 bool retVal = packer->WriteUint32(devId); 110 if (retVal) { 111 retVal = packer->WriteUint32(layerId); 112 } 113 return retVal ? HDF_SUCCESS : HDF_FAILURE; 114 } 115 EndSection(std::shared_ptr<CommandDataPacker> packer)116 static int32_t EndSection(std::shared_ptr<CommandDataPacker> packer) 117 { 118 return packer->EndSection() ? HDF_SUCCESS : HDF_FAILURE; 119 } 120 GenerateHdifdSeqid()121 static int32_t GenerateHdifdSeqid() 122 { 123 static int32_t HdifdSeqidCursor = 0; 124 125 if (HdifdSeqidCursor <= MAX_INT) { 126 ++HdifdSeqidCursor; 127 return HdifdSeqidCursor; 128 } else { 129 return 0; 130 } 131 } 132 MatchHdiFd(int32_t id,std::vector<HdifdInfo> hdiFds,int32_t & fd)133 static bool MatchHdiFd(int32_t id, std::vector<HdifdInfo> hdiFds, int32_t &fd) 134 { 135 for (uint32_t i = 0; i < hdiFds.size(); ++i) { 136 if (hdiFds[i].id == id) { 137 fd = hdiFds[i].hdiFd->Move(); 138 return true; 139 } 140 } 141 return false; 142 } 143 RectPack(const IRect & rect,std::shared_ptr<CommandDataPacker> packer)144 static int32_t RectPack(const IRect &rect, std::shared_ptr<CommandDataPacker> packer) 145 { 146 bool retVal = packer->WriteInt32(rect.x); 147 if (retVal) { 148 retVal = packer->WriteInt32(rect.y); 149 } 150 if (retVal) { 151 retVal = packer->WriteInt32(rect.w); 152 } 153 if (retVal) { 154 retVal = packer->WriteInt32(rect.h); 155 } 156 return retVal ? HDF_SUCCESS : HDF_FAILURE; 157 } 158 FileDescriptorPack(const int32_t fd,std::shared_ptr<CommandDataPacker> packer,std::vector<HdifdInfo> & hdiFds)159 static int32_t FileDescriptorPack( 160 const int32_t fd, std::shared_ptr<CommandDataPacker> packer, std::vector<HdifdInfo> &hdiFds) 161 { 162 int32_t ec = HDF_SUCCESS; 163 164 HdifdInfo hdifdInfo; 165 hdifdInfo.id = GenerateHdifdSeqid(); 166 hdifdInfo.hdiFd = new HdifdParcelable(); 167 if (hdifdInfo.hdiFd == nullptr) { 168 HDF_LOGE("%{public}s: new HdifdParcelable failed", __func__); 169 ec = HDF_FAILURE; 170 } else { 171 if (fd >= 0) { 172 // A normal fd is transfered by binder, here just write id for unpacking to match fd. 173 if (ec == HDF_SUCCESS && hdifdInfo.hdiFd->Init(fd)) { 174 hdiFds.push_back(hdifdInfo); 175 ec = packer->WriteInt32(hdifdInfo.id) ? HDF_SUCCESS : HDF_FAILURE; 176 } else { 177 HDF_LOGE("%{public}s: WriteInt32 failed, line=%{public}d", __func__, __LINE__); 178 ec = HDF_FAILURE; 179 } 180 } else { 181 // A illegal fd is transfered by smq directly. 182 ec = packer->WriteInt32(fd); 183 if (ec != HDF_SUCCESS { 184 HDF_LOGE("%{public}s: WriteInt32 failed, line=%{public}d", __func__, __LINE__); 185 } 186 } 187 } 188 return ec; 189 } 190 191 static int32_t BufferHandlePack(const BufferHandle &buffer, std::shared_ptr<CommandDataPacker> packer, 192 std::vector<HdifdInfo> &hdiFds) 193 { 194 PARCEL_OPS_CHECK_RET(packer->WriteUint32, buffer.reserveFds); 195 PARCEL_OPS_CHECK_RET(packer->WriteUint32, buffer.reserveInts); 196 int32_t ec = FileDescriptorPack(buffer.fd, packer, hdiFds); 197 if (ec != HDF_SUCCESS) { 198 return ec; 199 } 200 PARCEL_OPS_CHECK_RET(packer->WriteInt32, buffer.width); 201 PARCEL_OPS_CHECK_RET(packer->WriteInt32, buffer.stride); 202 PARCEL_OPS_CHECK_RET(packer->WriteInt32, buffer.height); 203 PARCEL_OPS_CHECK_RET(packer->WriteInt32, buffer.size); 204 PARCEL_OPS_CHECK_RET(packer->WriteInt32, buffer.format); 205 PARCEL_OPS_CHECK_RET(packer->WriteUint64, buffer.usage); 206 PARCEL_OPS_CHECK_RET(packer->WriteUint64, buffer.phyAddr); 207 PARCEL_OPS_CHECK_RET(packer->WriteInt32, buffer.key); 208 209 bool retVal = true; 210 int32_t i = 0; 211 for (i = 0; i < buffer.reserveFds; i++) { 212 ec = FileDescriptorPack(buffer.reserve[i], packer, hdiFds); 213 if (ec != HDF_SUCCESS) { 214 retVal = false; 215 break; 216 } 217 } 218 for (int32_t j = 0; j < buffer.reserveInts; j++) { 219 retVal = packer->WriteInt32(buffer.reserve[i++]); 220 if (!retVal) { 221 break; 222 } 223 } 224 return retVal ? HDF_SUCCESS : HDF_FAILURE; 225 } 226 227 static int32_t SetupDeviceUnpack(std::shared_ptr<CommandDataUnpacker> unpacker, uint32_t &devId, uint32_t &layerId) 228 { 229 bool retVal = unpacker->ReadUint32(devId); 230 if (retVal) { 231 retVal = unpacker->ReadUint32(layerId); 232 } 233 return retVal ? HDF_SUCCESS : HDF_FAILURE; 234 } 235 236 static int32_t RectUnpack(std::shared_ptr<CommandDataUnpacker> unpacker, IRect &rect) 237 { 238 bool retVal = unpacker->ReadInt32(rect.x); 239 if (retVal) { 240 retVal = unpacker->ReadInt32(rect.y); 241 } 242 if (retVal) { 243 retVal = unpacker->ReadInt32(rect.w); 244 } 245 if (retVal) { 246 retVal = unpacker->ReadInt32(rect.h); 247 } 248 return retVal ? HDF_SUCCESS : HDF_FAILURE; 249 } 250 251 static int32_t FileDescriptorUnpack( 252 std::shared_ptr<CommandDataUnpacker> unpacker, const std::vector<HdifdInfo> &hdiFds, int32_t &fd) 253 { 254 int32_t fdId = -1; 255 int32_t ec = unpacker->ReadInt32(fdId) ? HDF_SUCCESS : HDF_FAILURE; 256 if (ec == HDF_SUCCESS && fdId >= 0) { 257 ec = MatchHdiFd(fdId, hdiFds, fd) ? HDF_SUCCESS : HDF_FAILURE; 258 } 259 if (ec == HDF_FAILURE) { 260 // If matching failure, the illegal fd is transfered by smq directly, not by binder IPC. 261 fd = fdId; 262 } 263 return ec; 264 } 265 266 static int32_t BufferHandleUnpack(std::shared_ptr<CommandDataUnpacker> unpacker, 267 const std::vector<HdifdInfo> &hdiFds, BufferHandle *&buffer) 268 { 269 uint32_t fdsNum = 0; 270 uint32_t intsNum = 0; 271 PARCEL_OPS_CHECK_RET(unpacker->ReadUint32, fdsNum); 272 PARCEL_OPS_CHECK_RET(unpacker->ReadUint32, intsNum); 273 BufferHandle *handle = AllocateBufferHandle(fdsNum, intsNum); 274 if (handle == nullptr) { 275 return HDF_FAILURE; 276 } 277 handle->reserveFds = fdsNum; 278 handle->reserveInts = intsNum; 279 int32_t ec = FileDescriptorUnpack(unpacker, hdiFds, handle->fd); 280 bool retVal = (ec == HDF_SUCCESS ? true : false); 281 PARCEL_OPS_CHECK_WITHOUT_RET(unpacker->ReadInt32, handle->width, retVal); 282 PARCEL_OPS_CHECK_WITHOUT_RET(unpacker->ReadInt32, handle->stride, retVal); 283 PARCEL_OPS_CHECK_WITHOUT_RET(unpacker->ReadInt32, handle->height, retVal); 284 PARCEL_OPS_CHECK_WITHOUT_RET(unpacker->ReadInt32, handle->size, retVal); 285 PARCEL_OPS_CHECK_WITHOUT_RET(unpacker->ReadUint64, handle->usage, retVal); 286 PARCEL_OPS_CHECK_WITHOUT_RET(unpacker->ReadUint64, handle->phyAddr, retVal); 287 PARCEL_OPS_CHECK_WITHOUT_RET(unpacker->ReadInt32, handle->key, retVal); 288 if (retVal) { 289 int32_t i = 0; 290 for (i = 0; i < handle->reserveFds; i++) { 291 ec = FileDescriptorUnpack(unpacker, hdiFds, handle->reserve[i]); 292 if (ec != HDF_SUCCESS) { 293 retVal = false; 294 break; 295 } 296 } 297 for (int32_t j = 0; j < handle->reserveInts; j++) { 298 retVal = unpacker->ReadInt32(handle->reserve[i++]); 299 if (!retVal) { 300 break; 301 } 302 } 303 } 304 if (!retVal) { 305 if (handle != nullptr) { 306 FreeBufferHandle(handle); 307 handle = nullptr; 308 } 309 HDF_LOGE("%{public}s: buffer handle unpack failed", __func__); 310 } 311 buffer = handle; 312 return retVal ? HDF_SUCCESS : HDF_FAILURE; 313 } 314 }; 315 using CmdUtils = DisplayCmdUtils; 316 } // namespace V1_0 317 } // namespace Composer 318 } // namespace Display 319 } // namespace HDI 320 } // namespace OHOS 321 #endif // OHOS_HDI_DISPLAY_V1_0_DISPLAY_CMD_UTILS_H