1 /*
2 * Copyright (c) 2023-2025 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 "basic_definitions.h"
19 #include "deferred_photo_result.h"
20 #include "dp_log.h"
21 #include "dp_timer.h"
22 #include "dp_utils.h"
23 #include "dps.h"
24 #include "dps_event_report.h"
25 #include "photo_process_command.h"
26
27 namespace OHOS {
28 namespace CameraStandard {
29 namespace DeferredProcessing {
30 namespace {
31 constexpr uint32_t MAX_PROC_TIME_MS = 11 * 1000;
32 }
33
DeferredPhotoProcessor(const int32_t userId,const std::shared_ptr<PhotoJobRepository> & repository,const std::shared_ptr<PhotoPostProcessor> & postProcessor)34 DeferredPhotoProcessor::DeferredPhotoProcessor(const int32_t userId,
35 const std::shared_ptr<PhotoJobRepository>& repository, const std::shared_ptr<PhotoPostProcessor>& postProcessor)
36 : userId_(userId), repository_(repository), postProcessor_(postProcessor)
37 {
38 DP_DEBUG_LOG("entered.");
39 }
40
~DeferredPhotoProcessor()41 DeferredPhotoProcessor::~DeferredPhotoProcessor()
42 {
43 DP_INFO_LOG("entered, userId: %{public}d", userId_);
44 }
45
Initialize()46 int32_t DeferredPhotoProcessor::Initialize()
47 {
48 DP_CHECK_ERROR_RETURN_RET_LOG(repository_ == nullptr, DP_NULL_POINTER, "PhotoRepository is nullptr");
49 DP_CHECK_ERROR_RETURN_RET_LOG(postProcessor_ == nullptr, DP_NULL_POINTER, "PhotoPostProcessor is nullptr");
50 result_ = DeferredPhotoResult::Create();
51 DP_CHECK_ERROR_RETURN_RET_LOG(result_ == nullptr, DP_NULL_POINTER, "DeferredPhotoResult is nullptr");
52 initialized_ = true;
53 return DP_OK;
54 }
55
AddImage(const std::string & imageId,bool discardable,DpsMetadata & metadata)56 void DeferredPhotoProcessor::AddImage(const std::string& imageId, bool discardable, DpsMetadata& metadata)
57 {
58 bool isProcess = ProcessCatchResults(imageId);
59 DP_CHECK_RETURN(isProcess);
60 repository_->AddDeferredJob(imageId, discardable, metadata);
61 }
62
RemoveImage(const std::string & imageId,bool restorable)63 void DeferredPhotoProcessor::RemoveImage(const std::string& imageId, bool restorable)
64 {
65 result_->DeRecordHigh(imageId);
66 repository_->RemoveDeferredJob(imageId, restorable);
67 DP_CHECK_RETURN(restorable);
68 DP_CHECK_EXECUTE(repository_->IsRunningJob(imageId), postProcessor_->Interrupt());
69 postProcessor_->RemoveImage(imageId);
70 }
71
RestoreImage(const std::string & imageId)72 void DeferredPhotoProcessor::RestoreImage(const std::string& imageId)
73 {
74 repository_->RestoreJob(imageId);
75 }
76
ProcessImage(const std::string & appName,const std::string & imageId)77 void DeferredPhotoProcessor::ProcessImage(const std::string& appName, const std::string& imageId)
78 {
79 DP_CHECK_RETURN_LOG(repository_->IsBackgroundJob(imageId),
80 "DPS_PHOTO: imageId is backgroundJob %{public}s", imageId.c_str());
81 if (!repository_->RequestJob(imageId)) {
82 OnProcessError(userId_, imageId, DpsError::DPS_ERROR_IMAGE_PROC_INVALID_PHOTO_ID);
83 return;
84 }
85 result_->RecordHigh(imageId);
86 }
87
CancelProcessImage(const std::string & imageId)88 void DeferredPhotoProcessor::CancelProcessImage(const std::string& imageId)
89 {
90 DP_CHECK_RETURN_LOG(repository_->IsBackgroundJob(imageId),
91 "DPS_PHOTO: imageId is backgroundJob %{public}s", imageId.c_str());
92 result_->DeRecordHigh(imageId);
93 repository_->CancelJob(imageId);
94 }
95
DoProcess(const DeferredPhotoJobPtr & job)96 void DeferredPhotoProcessor::DoProcess(const DeferredPhotoJobPtr& job)
97 {
98 auto executionMode = job->GetExecutionMode();
99 auto imageId = job->GetImageId();
100 DP_INFO_LOG("DPS_PHOTO: imageId: %{public}s, executionMode: %{public}d", imageId.c_str(), executionMode);
101 uint32_t timerId = StartTimer(imageId);
102 job->Start(timerId);
103 result_->DeRecordHigh(imageId);
104 postProcessor_->SetExecutionMode(executionMode);
105 postProcessor_->ProcessImage(imageId);
106 DPSEventReport::GetInstance().UpdateExecutionMode(imageId, userId_, executionMode);
107 DPSEventReport::GetInstance().ReportImageModeChange(executionMode);
108 }
109
OnProcessSuccess(const int32_t userId,const std::string & imageId,std::unique_ptr<ImageInfo> imageInfo)110 void DeferredPhotoProcessor::OnProcessSuccess(const int32_t userId, const std::string& imageId,
111 std::unique_ptr<ImageInfo> imageInfo)
112 {
113 DP_CHECK_ERROR_RETURN_LOG(!initialized_, "Not initialized.");
114 DP_INFO_LOG("DPS_PHOTO: userId: %{public}d, imageId: %{public}s, bufferQuality: %{public}d",
115 userId, imageId.c_str(), imageInfo->IsHighQuality());
116 HandleSuccess(userId, imageId, std::move(imageInfo));
117 }
118
OnProcessError(const int32_t userId,const std::string & imageId,DpsError error)119 void DeferredPhotoProcessor::OnProcessError(const int32_t userId, const std::string& imageId, DpsError error)
120 {
121 DP_CHECK_ERROR_RETURN_LOG(!initialized_, "Not initialized.");
122 DP_ERR_LOG("DPS_PHOTO: userId: %{public}d, imageId: %{public}s, dps error: %{public}d.",
123 userId, imageId.c_str(), error);
124 bool isHighJob = repository_->IsHighJob(imageId);
125 HandleError(userId, imageId, error, isHighJob);
126 }
127
NotifyScheduleState(DpsStatus status)128 void DeferredPhotoProcessor::NotifyScheduleState(DpsStatus status)
129 {
130 auto statusCode = MapDpsStatus(status);
131 if (auto callback = GetCallback()) {
132 DP_INFO_LOG("DPS_OHOTO: statusCode: %{public}d", statusCode);
133 callback->OnStateChanged(statusCode);
134 }
135 }
136
Interrupt()137 void DeferredPhotoProcessor::Interrupt()
138 {
139 postProcessor_->Interrupt();
140 }
141
SetDefaultExecutionMode()142 void DeferredPhotoProcessor::SetDefaultExecutionMode()
143 {
144 postProcessor_->SetDefaultExecutionMode();
145 }
146
GetPendingImages(std::vector<std::string> & pendingImages)147 bool DeferredPhotoProcessor::GetPendingImages(std::vector<std::string>& pendingImages)
148 {
149 return postProcessor_->GetPendingImages(pendingImages);
150 }
151
HasRunningJob()152 bool DeferredPhotoProcessor::HasRunningJob()
153 {
154 return repository_->HasRunningJob();
155 }
156
IsIdleState()157 bool DeferredPhotoProcessor::IsIdleState()
158 {
159 DP_DEBUG_LOG("entered.");
160 return repository_->GetOfflineIdleJobSize() == DEFAULT_COUNT &&
161 repository_->GetBackgroundIdleJobSize() == DEFAULT_COUNT;
162 }
163
GetRepository()164 std::shared_ptr<PhotoJobRepository> DeferredPhotoProcessor::GetRepository()
165 {
166 return repository_;
167 }
168
GetPhotoPostProcessor()169 std::shared_ptr<PhotoPostProcessor> DeferredPhotoProcessor::GetPhotoPostProcessor()
170 {
171 return postProcessor_;
172 }
173
HandleSuccess(const int32_t userId,const std::string & imageId,std::unique_ptr<ImageInfo> imageInfo)174 void DeferredPhotoProcessor::HandleSuccess(const int32_t userId, const std::string& imageId,
175 std::unique_ptr<ImageInfo> imageInfo)
176 {
177 StopTimer(imageId);
178 result_->OnSuccess(imageId);
179 auto jobPtr = repository_->GetJobUnLocked(imageId);
180 auto callback = GetCallback();
181 if (jobPtr == nullptr || callback == nullptr) {
182 return;
183 }
184
185 jobPtr->Complete();
186 DP_INFO_LOG("DPS_OHOTO: userId: %{public}d, imageId: %{public}s", userId, imageId.c_str());
187 uint32_t cloudFlag = imageInfo->GetCloudFlag();
188 switch (imageInfo->GetType()) {
189 case CallbackType::IMAGE_PROCESS_DONE: {
190 int32_t dataSize = imageInfo->GetDataSize();
191 sptr<IPCFileDescriptor> ipcFd = imageInfo->GetIPCFileDescriptor();
192 callback->OnProcessImageDone(imageId, ipcFd, dataSize, cloudFlag);
193 break;
194 }
195 case CallbackType::IMAGE_PROCESS_YUV_DONE: {
196 std::shared_ptr<PictureIntf> picture = imageInfo->GetPicture();
197 callback->OnProcessImageDone(imageId, picture, cloudFlag);
198 break;
199 }
200 default:
201 DP_ERR_LOG("Unexpected callback type: %{public}d for imageId: %{public}s",
202 static_cast<int>(imageInfo->GetType()), imageId.c_str());
203 break;
204 }
205 }
206
HandleError(const int32_t userId,const std::string & imageId,DpsError error,bool isHighJob)207 void DeferredPhotoProcessor::HandleError(const int32_t userId, const std::string& imageId,
208 DpsError error, bool isHighJob)
209 {
210 StopTimer(imageId);
211 ErrorType ret = result_->OnError(imageId, error, isHighJob);
212 auto jobPtr = repository_->GetJobUnLocked(imageId);
213 auto callback = GetCallback();
214 if (jobPtr == nullptr || callback == nullptr) {
215 auto errors = std::make_unique<ImageInfo>();
216 errors->SetError(error);
217 result_->RecordResult(imageId, std::move(errors));
218 return;
219 }
220
221 bool needNotify = false;
222 switch (ret) {
223 case ErrorType::RETRY:
224 jobPtr->Prepare();
225 break;
226 case ErrorType::NORMAL_FAILED:
227 jobPtr->Fail();
228 break;
229 case ErrorType::FATAL_NOTIFY:
230 jobPtr->Error();
231 needNotify = true;
232 break;
233 case ErrorType::FAILED_NOTIFY:
234 case ErrorType::HIGH_FAILED:
235 jobPtr->Fail();
236 needNotify = true;
237 break;
238 }
239 DP_CHECK_RETURN(!needNotify);
240
241 auto errorCode = MapDpsErrorCode(error);
242 DP_INFO_LOG("DPS_OHOTO: userId: %{public}d, imageId: %{public}s, error: %{public}d",
243 userId, imageId.c_str(), errorCode);
244 callback->OnError(imageId, errorCode);
245 }
246
StartTimer(const std::string & imageId)247 uint32_t DeferredPhotoProcessor::StartTimer(const std::string& imageId)
248 {
249 auto thisPtr = weak_from_this();
250 uint32_t timerId = DpsTimer::GetInstance().StartTimer([thisPtr, imageId]() {
251 auto process = thisPtr.lock();
252 DP_CHECK_EXECUTE(process != nullptr, process->ProcessPhotoTimeout(imageId));
253 }, MAX_PROC_TIME_MS);
254 DP_INFO_LOG("DPS_TIMER: Start imageId: %{public}s, timerId: %{public}u", imageId.c_str(), timerId);
255 return timerId;
256 }
257
StopTimer(const std::string & imageId)258 void DeferredPhotoProcessor::StopTimer(const std::string& imageId)
259 {
260 uint32_t timerId = repository_->GetJobTimerId(imageId);
261 DP_INFO_LOG("DPS_TIMER: Stop imageId: %{public}s, timeId: %{public}u", imageId.c_str(), timerId);
262 DpsTimer::GetInstance().StopTimer(timerId);
263 }
264
ProcessPhotoTimeout(const std::string & imageId)265 void DeferredPhotoProcessor::ProcessPhotoTimeout(const std::string& imageId)
266 {
267 DP_INFO_LOG("DPS_TIMER: Executed imageId: %{public}s", imageId.c_str());
268 DP_CHECK_EXECUTE(result_->IsNeedReset(), postProcessor_->Reset());
269 auto ret = DPS_SendCommand<PhotoProcessTimeOutCommand>(userId_, imageId, DPS_ERROR_IMAGE_PROC_TIMEOUT);
270 DP_CHECK_ERROR_RETURN_LOG(ret != DP_OK,
271 "process photo timeout imageId: %{public}s failed. ret: %{public}d", imageId.c_str(), ret);
272 }
273
GetCallback()274 sptr<IDeferredPhotoProcessingSessionCallback> DeferredPhotoProcessor::GetCallback()
275 {
276 if (auto session = DPS_GetSessionManager()) {
277 return session->GetCallback(userId_);
278 }
279 return nullptr;
280 }
281
ProcessCatchResults(const std::string & imageId)282 bool DeferredPhotoProcessor::ProcessCatchResults(const std::string& imageId)
283 {
284 auto result = result_->GetCacheResult(imageId);
285 DP_CHECK_RETURN_RET(result == nullptr, false);
286 auto callback = GetCallback();
287 DP_CHECK_RETURN_RET(callback == nullptr, false);
288
289 DP_INFO_LOG("DPS_PHOTO: ProcessCatchResults imageId: %{public}s", imageId.c_str());
290 switch (result->GetType()) {
291 case CallbackType::IMAGE_PROCESS_DONE:
292 callback->OnProcessImageDone(imageId, result->GetIPCFileDescriptor(),
293 result->GetDataSize(), result->GetCloudFlag());
294 break;
295 case CallbackType::IMAGE_PROCESS_YUV_DONE:
296 callback->OnProcessImageDone(imageId, result->GetPicture(), result->GetCloudFlag());
297 break;
298 case CallbackType::IMAGE_ERROR:
299 callback->OnError(imageId, MapDpsErrorCode(result->GetErrorCode()));
300 break;
301 default:
302 break;
303 }
304 result_->DeRecordResult(imageId);
305 return true;
306 }
307 } // namespace DeferredProcessing
308 } // namespace CameraStandard
309 } // namespace OHOS