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