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 #define MLOG_TAG "PhotoAssetProxy"
17 
18 #include <cstdint>
19 #include <string>
20 #include <sstream>
21 
22 #include "media_photo_asset_proxy.h"
23 
24 #include "datashare_abs_result_set.h"
25 #include "datashare_predicates.h"
26 #include "fetch_result.h"
27 #include "media_file_utils.h"
28 #include "media_log.h"
29 #include "medialibrary_errno.h"
30 #include "image_packer.h"
31 #include "media_column.h"
32 #include "datashare_values_bucket.h"
33 #include "media_file_uri.h"
34 #include "medialibrary_tracer.h"
35 #include "userfilemgr_uri.h"
36 #include "datashare_helper.h"
37 #include "media_exif.h"
38 
39 using namespace std;
40 
41 namespace OHOS {
42 namespace Media {
43 const string API_VERSION = "api_version";
44 const string SAVE_PICTURE = "save_picture";
45 const double TIMER_MULTIPLIER = 60.0;
46 const std::unordered_map<CameraShotType, PhotoSubType> CAMERASHOT_TO_SUBTYPE_MAP = {
47     {CameraShotType::MOVING_PHOTO, PhotoSubType::MOVING_PHOTO},
48     {CameraShotType::BURST, PhotoSubType::BURST},
49     {CameraShotType::IMAGE, PhotoSubType::CAMERA},
50     {CameraShotType::VIDEO, PhotoSubType::CAMERA},
51 };
PhotoAssetProxy()52 PhotoAssetProxy::PhotoAssetProxy() {}
53 
PhotoAssetProxy(shared_ptr<DataShare::DataShareHelper> dataShareHelper,CameraShotType cameraShotType,uint32_t callingUid,int32_t userId)54 PhotoAssetProxy::PhotoAssetProxy(shared_ptr<DataShare::DataShareHelper> dataShareHelper, CameraShotType cameraShotType,
55     uint32_t callingUid, int32_t userId)
56 {
57     dataShareHelper_ = dataShareHelper;
58     cameraShotType_ = cameraShotType;
59     callingUid_ = callingUid;
60     userId_ = userId;
61     auto itr = CAMERASHOT_TO_SUBTYPE_MAP.find(cameraShotType);
62     if (itr == CAMERASHOT_TO_SUBTYPE_MAP.end()) {
63         subType_ = PhotoSubType::CAMERA;
64     } else {
65         subType_ = itr->second;
66     }
67     MEDIA_INFO_LOG("init success, shottype: %{public}d, callingUid: %{public}d, userid: %{public}d",
68         static_cast<int32_t>(cameraShotType), callingUid, userId);
69 }
70 
~PhotoAssetProxy()71 PhotoAssetProxy::~PhotoAssetProxy()
72 {
73     if (cameraShotType_ == CameraShotType::MOVING_PHOTO && !isMovingPhotoVideoSaved_) {
74         if (dataShareHelper_ == nullptr) {
75             MEDIA_WARN_LOG("datashareHelper is nullptr");
76             return;
77         }
78         string uri = PAH_DEGENERATE_MOVING_PHOTO;
79         MediaFileUtils::UriAppendKeyValue(uri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
80         Uri updateUri(uri);
81         DataShare::DataSharePredicates predicates;
82         DataShare::DataShareValuesBucket valuesBucket;
83         string fileId = MediaFileUtils::GetIdFromUri(uri_);
84         predicates.EqualTo(MediaColumn::MEDIA_ID, fileId);
85         valuesBucket.Put(PhotoColumn::PHOTO_SUBTYPE, static_cast<int32_t>(PhotoSubType::DEFAULT));
86         int32_t changeRows = dataShareHelper_->Update(updateUri, predicates, valuesBucket);
87         MEDIA_WARN_LOG("Degenerate moving photo: %{public}s, ret: %{public}d", fileId.c_str(), changeRows);
88     }
89 }
90 
91 // 调用之前,必须先AddPhotoProxy,否则无法获取FileAsset对象
GetFileAsset()92 unique_ptr<FileAsset> PhotoAssetProxy::GetFileAsset()
93 {
94     if (dataShareHelper_ == nullptr) {
95         MEDIA_ERR_LOG("Failed to create Asset, datashareHelper is nullptr");
96         return nullptr;
97     }
98 
99     string uri = PAH_QUERY_PHOTO;
100     MediaFileUtils::UriAppendKeyValue(uri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
101     Uri queryUri(uri);
102     DataShare::DataSharePredicates predicates;
103     predicates.EqualTo(MediaColumn::MEDIA_ID, fileId_);
104     DataShare::DatashareBusinessError businessError;
105     vector<string> columns;
106 
107     auto resultSet = dataShareHelper_->Query(queryUri, predicates, columns, &businessError);
108     if (resultSet == nullptr) {
109         MEDIA_ERR_LOG("Failed to query asset, fileId_: %{public}d", fileId_);
110         return nullptr;
111     }
112     auto fetchResult = make_unique<FetchResult<FileAsset>>(resultSet);
113     if (fetchResult == nullptr) {
114         MEDIA_ERR_LOG("fetchResult is nullptr, %{public}d", fileId_);
115         return nullptr;
116     }
117     unique_ptr<FileAsset> fileAsset = fetchResult->GetFirstObject();
118     if (fileAsset != nullptr) {
119         fileAsset->SetResultNapiType(ResultNapiType::TYPE_PHOTOACCESS_HELPER);
120     }
121     return fileAsset;
122 }
123 
GetPhotoAssetUri()124 string PhotoAssetProxy::GetPhotoAssetUri()
125 {
126     return uri_;
127 }
128 
CreatePhotoAsset(const sptr<PhotoProxy> & photoProxy)129 void PhotoAssetProxy::CreatePhotoAsset(const sptr<PhotoProxy> &photoProxy)
130 {
131     if (dataShareHelper_ == nullptr) {
132         MEDIA_ERR_LOG("Failed to create Asset, datashareHelper is nullptr");
133         return;
134     }
135     if (photoProxy->GetTitle().empty()) {
136         MEDIA_ERR_LOG("Failed to create Asset, displayName is empty");
137         return;
138     }
139     if (cameraShotType_ == CameraShotType::BURST && photoProxy->GetBurstKey().empty()) {
140         MEDIA_ERR_LOG("Failed to create Asset, burstKey is empty when CameraShotType::BURST");
141         return;
142     }
143 
144     string displayName = photoProxy->GetTitle() + "." + photoProxy->GetExtension();
145     MediaType mediaType = MediaFileUtils::GetMediaType(displayName);
146     if ((mediaType != MEDIA_TYPE_IMAGE) && (mediaType != MEDIA_TYPE_VIDEO)) {
147         MEDIA_ERR_LOG("Failed to create Asset, invalid file type %{public}d", static_cast<int32_t>(mediaType));
148         return;
149     }
150     DataShare::DataShareValuesBucket values;
151     values.Put(MediaColumn::MEDIA_NAME, displayName);
152     values.Put(MediaColumn::MEDIA_TYPE, static_cast<int32_t>(mediaType));
153     if (cameraShotType_ == CameraShotType::MOVING_PHOTO) {
154         values.Put(PhotoColumn::PHOTO_SUBTYPE, static_cast<int32_t>(PhotoSubType::MOVING_PHOTO));
155     }
156     if (cameraShotType_ == CameraShotType::BURST) {
157         values.Put(PhotoColumn::PHOTO_SUBTYPE, static_cast<int32_t>(PhotoSubType::BURST));
158         values.Put(PhotoColumn::PHOTO_BURST_KEY, photoProxy->GetBurstKey());
159         values.Put(PhotoColumn::PHOTO_BURST_COVER_LEVEL,
160             photoProxy->IsCoverPhoto() ? static_cast<int32_t>(BurstCoverLevelType::COVER)
161                                        : static_cast<int32_t>(BurstCoverLevelType::MEMBER));
162         values.Put(PhotoColumn::PHOTO_DIRTY, -1);
163     }
164     values.Put(MEDIA_DATA_CALLING_UID, static_cast<int32_t>(callingUid_));
165     values.Put(PhotoColumn::PHOTO_IS_TEMP, true);
166     string uri = PAH_CREATE_PHOTO;
167     MediaFileUtils::UriAppendKeyValue(uri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
168     Uri createUri(uri);
169     fileId_ = dataShareHelper_->InsertExt(createUri, values, uri_);
170     if (fileId_ < 0) {
171         MEDIA_ERR_LOG("Failed to create Asset, insert database error!");
172         return;
173     }
174     MEDIA_INFO_LOG(
175         "CreatePhotoAsset Success, photoId: %{public}s, fileId: %{public}d, uri: %{public}s, burstKey: %{public}s",
176         photoProxy->GetPhotoId().c_str(), fileId_, uri_.c_str(), photoProxy->GetBurstKey().c_str());
177 }
178 
isHighQualityPhotoExist(string uri)179 static bool isHighQualityPhotoExist(string uri)
180 {
181     string filePath = MediaFileUri::GetPathFromUri(uri, true);
182     string filePathTemp = filePath + ".high";
183     return MediaFileUtils::IsFileExists(filePathTemp) || MediaFileUtils::IsFileExists(filePath);
184 }
185 
SetPhotoIdForAsset(const sptr<PhotoProxy> & photoProxy,DataShare::DataShareValuesBucket & values)186 void PhotoAssetProxy::SetPhotoIdForAsset(const sptr<PhotoProxy> &photoProxy, DataShare::DataShareValuesBucket &values)
187 {
188     if (photoProxy == nullptr) {
189         MEDIA_ERR_LOG("input param invalid, SetPhotoIdForAsset is failed");
190         return;
191     }
192 
193     if (photoProxy->GetPhotoId() == "") {
194         stringstream result;
195         string displayName = photoProxy->GetTitle();
196         for (size_t i = 0; i < displayName.length(); i++) {
197             if (isdigit(displayName[i])) {
198                 result << displayName[i];
199             }
200         }
201         values.Put(PhotoColumn::PHOTO_ID, result.str());
202     } else {
203         values.Put(PhotoColumn::PHOTO_ID, photoProxy->GetPhotoId());
204     }
205 }
206 
CloseFd(const shared_ptr<DataShare::DataShareHelper> & dataShareHelper,const string & uri,const int32_t fd)207 int32_t CloseFd(const shared_ptr<DataShare::DataShareHelper> &dataShareHelper, const string &uri, const int32_t fd)
208 {
209     MediaLibraryTracer tracer;
210     tracer.Start("CloseFd");
211 
212     int32_t retVal = E_FAIL;
213     DataShare::DataShareValuesBucket valuesBucket;
214     valuesBucket.Put(MEDIA_DATA_DB_URI, uri);
215 
216     if (dataShareHelper != nullptr) {
217         string uriStr = PAH_SCAN_WITHOUT_ALBUM_UPDATE;
218         MediaFileUtils::UriAppendKeyValue(uriStr, API_VERSION, to_string(MEDIA_API_VERSION_V10));
219         Uri closeAssetUri(uriStr);
220 
221         if (close(fd) == E_SUCCESS) {
222             retVal = dataShareHelper->Insert(closeAssetUri, valuesBucket);
223         }
224 
225         if (retVal == E_FAIL) {
226             MEDIA_ERR_LOG("Failed to close the file");
227         }
228     }
229 
230     return retVal;
231 }
232 
SaveImage(int fd,const string & uri,const string & photoId,void * output,size_t writeSize)233 int PhotoAssetProxy::SaveImage(int fd, const string &uri, const string &photoId, void *output, size_t writeSize)
234 {
235     MediaLibraryTracer tracer;
236     tracer.Start("SaveImage");
237 
238     if (fd <= 0) {
239         MEDIA_ERR_LOG("invalid fd");
240         return E_ERR;
241     }
242 
243     if (isHighQualityPhotoExist(uri)) {
244         MEDIA_INFO_LOG("high quality photo exists, discard low quality photo. photoId: %{public}s", photoId.c_str());
245         return E_OK;
246     }
247 
248     int ret = write(fd, output, writeSize);
249     if (ret < 0) {
250         MEDIA_ERR_LOG("write err %{public}d", errno);
251         return ret;
252     }
253     MEDIA_INFO_LOG("Save Low Quality file Success, photoId: %{public}s, size: %{public}zu, ret: %{public}d",
254         photoId.c_str(), writeSize, ret);
255     return E_OK;
256 }
257 
PackAndSaveImage(int fd,const string & uri,const sptr<PhotoProxy> & photoProxy)258 int PhotoAssetProxy::PackAndSaveImage(int fd, const string &uri, const sptr<PhotoProxy> &photoProxy)
259 {
260     MediaLibraryTracer tracer;
261     tracer.Start("PackAndSaveImage");
262 
263     void *imageAddr = photoProxy->GetFileDataAddr();
264     size_t imageSize = photoProxy->GetFileSize();
265     if (imageAddr == nullptr || imageSize == 0) {
266         MEDIA_ERR_LOG("imageAddr is nullptr or imageSize(%{public}zu)==0", imageSize);
267         return E_ERR;
268     }
269 
270     MEDIA_DEBUG_LOG("start pack PixelMap");
271     Media::InitializationOptions opts;
272     opts.pixelFormat = Media::PixelFormat::RGBA_8888;
273     opts.size = {
274         .width = photoProxy->GetWidth(),
275         .height = photoProxy->GetHeight()
276     };
277     auto pixelMap = Media::PixelMap::Create(opts);
278     if (pixelMap == nullptr) {
279         MEDIA_ERR_LOG("Create pixelMap failed.");
280         return E_ERR;
281     }
282     pixelMap->SetPixelsAddr(imageAddr, nullptr, imageSize, Media::AllocatorType::SHARE_MEM_ALLOC, nullptr);
283     auto pixelSize = static_cast<uint32_t>(pixelMap->GetByteCount());
284     if (pixelSize == 0) {
285         MEDIA_ERR_LOG("pixel size is 0.");
286         return E_ERR;
287     }
288 
289     // encode rgba to jpeg
290     auto buffer = new (std::nothrow) uint8_t[pixelSize];
291     if (buffer == nullptr) {
292         MEDIA_ERR_LOG("Failed to new buffer");
293         return E_ERR;
294     }
295     int64_t packedSize = 0L;
296     Media::ImagePacker imagePacker;
297     Media::PackOption packOption;
298     packOption.format = "image/jpeg";
299     imagePacker.StartPacking(buffer, pixelSize, packOption);
300     imagePacker.AddImage(*pixelMap);
301     uint32_t packResult = imagePacker.FinalizePacking(packedSize);
302     if (packResult != E_OK || buffer == nullptr) {
303         MEDIA_ERR_LOG("packet pixelMap failed packResult: %{public}d", packResult);
304         return E_ERR;
305     }
306     MEDIA_INFO_LOG("pack pixelMap success, packedSize: %{public}" PRId64, packedSize);
307 
308     auto ret = SaveImage(fd, uri, photoProxy->GetPhotoId(), buffer, packedSize);
309     SetShootingModeAndGpsInfo(buffer, packedSize, photoProxy, fd);
310     delete[] buffer;
311     return ret;
312 }
313 
SetShootingModeAndGpsInfo(const uint8_t * data,uint32_t size,const sptr<PhotoProxy> & photoProxy,int fd)314 void PhotoAssetProxy::SetShootingModeAndGpsInfo(const uint8_t *data, uint32_t size,
315     const sptr<PhotoProxy> &photoProxy, int fd)
316 {
317     MediaLibraryTracer tracer;
318     tracer.Start("SetShootingModeAndGpsInfo");
319     int32_t shootingMode = photoProxy->GetShootingMode();
320     double latitude = photoProxy->GetLatitude();
321     double longitude = photoProxy->GetLongitude();
322     uint32_t errorCode = 0;
323     SourceOptions opts;
324     tracer.Start("CreateImageSource");
325     unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(data, size, opts, errorCode);
326     tracer.Finish();
327     if (imageSource == nullptr) {
328         MEDIA_ERR_LOG("imageSource is nullptr");
329         return;
330     }
331     uint32_t index = 0;
332     uint32_t ret = imageSource->ModifyImageProperty(index, PHOTO_DATA_IMAGE_ISO_SPEED_LATITUDE_ZZZ,
333         to_string(shootingMode));
334     if (ret != E_OK) {
335         MEDIA_ERR_LOG("modify image property shooting mode fail %{public}d", ret);
336     }
337 
338     ret = imageSource->ModifyImageProperty(index, PHOTO_DATA_IMAGE_GPS_LONGITUDE, LocationValueToString(longitude));
339     if (ret != E_OK) {
340         MEDIA_ERR_LOG("modify image property longitude fail %{public}d", ret);
341     }
342 
343     ret = imageSource->ModifyImageProperty(index, PHOTO_DATA_IMAGE_GPS_LONGITUDE_REF, longitude > 0.0 ? "E" : "W");
344     if (ret != E_OK) {
345         MEDIA_ERR_LOG("modify image property longitude ref fail %{public}d", ret);
346     }
347 
348     ret = imageSource->ModifyImageProperty(index, PHOTO_DATA_IMAGE_GPS_LATITUDE, LocationValueToString(latitude));
349     if (ret != E_OK) {
350         MEDIA_ERR_LOG("modify image property latitude fail %{public}d", ret);
351     }
352 
353     tracer.Start("ModifyImageProperty");
354     ret = imageSource->ModifyImageProperty(index, PHOTO_DATA_IMAGE_GPS_LATITUDE_REF, latitude > 0.0 ? "N" : "S", fd);
355     tracer.Finish();
356     if (ret != E_OK) {
357         MEDIA_ERR_LOG("modify image property latitude ref fail %{public}d", ret);
358     }
359     MEDIA_INFO_LOG("Success.");
360 }
361 
LocationValueToString(double value)362 std::string PhotoAssetProxy::LocationValueToString(double value)
363 {
364     string result = "";
365     double stringValue = value;
366     if (value < 0.0) {
367         stringValue = 0.0 - value;
368     }
369 
370     int degrees = static_cast<int32_t>(stringValue);
371     result = result + to_string(degrees) + ", ";
372     stringValue -= (double)degrees;
373     stringValue *= TIMER_MULTIPLIER;
374     int minutes = (int)stringValue;
375     result = result + to_string(minutes) + ", ";
376     stringValue -= (double)minutes;
377     stringValue *= TIMER_MULTIPLIER;
378     result = result + to_string(stringValue);
379     return result;
380 }
381 
UpdatePhotoQuality(shared_ptr<DataShare::DataShareHelper> & dataShareHelper,const sptr<PhotoProxy> & photoProxy,int32_t fileId,int32_t subType)382 int32_t PhotoAssetProxy::UpdatePhotoQuality(shared_ptr<DataShare::DataShareHelper> &dataShareHelper,
383     const sptr<PhotoProxy> &photoProxy, int32_t fileId, int32_t subType)
384 {
385     string uri = PAH_ADD_IMAGE;
386     MediaFileUtils::UriAppendKeyValue(uri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
387     if (photoProxy->GetFormat() == PhotoFormat::YUV) {
388         MediaFileUtils::UriAppendKeyValue(uri, SAVE_PICTURE, OPRN_ADD_LOWQUALITY_IMAGE);
389     }
390     Uri updateAssetUri(uri);
391     DataShare::DataSharePredicates predicates;
392     predicates.SetWhereClause(MediaColumn::MEDIA_ID + " = ? ");
393     predicates.SetWhereArgs({ to_string(fileId) });
394 
395     DataShare::DataShareValuesBucket valuesBucket;
396     SetPhotoIdForAsset(photoProxy, valuesBucket);
397     valuesBucket.Put(PhotoColumn::PHOTO_DEFERRED_PROC_TYPE, static_cast<int32_t>(photoProxy->GetDeferredProcType()));
398     valuesBucket.Put(MediaColumn::MEDIA_ID, fileId);
399     valuesBucket.Put(PhotoColumn::PHOTO_SUBTYPE, static_cast<int32_t>(subType));
400     valuesBucket.Put(PhotoColumn::PHOTO_QUALITY, static_cast<int32_t>(photoProxy->GetPhotoQuality()));
401 
402     int32_t changeRows = dataShareHelper->Update(updateAssetUri, predicates, valuesBucket);
403     if (changeRows < 0) {
404         MEDIA_ERR_LOG("update fail, error: %{public}d", changeRows);
405     }
406     MEDIA_INFO_LOG("photoId: %{public}s, fileId: %{public}d", photoProxy->GetPhotoId().c_str(), fileId);
407     return changeRows;
408 }
409 
SaveLowQualityPhoto(std::shared_ptr<DataShare::DataShareHelper> & dataShareHelper,const sptr<PhotoProxy> & photoProxy,int32_t fileId,int32_t subType)410 int PhotoAssetProxy::SaveLowQualityPhoto(std::shared_ptr<DataShare::DataShareHelper>  &dataShareHelper,
411     const sptr<PhotoProxy> &photoProxy, int32_t fileId, int32_t subType)
412 {
413     MediaLibraryTracer tracer;
414     tracer.Start("SaveLowQualityPhoto");
415     string uri = PAH_ADD_LOWQUALITY_IMAGE;
416     MediaFileUtils::UriAppendKeyValue(uri, API_VERSION, to_string(MEDIA_API_VERSION_V10));
417     Uri updateAssetUri(uri);
418     DataShare::DataSharePredicates predicates;
419     predicates.SetWhereClause(MediaColumn::MEDIA_ID + " = ? ");
420     predicates.SetWhereArgs({ to_string(fileId) });
421 
422     DataShare::DataShareValuesBucket valuesBucket;
423     valuesBucket.Put(PhotoColumn::PHOTO_ID, photoProxy->GetPhotoId());
424     valuesBucket.Put(PhotoColumn::PHOTO_DEFERRED_PROC_TYPE, static_cast<int32_t>(photoProxy->GetDeferredProcType()));
425     valuesBucket.Put(MediaColumn::MEDIA_ID, fileId);
426     valuesBucket.Put(PhotoColumn::PHOTO_SUBTYPE, static_cast<int32_t>(subType));
427     valuesBucket.Put(PhotoColumn::PHOTO_LATITUDE, photoProxy->GetLatitude());
428     valuesBucket.Put(PhotoColumn::PHOTO_LONGITUDE, photoProxy->GetLongitude());
429 
430     int32_t changeRows = dataShareHelper->Update(updateAssetUri, predicates, valuesBucket);
431     if (changeRows < 0) {
432         MEDIA_ERR_LOG("update fail, error: %{public}d", changeRows);
433     }
434     MEDIA_INFO_LOG("photoId: %{public}s,", photoProxy->GetPhotoId().c_str());
435     photoProxy->Release();
436     return E_OK;
437 }
438 
DealWithLowQualityPhoto(shared_ptr<DataShare::DataShareHelper> & dataShareHelper,int fd,const string & uri,const sptr<PhotoProxy> & photoProxy)439 void PhotoAssetProxy::DealWithLowQualityPhoto(shared_ptr<DataShare::DataShareHelper> &dataShareHelper,
440     int fd, const string &uri, const sptr<PhotoProxy> &photoProxy)
441 {
442     MediaLibraryTracer tracer;
443     tracer.Start("DealWithLowQualityPhoto");
444     MEDIA_INFO_LOG("start photoId: %{public}s format: %{public}d, quality: %{public}d",
445         photoProxy->GetPhotoId().c_str(), photoProxy->GetFormat(), photoProxy->GetPhotoQuality());
446 
447     PhotoFormat photoFormat = photoProxy->GetFormat();
448     if (photoFormat == PhotoFormat::RGBA) {
449         PackAndSaveImage(fd, uri, photoProxy);
450     } else {
451         SaveImage(fd, uri, photoProxy->GetPhotoId(), photoProxy->GetFileDataAddr(), photoProxy->GetFileSize());
452     }
453     photoProxy->Release();
454     CloseFd(dataShareHelper, uri, fd);
455     MEDIA_INFO_LOG("end");
456 }
457 
AddPhotoProxy(const sptr<PhotoProxy> & photoProxy)458 void PhotoAssetProxy::AddPhotoProxy(const sptr<PhotoProxy> &photoProxy)
459 {
460     if (photoProxy == nullptr || dataShareHelper_ == nullptr) {
461         MEDIA_ERR_LOG("input param invalid, photo proxy is nullptr");
462         return;
463     }
464 
465     MediaLibraryTracer tracer;
466     tracer.Start("PhotoAssetProxy::AddPhotoProxy " + photoProxy->GetPhotoId());
467     MEDIA_INFO_LOG("photoId: %{public}s", photoProxy->GetPhotoId().c_str());
468     tracer.Start("PhotoAssetProxy CreatePhotoAsset");
469     CreatePhotoAsset(photoProxy);
470     if (cameraShotType_ == CameraShotType::VIDEO) {
471         return;
472     }
473     if (photoProxy->GetPhotoQuality() == PhotoQuality::LOW ||
474         (photoProxy->GetFormat() == PhotoFormat::YUV && subType_ != PhotoSubType::BURST)) {
475         UpdatePhotoQuality(dataShareHelper_, photoProxy, fileId_, static_cast<int32_t>(subType_));
476     }
477     if (photoProxy->GetFormat() == PhotoFormat::YUV) {
478         photoProxy->Release();
479         tracer.Finish();
480         return;
481     }
482     tracer.Finish();
483 
484     Uri openUri(uri_);
485     int fd = dataShareHelper_->OpenFile(openUri, MEDIA_FILEMODE_READWRITE);
486     if (fd < 0) {
487         MEDIA_ERR_LOG("fd.Get() < 0 fd %{public}d status %{public}d", fd, errno);
488         return;
489     }
490     DealWithLowQualityPhoto(dataShareHelper_, fd, uri_, photoProxy);
491     MEDIA_INFO_LOG("exit");
492 }
493 
GetVideoFd()494 int32_t PhotoAssetProxy::GetVideoFd()
495 {
496     if (dataShareHelper_ == nullptr) {
497         MEDIA_ERR_LOG("Failed to read video of moving photo, datashareHelper is nullptr");
498         return E_ERR;
499     }
500 
501     string videoUri = uri_;
502     MediaFileUtils::UriAppendKeyValue(videoUri, MEDIA_MOVING_PHOTO_OPRN_KEYWORD, OPEN_MOVING_PHOTO_VIDEO);
503     Uri openVideoUri(videoUri);
504     int32_t fd = dataShareHelper_->OpenFile(openVideoUri, MEDIA_FILEMODE_READWRITE);
505     MEDIA_INFO_LOG("GetVideoFd enter, video path: %{public}s, fd: %{public}d", videoUri.c_str(), fd);
506     return fd;
507 }
508 
NotifyVideoSaveFinished()509 void PhotoAssetProxy::NotifyVideoSaveFinished()
510 {
511     isMovingPhotoVideoSaved_ = true;
512     if (dataShareHelper_ == nullptr) {
513         MEDIA_ERR_LOG("datashareHelper is nullptr");
514         return;
515     }
516     string uriStr = PAH_MOVING_PHOTO_SCAN;
517     MediaFileUtils::UriAppendKeyValue(uriStr, API_VERSION, to_string(MEDIA_API_VERSION_V10));
518     Uri uri(uriStr);
519     DataShare::DataSharePredicates predicates;
520     DataShare::DatashareBusinessError businessError;
521     std::vector<std::string> columns { uri_ };
522     dataShareHelper_->Query(uri, predicates, columns, &businessError);
523     MEDIA_INFO_LOG("video save finished %{public}s", uri_.c_str());
524 }
525 } // Media
526 } // OHOS