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 "MultiStagesPhotoCaptureManager"
17 
18 #include "multistages_photo_capture_manager.h"
19 
20 #include "database_adapter.h"
21 #include "image_packer.h"
22 #include "exif_utils.h"
23 #include "medialibrary_asset_operations.h"
24 #include "medialibrary_bundle_manager.h"
25 #include "medialibrary_command.h"
26 #include "medialibrary_errno.h"
27 #include "medialibrary_rdbstore.h"
28 #include "medialibrary_type_const.h"
29 #include "medialibrary_tracer.h"
30 #include "media_file_uri.h"
31 #include "media_file_utils.h"
32 #include "media_log.h"
33 #include "medialibrary_formmap_operations.h"
34 #include "picture_manager_thread.h"
35 #include "multistages_capture_dfx_first_visit.h"
36 #include "multistages_capture_dfx_request_policy.h"
37 #include "multistages_capture_dfx_total_time.h"
38 #include "multistages_capture_dfx_trigger_ratio.h"
39 #include "multistages_capture_request_task_manager.h"
40 #include "request_policy.h"
41 #include "result_set_utils.h"
42 
43 using namespace std;
44 #ifdef ABILITY_CAMERA_SUPPORT
45 using namespace OHOS::CameraStandard;
46 #endif
47 
48 namespace OHOS {
49 namespace Media {
50 const int32_t SAVE_PICTURE_TIMEOUT_SEC = 20;
51 
MultiStagesPhotoCaptureManager()52 MultiStagesPhotoCaptureManager::MultiStagesPhotoCaptureManager()
53 {
54     deferredProcSession_ = make_shared<DeferredPhotoProcessingAdapter>();
55 }
56 
~MultiStagesPhotoCaptureManager()57 MultiStagesPhotoCaptureManager::~MultiStagesPhotoCaptureManager() {}
58 
GetInstance()59 MultiStagesPhotoCaptureManager& MultiStagesPhotoCaptureManager::GetInstance()
60 {
61     static MultiStagesPhotoCaptureManager instance;
62     return instance;
63 }
64 
Init()65 bool MultiStagesPhotoCaptureManager::Init()
66 {
67     SyncWithDeferredProcSession();
68     return true;
69 }
70 
CancelRequestAndRemoveImage(const vector<string> & columns)71 void MultiStagesPhotoCaptureManager::CancelRequestAndRemoveImage(const vector<string> &columns)
72 {
73     if (columns.size() < 1) {
74         MEDIA_ERR_LOG("invalid param");
75         return;
76     }
77     int32_t fileId = stoi(columns[0]);
78     string photoId = MultiStagesCaptureRequestTaskManager::GetProcessingPhotoId(fileId);
79     MEDIA_INFO_LOG("fileId: %{public}d, photoId: %{public}s", fileId, photoId.c_str());
80     CancelProcessRequest(photoId);
81     RemoveImage(photoId, false);
82 }
83 
HandleMultiStagesOperation(MediaLibraryCommand & cmd,const vector<string> & columns)84 shared_ptr<OHOS::NativeRdb::ResultSet> MultiStagesPhotoCaptureManager::HandleMultiStagesOperation(
85     MediaLibraryCommand &cmd, const vector<string> &columns)
86 {
87     switch (cmd.GetOprnType()) {
88         case OperationType::PROCESS_IMAGE: {
89             int fileId = std::stoi(columns[0]); // 0 indicates file id
90             int deliveryMode = std::stoi(columns[1]); // 1 indicates delivery mode
91             ProcessImage(fileId, deliveryMode);
92             MultiStagesCaptureDfxTriggerRatio::GetInstance().SetTrigger(MultiStagesCaptureTriggerType::THIRD_PART);
93             break;
94         }
95         case OperationType::ADD_IMAGE: {
96             AddImage(cmd);
97             break;
98         }
99         case OperationType::SET_LOCATION: {
100             UpdateLocation(cmd.GetValueBucket());
101             break;
102         }
103         case OperationType::CANCEL_PROCESS_IMAGE: {
104             string photoId = columns[0]; // 0 indicates photo id
105             MEDIA_INFO_LOG("cancel request photoId: %{public}s", photoId.c_str());
106             CancelProcessRequest(photoId);
107             break;
108         }
109         case OperationType::REMOVE_MSC_TASK: {
110             CancelRequestAndRemoveImage(columns);
111             break;
112         }
113         case OperationType::ADD_LOWQUALITY_IMAGE: {
114             MEDIA_DEBUG_LOG("save low quality Image");
115             SaveLowQualityImageInfo(cmd);
116             break;
117         }
118         default:
119             break;
120     }
121     return nullptr;
122 }
123 
SaveLowQualityImageInfo(MediaLibraryCommand & cmd)124 void MultiStagesPhotoCaptureManager::SaveLowQualityImageInfo(MediaLibraryCommand &cmd)
125 {
126     auto values = cmd.GetValueBucket();
127     string photoId = "";
128     ValueObject valueObject;
129     if (values.GetObject(PhotoColumn::PHOTO_ID, valueObject)) {
130         valueObject.GetString(photoId);
131     }
132     int32_t deferredProcType = -1;
133     if (values.GetObject(PhotoColumn::PHOTO_DEFERRED_PROC_TYPE, valueObject)) {
134         valueObject.GetInt(deferredProcType);
135     }
136     int32_t fileId = 0;
137     if (values.GetObject(MediaColumn::MEDIA_ID, valueObject)) {
138         valueObject.GetInt(fileId);
139     }
140 }
141 
142 // 低质量入缓存
DealLowQualityPicture(const std::string & imageId,std::shared_ptr<Media::Picture> picture,bool isEdited)143 void MultiStagesPhotoCaptureManager::DealLowQualityPicture(const std::string &imageId,
144     std::shared_ptr<Media::Picture> picture, bool isEdited)
145 {
146     auto pictureManagerThread = PictureManagerThread::GetInstance();
147     if (pictureManagerThread == nullptr) {
148         return;
149     }
150     if (pictureManagerThread->IsExsitPictureByImageId(imageId)) {
151         return;
152     }
153     // 将低质量图存入缓存
154     time_t currentTime;
155     if ((currentTime = time(NULL)) == -1) {
156         MEDIA_ERR_LOG("Get time is error");
157         currentTime = time(NULL);
158     }
159     time_t expireTime = currentTime + SAVE_PICTURE_TIMEOUT_SEC;
160     std::string imageIdInPair = imageId;
161     sptr<PicturePair> picturePair = new PicturePair(std::move(picture), imageIdInPair, expireTime, true, false);
162     // 存低质量裸picture
163     pictureManagerThread->InsertPictureData(imageId, picturePair, LOW_QUALITY_PICTURE);
164     MEDIA_INFO_LOG("photoid: %{public}s", imageId.c_str());
165 }
166 
IsHighQualityPhotoExist(const std::string & uri)167 bool MultiStagesPhotoCaptureManager::IsHighQualityPhotoExist(const std::string &uri)
168 {
169     string filePath = MediaFileUri::GetPathFromUri(uri, true);
170     string filePathTemp = filePath + ".high";
171     return MediaFileUtils::IsFileExists(filePathTemp) || MediaFileUtils::IsFileExists(filePath);
172 }
173 
SaveLowQualityPicture(const std::string & imageId)174 void MultiStagesPhotoCaptureManager::SaveLowQualityPicture(const std::string &imageId)
175 {
176     MEDIA_INFO_LOG("photoid: %{public}s", imageId.c_str());
177     auto pictureManagerThread = PictureManagerThread::GetInstance();
178     if (pictureManagerThread == nullptr) {
179         return;
180     }
181     pictureManagerThread->SaveLowQualityPicture(imageId);
182 }
183 
184 // 高质量编辑图片存20S
DealHighQualityPicture(const std::string & imageId,std::shared_ptr<Media::Picture> picture,bool isEdited)185 void MultiStagesPhotoCaptureManager::DealHighQualityPicture(const std::string &imageId,
186     std::shared_ptr<Media::Picture> picture, bool isEdited)
187 {
188     MEDIA_INFO_LOG("photoid: %{public}s", imageId.c_str());
189     auto pictureManagerThread = PictureManagerThread::GetInstance();
190     if (pictureManagerThread == nullptr) {
191         return;
192     }
193     // 将低质量图存入缓存
194     time_t currentTime;
195     if ((currentTime = time(NULL)) == -1) {
196         MEDIA_ERR_LOG("Get time is error");
197         currentTime = time(NULL);
198     }
199     time_t expireTime = currentTime + SAVE_PICTURE_TIMEOUT_SEC;
200     std::string imageIdInPair = imageId;
201     sptr<PicturePair> picturePair= new PicturePair(std::move(picture), imageIdInPair, expireTime, true, isEdited);
202     pictureManagerThread->InsertPictureData(imageId, picturePair, HIGH_QUALITY_PICTURE);
203 }
204 
UpdateDbInfo(MediaLibraryCommand & cmd)205 int32_t MultiStagesPhotoCaptureManager::UpdateDbInfo(MediaLibraryCommand &cmd)
206 {
207     MediaLibraryCommand cmdLocal (OperationObject::FILESYSTEM_PHOTO, OperationType::UPDATE);
208     auto values = cmd.GetValueBucket();
209     ValueObject valueObject;
210     int32_t photoQuality = static_cast<int32_t>(MultiStagesPhotoQuality::LOW);
211     if (values.GetObject(PhotoColumn::PHOTO_QUALITY, valueObject)) {
212         valueObject.GetInt(photoQuality);
213     }
214     if (photoQuality == static_cast<int32_t>(MultiStagesPhotoQuality::LOW)) {
215         values.PutInt(MEDIA_DATA_DB_DIRTY, -1); // prevent uploading low-quality photo
216     }
217     cmdLocal.SetValueBucket(values);
218     cmdLocal.GetAbsRdbPredicates()->SetWhereClause(cmd.GetAbsRdbPredicates()->GetWhereClause());
219     cmdLocal.GetAbsRdbPredicates()->SetWhereArgs(cmd.GetAbsRdbPredicates()->GetWhereArgs());
220     auto result = DatabaseAdapter::Update(cmdLocal);
221     if (result != NativeRdb::E_OK) {
222         MEDIA_ERR_LOG("update failed");
223     }
224     return result;
225 }
226 
UpdateLocation(const NativeRdb::ValuesBucket & values)227 void MultiStagesPhotoCaptureManager::UpdateLocation(const NativeRdb::ValuesBucket &values)
228 {
229     MediaLibraryTracer tracer;
230     tracer.Start("UpdateLocation");
231     double longitude = 0;
232     ValueObject valueObject;
233     if (values.GetObject(PhotoColumn::PHOTO_LONGITUDE, valueObject)) {
234         valueObject.GetDouble(longitude);
235     }
236     double latitude = 0;
237     if (values.GetObject(PhotoColumn::PHOTO_LATITUDE, valueObject)) {
238         valueObject.GetDouble(latitude);
239     }
240 
241     int32_t fileId = 0;
242     if (values.GetObject(MediaColumn::MEDIA_ID, valueObject)) {
243         valueObject.GetInt(fileId);
244     }
245 
246     MediaLibraryCommand queryCmd(OperationObject::FILESYSTEM_PHOTO, OperationType::QUERY);
247     queryCmd.GetAbsRdbPredicates()->SetWhereClause(MediaColumn::MEDIA_ID + " = " + to_string(fileId));
248     vector<string> columns { MediaColumn::MEDIA_FILE_PATH };
249 
250     auto resultSet = DatabaseAdapter::Query(queryCmd, columns);
251     if (resultSet == nullptr || resultSet->GoToFirstRow() != 0) {
252         MEDIA_ERR_LOG("result set is empty");
253         return;
254     }
255     string path = GetStringVal(MediaColumn::MEDIA_FILE_PATH, resultSet);
256     resultSet->Close();
257 
258     // update exif info
259     auto ret = ExifUtils::WriteGpsExifInfo(path, longitude, latitude);
260     if (ret != E_OK) {
261         MEDIA_ERR_LOG("write gps info fail");
262         return;
263     }
264 
265     string originPath = MediaLibraryAssetOperations::GetEditDataSourcePath(path);
266     if (MediaFileUtils::IsFileExists(originPath)) {
267         // write gps info if this photo was edited.
268         auto ret = ExifUtils::WriteGpsExifInfo(path, longitude, latitude);
269         if (ret != E_OK) {
270             MEDIA_ERR_LOG("write origin file gps info fail");
271             return;
272         }
273     }
274 
275     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_PHOTO, OperationType::UPDATE);
276     cmd.GetAbsRdbPredicates()->EqualTo(PhotoColumn::MEDIA_ID, fileId);
277     ValuesBucket updateValues;
278     updateValues.PutDouble(MEDIA_DATA_DB_LATITUDE, latitude);
279     updateValues.PutDouble(MEDIA_DATA_DB_LONGITUDE, longitude);
280     cmd.SetValueBucket(updateValues);
281 
282     auto result = DatabaseAdapter::Update(cmd);
283     if (result != NativeRdb::E_OK) {
284         MEDIA_ERR_LOG("update fail fileId: %{public}d", fileId);
285     }
286 }
287 
AddImageInternal(int32_t fileId,const string & photoId,int32_t deferredProcType,bool discardable)288 void MultiStagesPhotoCaptureManager::AddImageInternal(int32_t fileId, const string &photoId, int32_t deferredProcType,
289     bool discardable)
290 {
291     MultiStagesCaptureRequestTaskManager::AddPhotoInProgress(fileId, photoId, discardable);
292 
293 #ifdef ABILITY_CAMERA_SUPPORT
294     DpsMetadata metadata;
295     metadata.Set(CameraStandard::DEFERRED_PROCESSING_TYPE_KEY, deferredProcType);
296     deferredProcSession_->AddImage(photoId, metadata, discardable);
297 #endif
298 }
299 
AddImage(int32_t fileId,const string & photoId,int32_t deferredProcType)300 void MultiStagesPhotoCaptureManager::AddImage(int32_t fileId, const string &photoId, int32_t deferredProcType)
301 {
302     if (photoId.empty()) {
303         MEDIA_ERR_LOG("photo is empty");
304         return;
305     }
306     MEDIA_INFO_LOG("enter fileId: %{public}d, photoId: %{public}s, deferredProcType: %{public}d", fileId,
307         photoId.c_str(), deferredProcType);
308 
309     // called when camera low quality photo saved, isTrashed must be false.
310     AddImageInternal(fileId, photoId, deferredProcType, false);
311 }
312 
AddImage(MediaLibraryCommand & cmd)313 void MultiStagesPhotoCaptureManager::AddImage(MediaLibraryCommand &cmd)
314 {
315     MEDIA_DEBUG_LOG("calling addImage");
316     UpdateDbInfo(cmd);
317     auto values = cmd.GetValueBucket();
318     ValueObject valueObject;
319     int32_t photoQuality = static_cast<int32_t>(MultiStagesPhotoQuality::LOW);
320     if (values.GetObject(PhotoColumn::PHOTO_QUALITY, valueObject)) {
321         valueObject.GetInt(photoQuality);
322     }
323     string photoId = "";
324     if (values.GetObject(PhotoColumn::PHOTO_ID, valueObject)) {
325         valueObject.GetString(photoId);
326     }
327     auto pictureManagerThread = PictureManagerThread::GetInstance();
328     if (pictureManagerThread == nullptr) {
329         return;
330     }
331     if (photoQuality == static_cast<int32_t>(MultiStagesPhotoQuality::FULL)) {
332         pictureManagerThread->SavePictureWithImageId(photoId);
333         UpdatePictureQuality(photoId);
334         return;
335     }
336     int32_t deferredProcType = -1;
337     if (values.GetObject(PhotoColumn::PHOTO_DEFERRED_PROC_TYPE, valueObject)) {
338         valueObject.GetInt(deferredProcType);
339     }
340     int32_t fileId = 0;
341     if (values.GetObject(MediaColumn::MEDIA_ID, valueObject)) {
342         valueObject.GetInt(fileId);
343     }
344     AddImage(fileId, photoId, deferredProcType);
345     MultiStagesCaptureDfxTotalTime::GetInstance().AddStartTime(photoId);
346     MultiStagesCaptureDfxTriggerRatio::GetInstance().SetTrigger(MultiStagesCaptureTriggerType::AUTO);
347     if (OPRN_ADD_LOWQUALITY_IMAGE == cmd.GetQuerySetParam("save_picture")) {
348         MEDIA_DEBUG_LOG("save last low quality Image");
349         SaveLowQualityImageInfo(cmd);
350     }
351 }
352 
UpdatePictureQuality(const std::string & photoId)353 int32_t MultiStagesPhotoCaptureManager::UpdatePictureQuality(const std::string &photoId)
354 {
355     MediaLibraryTracer tracer;
356     tracer.Start("UpdatePictureQuality " + photoId);
357     MediaLibraryCommand updateCmd(OperationObject::FILESYSTEM_PHOTO, OperationType::UPDATE);
358     NativeRdb::ValuesBucket updateValues;
359     updateValues.PutInt(PhotoColumn::PHOTO_QUALITY, static_cast<int32_t>(MultiStagesPhotoQuality::FULL));
360     updateCmd.SetValueBucket(updateValues);
361     updateCmd.GetAbsRdbPredicates()->EqualTo(PhotoColumn::PHOTO_ID, photoId);
362     int32_t updatePhotoQualityResult = DatabaseAdapter::Update(updateCmd);
363     updateCmd.GetAbsRdbPredicates()->EqualTo(PhotoColumn::PHOTO_IS_TEMP, false);
364     updateCmd.GetAbsRdbPredicates()->NotEqualTo(PhotoColumn::PHOTO_SUBTYPE,
365         to_string(static_cast<int32_t>(PhotoSubType::MOVING_PHOTO)));
366     NativeRdb::ValuesBucket updateValuesDirty;
367     updateValuesDirty.PutInt(PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(DirtyType::TYPE_NEW));
368     updateCmd.SetValueBucket(updateValuesDirty);
369     auto isDirtyResult = DatabaseAdapter::Update(updateCmd);
370     if (isDirtyResult < 0) {
371         MEDIA_WARN_LOG("update dirty flag fail, photoId: %{public}s", photoId.c_str());
372     }
373     return updatePhotoQualityResult;
374 }
375 
SyncWithDeferredProcSessionInternal()376 void MultiStagesPhotoCaptureManager::SyncWithDeferredProcSessionInternal()
377 {
378     MEDIA_INFO_LOG("enter");
379     // 进程重启场景,媒体库需要和延时子服务同步
380     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_PHOTO, OperationType::QUERY);
381     string where = MEDIA_DATA_DB_PHOTO_ID + " is not null and " +
382         MEDIA_DATA_DB_PHOTO_QUALITY + " > 0 and " + MEDIA_DATA_DB_MEDIA_TYPE + " = " +
383         to_string(static_cast<int32_t>(MediaType::MEDIA_TYPE_IMAGE));
384     cmd.GetAbsRdbPredicates()->SetWhereClause(where);
385     vector<string> columns { MEDIA_DATA_DB_ID, MEDIA_DATA_DB_PHOTO_ID, MEDIA_DATA_DB_DATE_TRASHED,
386         MEDIA_DATA_DB_DEFERRED_PROC_TYPE };
387 
388     auto resultSet = DatabaseAdapter::Query(cmd, columns);
389     if (resultSet == nullptr || resultSet->GoToFirstRow() != 0) {
390         MEDIA_ERR_LOG("result set is empty");
391         return;
392     }
393 
394     MediaLibraryTracer tracer;
395     tracer.Start("MultiStagesPhotoCaptureManager::SyncWithDeferredProcSession");
396 
397     deferredProcSession_->BeginSynchronize();
398     do {
399         int32_t fileId = GetInt32Val(MEDIA_DATA_DB_ID, resultSet);
400         string photoId = GetStringVal(MEDIA_DATA_DB_PHOTO_ID, resultSet);
401         bool isTrashed = GetInt32Val(MEDIA_DATA_DB_DATE_TRASHED, resultSet) > 0;
402         if (setOfDeleted_.find(fileId) != setOfDeleted_.end()) {
403             MEDIA_INFO_LOG("remove image, fileId: %{public}d, photoId: %{public}s", fileId, photoId.c_str());
404             deferredProcSession_->RemoveImage(photoId);
405             continue;
406         }
407         MEDIA_INFO_LOG("AddImage fileId: %{public}d, photoId: %{public}s", fileId, photoId.c_str());
408         int32_t deferredProcType = GetInt32Val(MEDIA_DATA_DB_DEFERRED_PROC_TYPE, resultSet);
409         AddImageInternal(fileId, photoId, deferredProcType, isTrashed);
410     } while (!resultSet->GoToNextRow());
411     resultSet->Close();
412 
413     deferredProcSession_->EndSynchronize();
414     MEDIA_INFO_LOG("exit");
415 }
416 
SyncWithDeferredPhotoProcSessionAsync(AsyncTaskData * data)417 static void SyncWithDeferredPhotoProcSessionAsync(AsyncTaskData *data)
418 {
419     MultiStagesPhotoCaptureManager::GetInstance().SyncWithDeferredProcSessionInternal();
420 }
421 
SyncWithDeferredProcSession()422 void MultiStagesPhotoCaptureManager::SyncWithDeferredProcSession()
423 {
424     shared_ptr<MediaLibraryAsyncWorker> asyncWorker = MediaLibraryAsyncWorker::GetInstance();
425     if (asyncWorker == nullptr) {
426         MEDIA_INFO_LOG("can not get async worker");
427         return;
428     }
429 
430     shared_ptr<MediaLibraryAsyncTask> asyncTask =
431         make_shared<MediaLibraryAsyncTask>(SyncWithDeferredPhotoProcSessionAsync, nullptr);
432     if (asyncTask == nullptr) {
433         MEDIA_ERR_LOG("SyncWithDeferredProcSession create task fail");
434         return;
435     }
436     MEDIA_INFO_LOG("SyncWithDeferredProcSession add task success");
437     asyncWorker->AddTask(asyncTask, false);
438 }
439 
CancelProcessRequest(const string & photoId)440 bool MultiStagesPhotoCaptureManager::CancelProcessRequest(const string &photoId)
441 {
442     if (!MultiStagesCaptureRequestTaskManager::IsPhotoInProcess(photoId)) {
443         MEDIA_ERR_LOG("photoId is empty or not in process");
444         return false;
445     }
446 
447     int32_t currentRequestCount =
448         MultiStagesCaptureRequestTaskManager::UpdatePhotoInProcessRequestCount(photoId, RequestType::CANCEL_REQUEST);
449     if (currentRequestCount > 0) {
450         MEDIA_ERR_LOG("not cancel request because request count(%{public}d) greater than 0", currentRequestCount);
451 
452         return false;
453     }
454     auto isCancelSucc = deferredProcSession_->CancelProcessImage(photoId);
455     MEDIA_INFO_LOG("cancel request isCancelSucc: %{public}d", isCancelSucc);
456 
457     return true;
458 }
459 
RemoveImage(const string & photoId,bool isRestorable)460 void MultiStagesPhotoCaptureManager::RemoveImage(const string &photoId, bool isRestorable)
461 {
462     if (!MultiStagesCaptureRequestTaskManager::IsPhotoInProcess(photoId)) {
463         // In order to ensure image can be completely deleted, do not return here, only record the log.
464         MEDIA_ERR_LOG("photoId is empty or not in process ");
465     }
466 
467     MultiStagesCaptureRequestTaskManager::RemovePhotoInProgress(photoId, isRestorable);
468     deferredProcSession_->RemoveImage(photoId, isRestorable);
469 }
470 
RestoreImage(const string & photoId)471 void MultiStagesPhotoCaptureManager::RestoreImage(const string &photoId)
472 {
473     if (photoId.empty()) {
474         MEDIA_DEBUG_LOG("photoId is empty");
475     }
476 
477     MultiStagesCaptureRequestTaskManager::UpdatePhotoInProgress(photoId);
478     deferredProcSession_->RestoreImage(photoId);
479 }
480 
ProcessImage(int fileId,int deliveryMode)481 void MultiStagesPhotoCaptureManager::ProcessImage(int fileId, int deliveryMode)
482 {
483     string photoId = MultiStagesCaptureRequestTaskManager::GetProcessingPhotoId(fileId) ;
484     if (photoId.size() == 0) {
485         MEDIA_ERR_LOG("processimage image id is invalid, fileId: %{public}d", fileId);
486         return;
487     }
488 
489     string callerBundleName = MediaLibraryBundleManager::GetInstance()->GetClientBundleName();
490 
491     MultiStagesCaptureDfxTriggerRatio::GetInstance().SetTrigger(MultiStagesCaptureTriggerType::THIRD_PART);
492     MultiStagesCaptureDfxRequestPolicy::GetInstance().SetPolicy(callerBundleName,
493         static_cast<RequestPolicy>(deliveryMode));
494     MultiStagesCaptureDfxFirstVisit::GetInstance().Report(photoId);
495     int32_t currentRequestCount =
496         MultiStagesCaptureRequestTaskManager::UpdatePhotoInProcessRequestCount(photoId, RequestType::REQUEST);
497     MEDIA_INFO_LOG("processimage, pkg name: %{public}s, photoid %{public}s, mode: %{public}d, count: %{public}d",
498         callerBundleName.c_str(), photoId.c_str(), deliveryMode, currentRequestCount);
499     if ((deliveryMode == static_cast<int32_t>(RequestPolicy::HIGH_QUALITY_MODE) ||
500         deliveryMode == static_cast<int32_t>(RequestPolicy::BALANCE_MODE)) &&
501         currentRequestCount <= 1) {
502         deferredProcSession_->ProcessImage(callerBundleName, photoId);
503     }
504 }
505 
IsPhotoDeleted(const std::string & photoId)506 bool MultiStagesPhotoCaptureManager::IsPhotoDeleted(const std::string &photoId)
507 {
508     if (!MultiStagesCaptureRequestTaskManager::IsPhotoInProcess(photoId)) {
509         return false;
510     }
511 
512     return true;
513 }
514 } // namespace Media
515 } // namespace OHOS