• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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