1 /*
2 * Copyright (C) 2024 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 "picture_handle_client.h"
17
18 #include <cstdlib>
19 #include <fcntl.h>
20 #include <libexif/exif-entry.h>
21 #include <securec.h>
22 #include <sys/mman.h>
23 #include <unistd.h>
24
25 #include "exif_metadata.h"
26 #include "image_type.h"
27 #include "image_utils.h"
28 #include "medialibrary_db_const.h"
29 #include "medialibrary_errno.h"
30 #include "medialibrary_napi_utils.h"
31 #include "media_column.h"
32 #include "media_file_utils.h"
33 #include "media_log.h"
34 #include "pixel_yuv.h"
35 #include "pixel_yuv_ext.h"
36 #include "userfilemgr_uri.h"
37 #include "userfile_client.h"
38 #include <fstream>
39
40 namespace OHOS {
41 namespace Media {
42 const int32_t MAX_VALUE = 100000000;
RequestPicture(const int32_t & fileId)43 std::shared_ptr<Media::Picture> PictureHandlerClient::RequestPicture(const int32_t &fileId)
44 {
45 MEDIA_DEBUG_LOG("PictureHandlerClient::RequestPicture fileId: %{public}d", fileId);
46 std::string uri = PhotoColumn::PHOTO_REQUEST_PICTURE;
47 MediaFileUtils::UriAppendKeyValue(uri, MediaColumn::MEDIA_ID, std::to_string(fileId));
48 Uri requestUri(uri);
49 int32_t fd = UserFileClient::OpenFile(requestUri, MEDIA_FILEMODE_READONLY);
50 if (fd < 0) {
51 MEDIA_DEBUG_LOG("PictureHandlerClient::RequestPicture picture not exist");
52 return nullptr;
53 }
54 std::shared_ptr<Media::Picture> picture = nullptr;
55 ReadPicture(fd, fileId, picture);
56 FinishRequestPicture(fileId);
57 close(fd);
58 return picture;
59 }
60
FinishRequestPicture(const int32_t & fileId)61 void PictureHandlerClient::FinishRequestPicture(const int32_t &fileId)
62 {
63 MEDIA_DEBUG_LOG("PictureHandlerClient::FinishRequestPicture fileId: %{public}d", fileId);
64 std::string uri = PAH_FINISH_REQUEST_PICTURE;
65 MediaLibraryNapiUtils::UriAppendKeyValue(uri, API_VERSION, std::to_string(MEDIA_API_VERSION_V10));
66 Uri finishRequestPictureUri(uri);
67
68 DataShare::DataShareValuesBucket valuesBucket;
69 valuesBucket.Put(PhotoColumn::MEDIA_ID, fileId);
70 UserFileClient::Insert(finishRequestPictureUri, valuesBucket);
71 }
72
ReadPicture(const int32_t & fd,const int32_t & fileId,std::shared_ptr<Media::Picture> & picture)73 int32_t PictureHandlerClient::ReadPicture(const int32_t &fd, const int32_t &fileId,
74 std::shared_ptr<Media::Picture> &picture)
75 {
76 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadPicture fd: %{public}d", fd);
77 // 获取消息总长度
78 void *msgLenAddr = mmap(nullptr, UINT32_LEN, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
79 if (msgLenAddr == MAP_FAILED || msgLenAddr == nullptr) {
80 MEDIA_ERR_LOG("PictureHandlerClient::ReadPicture mmap msgLenAddr failed!");
81 close(fd);
82 return E_ERR;
83 }
84 uint32_t msgLen = *((uint32_t*)msgLenAddr);
85 munmap(msgLenAddr, UINT32_LEN);
86 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadPicture msgLen: %{public}d", msgLen);
87
88 // 获取消息
89 uint8_t *addr = (uint8_t*)mmap(nullptr, msgLen, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
90 if (addr == MAP_FAILED || addr == nullptr) {
91 MEDIA_ERR_LOG("PictureHandlerClient::ReadPicture mmap addr failed!");
92 close(fd);
93 return E_ERR;
94 }
95 uint32_t readoffset = UINT32_LEN;
96
97 // 读取dataSize
98 uint32_t dataSize = *reinterpret_cast<const uint32_t*>(addr + readoffset);
99 readoffset += UINT32_LEN;
100 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadPicture dataSize: %{public}d", dataSize);
101 if (dataSize == 0) {
102 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadPicture picture is not exists");
103 munmap(addr, msgLen);
104 return E_NO_SUCH_FILE;
105 }
106
107 // 读取auxiliaryPictureSize
108 uint32_t auxiliaryPictureSize = *reinterpret_cast<const uint32_t*>(addr + readoffset);
109 readoffset += UINT32_LEN;
110 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadPicture auxiliaryPictureSize: %{public}d",
111 auxiliaryPictureSize);
112 uint8_t *pictureParcelData = static_cast<uint8_t *>(malloc(dataSize));
113 if (pictureParcelData == nullptr) {
114 munmap(addr, msgLen);
115 return E_ERR;
116 }
117 if (memcpy_s((void*)pictureParcelData, dataSize, addr+readoffset, dataSize)) {
118 MEDIA_ERR_LOG("PictureHandlerService::ReadPicture memcpy_s pictureParcel failed!");
119 free(pictureParcelData);
120 munmap(addr, msgLen);
121 return E_ERR;
122 }
123 MessageParcel pictureParcel;
124 pictureParcel.ParseFrom(reinterpret_cast<uintptr_t>(pictureParcelData), dataSize);
125
126 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadPicture read mainPixelMap");
127 std::shared_ptr<PixelMap> mainPixelMap = ReadPixelMap(pictureParcel);
128 std::unique_ptr<Media::Picture> picturePtr = Picture::Create(mainPixelMap);
129 if (picturePtr == nullptr) {
130 MEDIA_ERR_LOG("PictureHandlerService::ReadPicture picturePtr is nullptr!");
131 munmap(addr, msgLen);
132 return E_ERR;
133 }
134
135 ReadExifMetadata(pictureParcel, picturePtr);
136 ReadMaintenanceData(pictureParcel, picturePtr);
137
138 for (size_t i = 1; i <= auxiliaryPictureSize; i++) {
139 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadPicture read auxiliaryPicture, index:%{public}zu", i);
140 ReadAuxiliaryPicture(pictureParcel, picturePtr);
141 }
142 picture.reset(picturePtr.get());
143 picturePtr.release();
144 munmap(addr, msgLen);
145 return E_OK;
146 }
147
ReadPixelMap(MessageParcel & data)148 std::shared_ptr<PixelMap> PictureHandlerClient::ReadPixelMap(MessageParcel &data)
149 {
150 ImageInfo imageInfo;
151 ReadImageInfo(data, imageInfo);
152
153 bool isYuv = data.ReadBool();
154 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadPixelMap isYuv:%{public}d", isYuv);
155 YUVDataInfo yuvInfo;
156 if (isYuv) {
157 ReadYuvDataInfo(data, yuvInfo);
158 }
159
160 bool editable = data.ReadBool();
161 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadPixelMap editable:%{public}d", editable);
162
163 std::unique_ptr<PixelMap> pixelMap;
164 if (isYuv) {
165 #ifdef EXT_PIXEL
166 pixelMap = std::make_unique<PixelYuvExt>();
167 #else
168 pixelMap = std::make_unique<PixelYuv>();
169 #endif
170 } else {
171 pixelMap = std::make_unique<PixelMap>();
172 }
173 pixelMap->SetImageInfo(imageInfo);
174 pixelMap->SetImageYUVInfo(yuvInfo);
175
176 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadPixelMap read surface buffer");
177 ReadSurfaceBuffer(data, pixelMap);
178
179 return pixelMap;
180 }
181
ReadAuxiliaryPicture(MessageParcel & data,std::unique_ptr<Media::Picture> & picture)182 bool PictureHandlerClient::ReadAuxiliaryPicture(MessageParcel &data, std::unique_ptr<Media::Picture> &picture)
183 {
184 AuxiliaryPictureInfo auxiliaryPictureInfo;
185 ReadAuxiliaryPictureInfo(data, auxiliaryPictureInfo);
186
187 std::shared_ptr<PixelMap> pixelMap = ReadPixelMap(data);
188 std::unique_ptr<AuxiliaryPicture> uptr = AuxiliaryPicture::Create(pixelMap,
189 auxiliaryPictureInfo.auxiliaryPictureType, auxiliaryPictureInfo.size);
190 std::shared_ptr<AuxiliaryPicture> auxiliaryPicture;
191 auxiliaryPicture.reset(uptr.get());
192 uptr.release();
193
194 auxiliaryPicture->SetAuxiliaryPictureInfo(auxiliaryPictureInfo);
195
196 int32_t metadataSize = 0;
197 if (data.ReadInt32(metadataSize) && metadataSize >= 0 && metadataSize < MAX_VALUE) {
198 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadAuxiliaryPicture metadataSize: %{public}d", metadataSize);
199 for (int i = 0; i < metadataSize; i++) {
200 MetadataType type = static_cast<MetadataType>(data.ReadInt32());
201 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadAuxiliaryPicture type: %{public}d", type);
202 std::shared_ptr<ImageMetadata> metadataPtr(nullptr);
203 metadataPtr.reset(ExifMetadata::Unmarshalling(data));
204 auxiliaryPicture->SetMetadata(type, metadataPtr);
205 }
206 } else {
207 MEDIA_ERR_LOG("PictureHandlerClient::ReadAuxiliaryPicture metadataSize failed");
208 }
209 picture->SetAuxiliaryPicture(auxiliaryPicture);
210 MEDIA_DEBUG_LOG("PictureHandler::ReadAuxiliaryPicture end");
211 return true;
212 }
213
ReadAuxiliaryPictureInfo(MessageParcel & data,AuxiliaryPictureInfo & auxiliaryPictureInfo)214 bool PictureHandlerClient::ReadAuxiliaryPictureInfo(MessageParcel &data, AuxiliaryPictureInfo &auxiliaryPictureInfo)
215 {
216 auxiliaryPictureInfo.auxiliaryPictureType = static_cast<AuxiliaryPictureType>(data.ReadInt32());
217 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadAuxiliaryPictureInfo auxiliaryPictureType: %{public}d",
218 auxiliaryPictureInfo.auxiliaryPictureType);
219
220 auxiliaryPictureInfo.colorSpace = static_cast<ColorSpace>(data.ReadInt32());
221 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadAuxiliaryPictureInfo colorSpace: %{public}d",
222 auxiliaryPictureInfo.colorSpace);
223
224 auxiliaryPictureInfo.pixelFormat = static_cast<PixelFormat>(data.ReadInt32());
225 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadAuxiliaryPictureInfo pixelFormat: %{public}d",
226 auxiliaryPictureInfo.pixelFormat);
227
228 auxiliaryPictureInfo.rowStride = static_cast<uint32_t>(data.ReadInt32());
229 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadAuxiliaryPictureInfo rowStride: %{public}d",
230 auxiliaryPictureInfo.rowStride);
231
232 auxiliaryPictureInfo.size.height = data.ReadInt32();
233 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadAuxiliaryPictureInfo height: %{public}d",
234 auxiliaryPictureInfo.size.height);
235
236 auxiliaryPictureInfo.size.width = data.ReadInt32();
237 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadAuxiliaryPictureInfo width: %{public}d",
238 auxiliaryPictureInfo.size.width);
239
240 return true;
241 }
242
ReadImageInfo(MessageParcel & data,ImageInfo & imageInfo)243 bool PictureHandlerClient::ReadImageInfo(MessageParcel &data, ImageInfo &imageInfo)
244 {
245 imageInfo.size.width = data.ReadInt32();
246 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadImageInfo width: %{public}d", imageInfo.size.width);
247 imageInfo.size.height = data.ReadInt32();
248 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadImageInfo height: %{public}d", imageInfo.size.height);
249 imageInfo.pixelFormat = static_cast<PixelFormat>(data.ReadInt32());
250 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadImageInfo pixelFormat: %{public}d", imageInfo.pixelFormat);
251 imageInfo.colorSpace = static_cast<ColorSpace>(data.ReadInt32());
252 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadImageInfo colorSpace: %{public}d", imageInfo.colorSpace);
253 imageInfo.alphaType = static_cast<AlphaType>(data.ReadInt32());
254 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadImageInfo alphaType: %{public}d", imageInfo.alphaType);
255 imageInfo.baseDensity = data.ReadInt32();
256 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadImageInfo baseDensity: %{public}d", imageInfo.baseDensity);
257 return true;
258 }
259
ReadYuvDataInfo(MessageParcel & data,YUVDataInfo & info)260 bool PictureHandlerClient::ReadYuvDataInfo(MessageParcel &data, YUVDataInfo &info)
261 {
262 info.imageSize.width = data.ReadInt32();
263 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadYuvDataInfo width: %{public}d", info.imageSize.width);
264 info.imageSize.height = data.ReadInt32();
265 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadYuvDataInfo height: %{public}d", info.imageSize.height);
266 info.yWidth = data.ReadUint32();
267 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadYuvDataInfo yWidth: %{public}d", info.yWidth);
268 info.yHeight = data.ReadUint32();
269 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadYuvDataInfo yHeight: %{public}d", info.yHeight);
270 info.uvWidth = data.ReadUint32();
271 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadYuvDataInfo uvWidth: %{public}d", info.uvWidth);
272 info.uvHeight = data.ReadUint32();
273 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadYuvDataInfo uvHeight: %{public}d", info.uvHeight);
274 info.yStride = data.ReadUint32();
275 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadYuvDataInfo yStride: %{public}d", info.yStride);
276 info.uStride = data.ReadUint32();
277 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadYuvDataInfo uStride: %{public}d", info.uStride);
278 info.vStride = data.ReadUint32();
279 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadYuvDataInfo vStride: %{public}d", info.vStride);
280 info.uvStride = data.ReadUint32();
281 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadYuvDataInfo uvStride: %{public}d", info.uvStride);
282 info.yOffset = data.ReadUint32();
283 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadYuvDataInfo yOffset: %{public}d", info.yOffset);
284 info.uOffset = data.ReadUint32();
285 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadYuvDataInfo uOffset: %{public}d", info.uOffset);
286 info.vOffset = data.ReadUint32();
287 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadYuvDataInfo vOffset: %{public}d", info.vOffset);
288 info.uvOffset = data.ReadUint32();
289 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadYuvDataInfo uvOffset: %{public}d", info.uvOffset);
290 return true;
291 }
292
ReadSurfaceBuffer(MessageParcel & data,std::unique_ptr<PixelMap> & pixelMap)293 bool PictureHandlerClient::ReadSurfaceBuffer(MessageParcel &data, std::unique_ptr<PixelMap> &pixelMap)
294 {
295 bool hasBufferHandle = data.ReadBool();
296 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadSurfaceBuffer hasBufferHandle: %{public}d", hasBufferHandle);
297 if (!hasBufferHandle) {
298 return false;
299 }
300 sptr<SurfaceBuffer> surfaceBuffer = SurfaceBuffer::Create();
301 ReadBufferHandle(data, surfaceBuffer);
302 void* nativeBuffer = surfaceBuffer.GetRefPtr();
303 OHOS::RefBase *ref = reinterpret_cast<OHOS::RefBase *>(nativeBuffer);
304 ref->IncStrongRef(ref);
305 pixelMap->SetPixelsAddr(static_cast<uint8_t*>(surfaceBuffer->GetVirAddr()), nativeBuffer,
306 pixelMap->GetByteCount(), AllocatorType::DMA_ALLOC, nullptr);
307 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadSurfaceBuffer end");
308 return true;
309 }
310
ReadBufferHandle(MessageParcel & data,sptr<SurfaceBuffer> & surfaceBuffer)311 bool PictureHandlerClient::ReadBufferHandle(MessageParcel &data, sptr<SurfaceBuffer> &surfaceBuffer)
312 {
313 uint32_t reserveFds = 0;
314 bool readReserveFdsRet = data.ReadUint32(reserveFds);
315 if (reserveFds < 0 || reserveFds > static_cast<uint32_t>(MAX_VALUE)) {
316 return false;
317 }
318 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadBufferHandle reserveFds: %{public}d", reserveFds);
319 uint32_t reserveInts = 0;
320 bool reserveIntsRet = data.ReadUint32(reserveInts);
321 if (reserveInts < 0 || reserveInts > static_cast<uint32_t>(MAX_VALUE)) {
322 return false;
323 }
324 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadBufferHandle reserveInts: %{public}d", reserveInts);
325
326 size_t handleSize = sizeof(BufferHandle) + (sizeof(int32_t) * (reserveFds + reserveInts));
327 BufferHandle *handle = static_cast<BufferHandle *>(malloc(handleSize));
328 if (handle == nullptr) {
329 MEDIA_ERR_LOG("PictureHandlerClient::ReadBufferHandle malloc BufferHandle failed");
330 return false;
331 }
332 memset_s(handle, handleSize, 0, handleSize);
333
334 handle->reserveFds = reserveFds;
335 handle->reserveInts = reserveInts;
336 handle->width = data.ReadInt32();
337 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadBufferHandle width: %{public}d", handle->width);
338 handle->stride = data.ReadInt32();
339 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadBufferHandle stride: %{public}d", handle->stride);
340 handle->height = data.ReadInt32();
341 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadBufferHandle height: %{public}d", handle->height);
342 handle->size = data.ReadInt32();
343 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadBufferHandle size: %{public}d", handle->size);
344 handle->format = data.ReadInt32();
345 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadBufferHandle format: %{public}d", handle->format);
346 handle->usage = data.ReadUint64();
347 handle->phyAddr = data.ReadUint64();
348
349 int32_t fd = RequestBufferHandlerFd(data.ReadInt32());
350 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadBufferHandle fd: %{public}d", fd);
351 handle->fd = dup(fd);
352 close(fd);
353 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadBufferHandle handle->fd: %{public}d", handle->fd);
354 if (readReserveFdsRet) {
355 for (uint32_t i = 0; i < reserveFds; i++) {
356 int32_t reserveFd = RequestBufferHandlerFd(data.ReadInt32());
357 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadBufferHandle reserve[%{public}d]: %{public}d", i, reserveFd);
358 handle->reserve[i] = dup(reserveFd);
359 close(reserveFd);
360 }
361 }
362
363 if (reserveIntsRet) {
364 for (uint32_t j = 0; j < handle->reserveInts; j++) {
365 handle->reserve[reserveFds + j] = data.ReadInt32();
366 }
367 }
368 surfaceBuffer->SetBufferHandle(handle);
369 return true;
370 }
371
ReadExifMetadata(MessageParcel & data,std::unique_ptr<Media::Picture> & picture)372 bool PictureHandlerClient::ReadExifMetadata(MessageParcel &data, std::unique_ptr<Media::Picture> &picture)
373 {
374 bool hasExifMetadata = data.ReadBool();
375 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadExifMetadata hasExifMetadata:%{public}d", hasExifMetadata);
376 if (!hasExifMetadata) {
377 return true;
378 }
379 ExifMetadata *exifMetadataPtr = ExifMetadata::Unmarshalling(data);
380 auto exifMetadata = std::shared_ptr<ExifMetadata>(exifMetadataPtr);
381 picture->SetExifMetadata(exifMetadata);
382 return true;
383 }
384
ReadMaintenanceData(MessageParcel & data,std::unique_ptr<Media::Picture> & picture)385 bool PictureHandlerClient::ReadMaintenanceData(MessageParcel &data, std::unique_ptr<Media::Picture> &picture)
386 {
387 bool hasMaintenanceData = data.ReadBool();
388 MEDIA_DEBUG_LOG("PictureHandlerClient::ReadMaintenanceData hasMaintenanceData:%{public}d", hasMaintenanceData);
389 if (!hasMaintenanceData) {
390 return true;
391 }
392 sptr<SurfaceBuffer> surfaceBuffer = SurfaceBuffer::Create();
393 ReadBufferHandle(data, surfaceBuffer);
394 return picture->SetMaintenanceData(surfaceBuffer);
395 }
396
RequestBufferHandlerFd(const int32_t & fd)397 int32_t PictureHandlerClient::RequestBufferHandlerFd(const int32_t &fd)
398 {
399 std::string uri = PhotoColumn::PHOTO_REQUEST_PICTURE_BUFFER;
400 MediaFileUtils::UriAppendKeyValue(uri, "fd", std::to_string(fd));
401 MEDIA_DEBUG_LOG("PictureHandlerClient::RequestBufferHandlerFd uri: %{public}s", uri.c_str());
402 Uri requestUri(uri);
403 return UserFileClient::OpenFile(requestUri, MEDIA_FILEMODE_READONLY);
404 }
405 }
406 }