1 /*
2  * Copyright (c) 2023-2023 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 "deferred_photo_processor.h"
17 
18 #include "dp_log.h"
19 #include "dps_event_report.h"
20 
21 namespace OHOS {
22 namespace CameraStandard {
23 namespace DeferredProcessing {
DeferredPhotoProcessor(const int32_t userId,TaskManager * taskManager,std::shared_ptr<PhotoJobRepository> repository,std::shared_ptr<IImageProcessCallbacks> callbacks)24 DeferredPhotoProcessor::DeferredPhotoProcessor(const int32_t userId, TaskManager* taskManager,
25     std::shared_ptr<PhotoJobRepository> repository, std::shared_ptr<IImageProcessCallbacks> callbacks)
26     : userId_(userId),
27       taskManager_(taskManager),
28       repository_(repository),
29       postProcessor_(nullptr),
30       callbacks_(callbacks),
31       requestedImages_()
32 {
33     DP_DEBUG_LOG("entered");
34     postProcessor_ = std::make_shared<PhotoPostProcessor>(userId_, taskManager, this);
35 }
36 
~DeferredPhotoProcessor()37 DeferredPhotoProcessor::~DeferredPhotoProcessor()
38 {
39     DP_DEBUG_LOG("entered");
40     taskManager_ = nullptr;
41     repository_ = nullptr;
42     postProcessor_ = nullptr;
43     callbacks_ = nullptr;
44 }
45 
Initialize()46 void DeferredPhotoProcessor::Initialize()
47 {
48     postProcessor_->Initialize();
49 }
50 
AddImage(const std::string & imageId,bool discardable,DpsMetadata & metadata)51 void DeferredPhotoProcessor::AddImage(const std::string& imageId, bool discardable, DpsMetadata& metadata)
52 {
53     DP_INFO_LOG("entered");
54     repository_->AddDeferredJob(imageId, discardable, metadata);
55     return;
56 }
57 
RemoveImage(const std::string & imageId,bool restorable)58 void DeferredPhotoProcessor::RemoveImage(const std::string& imageId, bool restorable)
59 {
60     DP_INFO_LOG("entered");
61     if (requestedImages_.count(imageId) != 0) {
62         requestedImages_.erase(imageId);
63     }
64     DP_CHECK_ERROR_RETURN_LOG(repository_ == nullptr, "repository_ is nullptr");
65 
66     if (restorable == false) {
67         if (repository_->GetJobStatus(imageId) == PhotoJobStatus::RUNNING) {
68             DP_CHECK_ERROR_RETURN_LOG(postProcessor_ == nullptr, "postProcessor_ is nullptr, RemoveImage failed.");
69             postProcessor_->Interrupt();
70         }
71         DP_CHECK_ERROR_RETURN_LOG(postProcessor_ == nullptr, "postProcessor_ is nullptr, RemoveImage failed.");
72         postProcessor_->RemoveImage(imageId);
73     }
74     repository_->RemoveDeferredJob(imageId, restorable);
75 }
76 
RestoreImage(const std::string & imageId)77 void DeferredPhotoProcessor::RestoreImage(const std::string& imageId)
78 {
79     DP_INFO_LOG("entered");
80     repository_->RestoreJob(imageId);
81     return;
82 }
83 
ProcessImage(const std::string & appName,const std::string & imageId)84 void DeferredPhotoProcessor::ProcessImage(const std::string& appName, const std::string& imageId)
85 {
86     DP_INFO_LOG("entered");
87     if (!repository_->IsOfflineJob(imageId)) {
88         DP_INFO_LOG("imageId is not offlineJob %{public}s", imageId.c_str());
89         return;
90     }
91     requestedImages_.insert(imageId);
92     bool isImageIdValid = repository_->RequestJob(imageId);
93     if (!isImageIdValid) {
94         if (callbacks_) {
95             callbacks_->OnError(userId_, imageId, DpsError::DPS_ERROR_IMAGE_PROC_INVALID_PHOTO_ID);
96         }
97     } else {
98         if (repository_->GetJobPriority(postedImageId_) != PhotoJobPriority::HIGH) {
99             Interrupt();
100         }
101     }
102     return;
103 }
104 
CancelProcessImage(const std::string & imageId)105 void DeferredPhotoProcessor::CancelProcessImage(const std::string& imageId)
106 {
107     DP_INFO_LOG("entered");
108     if (requestedImages_.count(imageId) != 0) {
109         requestedImages_.erase(imageId);
110     }
111     repository_->CancelJob(imageId);
112     return;
113 }
114 
OnProcessDone(const int32_t userId,const std::string & imageId,std::shared_ptr<BufferInfo> bufferInfo)115 void DeferredPhotoProcessor::OnProcessDone(const int32_t userId, const std::string& imageId,
116     std::shared_ptr<BufferInfo> bufferInfo)
117 {
118     DP_INFO_LOG("entered, userId: %{public}d, imageId: %{public}s.", userId, imageId.c_str());
119     //如果已经非高优先级,且任务结果不是全质量的图,那么不用返回给上层了,等下次出全质量图再返回
120     if (!(bufferInfo->IsHighQuality())) {
121         DP_INFO_LOG("not high quality photo");
122         if ((repository_->GetJobPriority(imageId) != PhotoJobPriority::HIGH)) {
123             DP_INFO_LOG("not high quality and not high priority, need retry");
124             repository_->SetJobPending(imageId);
125             return;
126         } else {
127             DP_INFO_LOG("not high quality, but high priority, and process as normal job before, need retry");
128             if (repository_->GetJobRunningPriority(imageId) != PhotoJobPriority::HIGH) {
129                 repository_->SetJobPending(imageId);
130                 return;
131             }
132         }
133     }
134     repository_->SetJobCompleted(imageId);
135     callbacks_->OnProcessDone(userId, imageId, std::move(bufferInfo));
136 }
137 
OnProcessDoneExt(const int32_t userId,const std::string & imageId,std::shared_ptr<BufferInfoExt> bufferInfo)138 void DeferredPhotoProcessor::OnProcessDoneExt(const int32_t userId, const std::string& imageId,
139     std::shared_ptr<BufferInfoExt> bufferInfo)
140 {
141     DP_INFO_LOG("entered");
142     //如果已经非高优先级,且任务结果不是全质量的图,那么不用返回给上层了,等下次出全质量图再返回
143     if (!(bufferInfo->IsHighQuality())) {
144         DP_INFO_LOG("not high quality photo");
145         if ((repository_->GetJobPriority(imageId) != PhotoJobPriority::HIGH)) {
146             DP_INFO_LOG("not high quality and not high priority, need retry");
147             repository_->SetJobPending(imageId);
148             return;
149         } else {
150             DP_INFO_LOG("not high quality, but high priority, and process as normal job before, need retry");
151             if (repository_->GetJobRunningPriority(imageId) != PhotoJobPriority::HIGH) {
152                 repository_->SetJobPending(imageId);
153                 return;
154             }
155         }
156     }
157     repository_->SetJobCompleted(imageId);
158     callbacks_->OnProcessDoneExt(userId, imageId, std::move(bufferInfo));
159 }
160 
OnError(const int32_t userId,const std::string & imageId,DpsError errorCode)161 void DeferredPhotoProcessor::OnError(const int32_t userId, const std::string& imageId, DpsError errorCode)
162 {
163     DP_INFO_LOG("entered");
164     if (errorCode == DpsError::DPS_ERROR_IMAGE_PROC_INTERRUPTED &&
165         repository_->GetJobPriority(imageId) == PhotoJobPriority::HIGH &&
166         requestedImages_.count(imageId) != 0) {
167         repository_->SetJobPending(imageId);
168         return;
169     }
170 
171     if (!IsFatalError(errorCode)) {
172         if (repository_->GetJobPriority(imageId) == PhotoJobPriority::HIGH) {
173             if (repository_->GetJobRunningPriority(imageId) != PhotoJobPriority::HIGH) {
174                 repository_->SetJobPending(imageId);
175                 return;
176             }
177         } else {
178             repository_->SetJobFailed(imageId);
179             return;
180         }
181     }
182     repository_->SetJobFailed(imageId);
183     callbacks_->OnError(userId, imageId, errorCode);
184     return;
185 }
186 
OnStateChanged(const int32_t userId,DpsStatus statusCode)187 void DeferredPhotoProcessor::OnStateChanged(const int32_t userId, DpsStatus statusCode)
188 {
189     (void)(userId);
190     (void)(statusCode);
191 }
192 
NotifyScheduleState(DpsStatus status)193 void DeferredPhotoProcessor::NotifyScheduleState(DpsStatus status)
194 {
195     if (callbacks_) {
196         callbacks_->OnStateChanged(userId_, status);
197     }
198 }
199 
PostProcess(DeferredPhotoWorkPtr work)200 void DeferredPhotoProcessor::PostProcess(DeferredPhotoWorkPtr work)
201 {
202     DP_INFO_LOG("entered");
203     auto executionMode = work->GetExecutionMode();
204     auto imageId = work->GetDeferredPhotoJob()->GetImageId();
205     if (requestedImages_.count(imageId) != 0) {
206         requestedImages_.erase(imageId);
207     }
208     postedImageId_ = imageId;
209     repository_->SetJobRunning(imageId);
210     postProcessor_->SetExecutionMode(executionMode);
211     postProcessor_->ProcessImage(imageId);
212     DPSEventReport::GetInstance().ReportImageModeChange(executionMode);
213     return;
214 }
215 
SetDefaultExecutionMode()216 void DeferredPhotoProcessor::SetDefaultExecutionMode()
217 {
218     DP_INFO_LOG("entered");
219     postProcessor_->SetDefaultExecutionMode();
220 }
221 
Interrupt()222 void DeferredPhotoProcessor::Interrupt()
223 {
224     DP_INFO_LOG("entered");
225     postProcessor_->Interrupt();
226     return;
227 }
228 
GetConcurrency(ExecutionMode mode)229 int DeferredPhotoProcessor::GetConcurrency(ExecutionMode mode)
230 {
231     DP_INFO_LOG("entered");
232     return postProcessor_->GetConcurrency(mode);
233 }
234 
GetPendingImages(std::vector<std::string> & pendingImages)235 bool DeferredPhotoProcessor::GetPendingImages(std::vector<std::string>& pendingImages)
236 {
237     DP_INFO_LOG("entered");
238     if (postProcessor_ == nullptr) {
239         DP_ERR_LOG("postProcessor_ is nullptr");
240         return false;
241     }
242     bool isSuccess = postProcessor_->GetPendingImages(pendingImages);
243     if (isSuccess) {
244         return true;
245     }
246     return false;
247 }
248 
IsFatalError(DpsError errorCode)249 bool DeferredPhotoProcessor::IsFatalError(DpsError errorCode)
250 {
251     DP_INFO_LOG("entered, code: %{public}d", errorCode);
252     if (errorCode == DpsError::DPS_ERROR_IMAGE_PROC_FAILED ||
253         errorCode == DpsError::DPS_ERROR_IMAGE_PROC_INVALID_PHOTO_ID) {
254         return true;
255     } else {
256         return false;
257     }
258 }
259 } // namespace DeferredProcessing
260 } // namespace CameraStandard
261 } // namespace OHOS