• 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 "photo_job_repository.h"
17 
18 #include "deferred_photo_job.h"
19 #include "dp_log.h"
20 #include "dp_utils.h"
21 #include "dps.h"
22 #include "dps_event_report.h"
23 #include "events_monitor.h"
24 #include "notify_job_changed_command.h"
25 
26 namespace OHOS {
27 namespace CameraStandard {
28 namespace DeferredProcessing {
PhotoJobStateListener(const std::weak_ptr<PhotoJobRepository> & repository)29 PhotoJobStateListener::PhotoJobStateListener(const std::weak_ptr<PhotoJobRepository>& repository)
30     : repository_(repository) {}
31 
UpdateRunningJob(const std::string & imageId,bool running)32 void PhotoJobStateListener::UpdateRunningJob(const std::string& imageId, bool running)
33 {
34     DP_ERR_LOG("UpdateRunningJob: %{public}s, running state: %{public}d", imageId.c_str(), running);
35     auto repository = repository_.lock();
36     DP_CHECK_ERROR_RETURN_LOG(repository == nullptr, "PhotoJobRepository is nullptr.");
37     repository->UpdateRunningJobUnLocked(imageId, running);
38 }
39 
UpdatePriorityJob(JobPriority cur,JobPriority pre)40 void PhotoJobStateListener::UpdatePriorityJob(JobPriority cur, JobPriority pre)
41 {
42     DP_ERR_LOG("UpdatePriorityJob cur: %{public}d, pre: %{public}d", cur, pre);
43     auto repository = repository_.lock();
44     DP_CHECK_ERROR_RETURN_LOG(repository == nullptr, "PhotoJobRepository is nullptr.");
45     repository->UpdatePriotyNumUnLocked(cur, pre);
46 }
47 
UpdateJobSize()48 void PhotoJobStateListener::UpdateJobSize()
49 {
50     DP_ERR_LOG("UpdateJobSize");
51     auto repository = repository_.lock();
52     DP_CHECK_ERROR_RETURN_LOG(repository == nullptr, "PhotoJobRepository is nullptr.");
53     repository->UpdateJobSizeUnLocked();
54 }
55 
TryDoNextJob(const std::string & imageId,bool isTyrDo)56 void PhotoJobStateListener::TryDoNextJob(const std::string& imageId, bool isTyrDo)
57 {
58     DP_ERR_LOG("TryDoNextJob");
59     auto repository = repository_.lock();
60     DP_CHECK_ERROR_RETURN_LOG(repository == nullptr, "PhotoJobRepository is nullptr.");
61     repository->NotifyJobChanged(imageId, isTyrDo);
62 }
63 
PhotoJobRepository(const int32_t userId)64 PhotoJobRepository::PhotoJobRepository(const int32_t userId) : userId_(userId)
65 {
66     DP_DEBUG_LOG("entered, userId: %{public}d", userId_);
67     offlineJobQueue_ = std::make_unique<PhotoJobQueue>(
68         [] (const DeferredPhotoJobPtr& a, const DeferredPhotoJobPtr& b) {return *a > *b;});
69 }
70 
~PhotoJobRepository()71 PhotoJobRepository::~PhotoJobRepository()
72 {
73     DP_INFO_LOG("entered, userId: %{public}d", userId_);
74     backgroundJobMap_.clear();
75     priotyToNum_.clear();
76     offlineJobQueue_->Clear();
77     runningJob_.clear();
78 }
79 
Initialize()80 int32_t PhotoJobRepository::Initialize()
81 {
82     jobChangeListener_ = std::make_shared<PhotoJobStateListener>(weak_from_this());
83     return DP_OK;
84 }
85 
AddDeferredJob(const std::string & imageId,bool discardable,DpsMetadata & metadata)86 void PhotoJobRepository::AddDeferredJob(const std::string& imageId, bool discardable, DpsMetadata& metadata)
87 {
88     DeferredPhotoJobPtr jobPtrFind = GetJobUnLocked(imageId);
89     DP_CHECK_RETURN_LOG(jobPtrFind != nullptr, "DPS_PHOTO: already existed, imageId: %{public}s", imageId.c_str());
90     int32_t type;
91     metadata.Get(DEFERRED_PROCESSING_TYPE_KEY, type);
92     auto jobPtr =
93         std::make_shared<DeferredPhotoJob>(imageId, static_cast<PhotoJobType>(type), discardable, jobChangeListener_);
94     DP_INFO_LOG("DPS_PHOTO: AddJob imageId: %{public}s, type: %{public}d, discardable: %{public}d",
95         imageId.c_str(), type, discardable);
96     if (jobPtr->GetPhotoJobType() == PhotoJobType::BACKGROUND) {
97         backgroundJobMap_.emplace(imageId, jobPtr);
98     } else {
99         offlineJobQueue_->Push(jobPtr);
100     }
101     jobPtr->Prepare();
102     ReportEvent(jobPtr, IDeferredPhotoProcessingSessionIpcCode::COMMAND_ADD_IMAGE);
103 }
104 
RemoveDeferredJob(const std::string & imageId,bool restorable)105 void PhotoJobRepository::RemoveDeferredJob(const std::string& imageId, bool restorable)
106 {
107     DeferredPhotoJobPtr jobPtr = GetJobUnLocked(imageId);
108     DP_CHECK_ERROR_RETURN_LOG(jobPtr == nullptr, "Does not existed, imageId: %{public}s", imageId.c_str());
109     DP_INFO_LOG("DPS_PHOTO: RemoveJob imageId: %{public}s, type: %{public}d, restorable: %{public}d",
110         imageId.c_str(), jobPtr->GetPhotoJobType(), restorable);
111     if (restorable) {
112         jobPtr->SetJobPriority(JobPriority::LOW);
113         offlineJobQueue_->Update(jobPtr);
114         return;
115     }
116 
117     if (jobPtr->GetPhotoJobType() == PhotoJobType::BACKGROUND) {
118         backgroundJobMap_.erase(imageId);
119     } else {
120         offlineJobQueue_->Remove(jobPtr);
121     }
122     jobPtr->Delete();
123     ReportEvent(jobPtr, IDeferredPhotoProcessingSessionIpcCode::COMMAND_REMOVE_IMAGE);
124 }
125 
RequestJob(const std::string & imageId)126 bool PhotoJobRepository::RequestJob(const std::string& imageId)
127 {
128     DeferredPhotoJobPtr jobPtr = GetJobUnLocked(imageId);
129     DP_CHECK_ERROR_RETURN_RET_LOG(jobPtr == nullptr, false, "Does not existed, imageId: %{public}s", imageId.c_str());
130     DP_INFO_LOG("DPS_PHOTO: RequestJob imageId: %{public}s", imageId.c_str());
131     jobPtr->SetJobPriority(JobPriority::HIGH);
132     DP_CHECK_EXECUTE(jobPtr->GetCurStatus() == JobState::FAILED, jobPtr->Prepare());
133     NotifyJobChanged(imageId, true);
134     return true;
135 }
136 
CancelJob(const std::string & imageId)137 void PhotoJobRepository::CancelJob(const std::string& imageId)
138 {
139     DeferredPhotoJobPtr jobPtr = GetJobUnLocked(imageId);
140     DP_CHECK_ERROR_RETURN_LOG(jobPtr == nullptr, "Does not existed, imageId: %{public}s", imageId.c_str());
141     DP_INFO_LOG("DPS_PHOTO: CancelJob imageId: %{public}s", imageId.c_str());
142     jobPtr->SetJobPriority(JobPriority::NORMAL);
143     NotifyJobChanged(imageId, false);
144     ReportEvent(jobPtr, IDeferredPhotoProcessingSessionIpcCode::COMMAND_CANCEL_PROCESS_IMAGE);
145 }
146 
RestoreJob(const std::string & imageId)147 void PhotoJobRepository::RestoreJob(const std::string& imageId)
148 {
149     DeferredPhotoJobPtr jobPtr = GetJobUnLocked(imageId);
150     DP_CHECK_ERROR_RETURN_LOG(jobPtr == nullptr, "Does not existed, imageId: %{public}s", imageId.c_str());
151     DP_INFO_LOG("DPS_PHOTO: RestoreJob imageId: %{public}s", imageId.c_str());
152     jobPtr->SetJobPriority(JobPriority::NORMAL);
153     NotifyJobChanged(imageId, true);
154     ReportEvent(jobPtr, IDeferredPhotoProcessingSessionIpcCode::COMMAND_RESTORE_IMAGE);
155 }
156 
GetJobState(const std::string & imageId)157 JobState PhotoJobRepository::GetJobState(const std::string& imageId)
158 {
159     DeferredPhotoJobPtr jobPtr = GetJobUnLocked(imageId);
160     if (jobPtr == nullptr) {
161         DP_INFO_LOG("Does not existed, imageId: %{public}s", imageId.c_str());
162         return JobState::NONE;
163     } else {
164         return jobPtr->GetCurStatus();
165     }
166 }
167 
GetJob()168 DeferredPhotoJobPtr PhotoJobRepository::GetJob()
169 {
170     DP_INFO_LOG("DPS_PHOTO: offline size: %{public}d, background size: %{public}zu, running job: %{public}zu",
171         offlineJobQueue_->GetSize(), backgroundJobMap_.size(), runningJob_.size());
172     DeferredPhotoJobPtr jobPtr = offlineJobQueue_->Peek();
173     DP_CHECK_RETURN_RET(jobPtr == nullptr || jobPtr->GetCurStatus() >= JobState::RUNNING, nullptr);
174     return jobPtr;
175 }
176 
GetJobPriority(const std::string & imageId)177 JobPriority PhotoJobRepository::GetJobPriority(const std::string& imageId)
178 {
179     DeferredPhotoJobPtr jobPtr = GetJobUnLocked(imageId);
180     DP_CHECK_RETURN_RET(jobPtr == nullptr, JobPriority::NONE);
181     return jobPtr->GetCurPriority();
182 }
183 
GetJobRunningPriority(const std::string & imageId)184 JobPriority PhotoJobRepository::GetJobRunningPriority(const std::string& imageId)
185 {
186     DeferredPhotoJobPtr jobPtr = GetJobUnLocked(imageId);
187     DP_CHECK_RETURN_RET(jobPtr == nullptr, JobPriority::NONE);
188     return jobPtr->GetRunningPriority();
189 }
190 
GetJobTimerId(const std::string & imageId)191 uint32_t PhotoJobRepository::GetJobTimerId(const std::string& imageId)
192 {
193     DeferredPhotoJobPtr jobPtr = GetJobUnLocked(imageId);
194     DP_CHECK_RETURN_RET(jobPtr == nullptr, INVALID_TIMERID);
195     return jobPtr->GetTimerId();
196 }
197 
NotifyJobChanged(const std::string & imageId,bool isTyrDo)198 void PhotoJobRepository::NotifyJobChanged(const std::string& imageId, bool isTyrDo)
199 {
200     offlineJobQueue_->UpdateById(imageId);
201     DP_CHECK_RETURN(!isTyrDo);
202     DP_INFO_LOG("DPS_PHOTO: NotifyJobChanged imageId %{public}s", imageId.c_str());
203     auto ret = DPS_SendCommand<NotifyJobChangedCommand>(userId_);
204     DP_CHECK_ERROR_RETURN_LOG(ret != DP_OK, "NotifyJobChanged failed, ret: %{public}d", ret);
205 }
206 
UpdateRunningJobUnLocked(const std::string & imageId,bool running)207 void PhotoJobRepository::UpdateRunningJobUnLocked(const std::string& imageId, bool running)
208 {
209     if (running) {
210         runningJob_.emplace(imageId);
211         ReportEvent(GetJobUnLocked(imageId), IDeferredPhotoProcessingSessionIpcCode::COMMAND_PROCESS_IMAGE);
212     } else {
213         runningJob_.erase(imageId);
214     }
215     DP_INFO_LOG("DPS_PHOTO: running job: %{public}s, total size: %{public}zu", imageId.c_str(), runningJob_.size());
216 }
217 
UpdatePriotyNumUnLocked(JobPriority cur,JobPriority pre)218 void PhotoJobRepository::UpdatePriotyNumUnLocked(JobPriority cur, JobPriority pre)
219 {
220     auto it = priotyToNum_.find(cur);
221     if (it != priotyToNum_.end()) {
222         (it->second)++;
223     }
224     it = priotyToNum_.find(pre);
225     if (it != priotyToNum_.end()) {
226         (it->second)--;
227     }
228 }
229 
UpdateJobSizeUnLocked()230 void PhotoJobRepository::UpdateJobSizeUnLocked()
231 {
232     EventsMonitor::GetInstance().NotifyPhotoProcessSize(offlineJobQueue_->GetSize(), backgroundJobMap_.size());
233 }
234 
GetJobUnLocked(const std::string & imageId)235 DeferredPhotoJobPtr PhotoJobRepository::GetJobUnLocked(const std::string& imageId)
236 {
237     auto jobPtr = offlineJobQueue_->GetJobById(imageId);
238     if (jobPtr) {
239         DP_DEBUG_LOG("DPS_PHOTO: offline job, imageId: %{public}s", imageId.c_str());
240         return jobPtr;
241     }
242 
243     auto item = backgroundJobMap_.find(imageId);
244     if (item != backgroundJobMap_.end()) {
245         DP_DEBUG_LOG("DPS_PHOTO: background job, imageId: %{public}s", imageId.c_str());
246         return item->second;
247     }
248 
249     return nullptr;
250 }
251 
GetBackgroundJobSize()252 int32_t PhotoJobRepository::GetBackgroundJobSize()
253 {
254     int32_t size = static_cast<int32_t>(backgroundJobMap_.size());
255     DP_DEBUG_LOG("background job size: %{public}d", size);
256     return size;
257 }
258 
GetBackgroundIdleJobSize()259 int32_t PhotoJobRepository::GetBackgroundIdleJobSize()
260 {
261     int32_t size = std::count_if(backgroundJobMap_.begin(), backgroundJobMap_.end(), [](const auto& item) {
262         return item.second->GetCurStatus() < JobState::COMPLETED;
263     });
264     DP_DEBUG_LOG("background idle job size: %{public}d", size);
265     return size;
266 }
267 
GetOfflineJobSize()268 int32_t PhotoJobRepository::GetOfflineJobSize()
269 {
270     DP_DEBUG_LOG("offline job size: %{public}d", offlineJobQueue_->GetSize());
271     return offlineJobQueue_->GetSize();
272 }
273 
GetOfflineIdleJobSize()274 int32_t PhotoJobRepository::GetOfflineIdleJobSize()
275 {
276     auto list = offlineJobQueue_->GetAllElements();
277     int32_t size = std::count_if(list.begin(), list.end(), [](const auto& jobPtr) {
278         return jobPtr->GetCurStatus() < JobState::COMPLETED;
279     });
280     DP_DEBUG_LOG("offline idle job size: %{public}d", size);
281     return size;
282 }
283 
IsBackgroundJob(const std::string & imageId)284 bool PhotoJobRepository::IsBackgroundJob(const std::string& imageId)
285 {
286     return backgroundJobMap_.find(imageId) != backgroundJobMap_.end();
287 }
288 
HasUnCompletedBackgroundJob()289 bool PhotoJobRepository::HasUnCompletedBackgroundJob()
290 {
291     auto it = std::find_if(backgroundJobMap_.begin(), backgroundJobMap_.end(), [](auto& ptr) {
292         return ptr.second->GetCurStatus() == JobState::PENDING;
293     });
294     return it != backgroundJobMap_.end();
295 }
296 
IsNeedInterrupt()297 bool PhotoJobRepository::IsNeedInterrupt()
298 {
299     return std::any_of(runningJob_.begin(), runningJob_.end(), [&](const auto& imageId) {
300         auto jobPtr = GetJobUnLocked(imageId);
301         DP_CHECK_RETURN_RET(jobPtr == nullptr, false);
302         return jobPtr->GetCurPriority() != JobPriority::HIGH;
303     });
304 }
305 
IsHighJob(const std::string & imageId)306 bool PhotoJobRepository::IsHighJob(const std::string& imageId)
307 {
308     DeferredPhotoJobPtr jobPtr = GetJobUnLocked(imageId);
309     DP_CHECK_RETURN_RET(jobPtr == nullptr, false);
310 
311     return jobPtr->GetCurPriority() ==  JobPriority::HIGH;
312 }
313 
HasRunningJob()314 bool PhotoJobRepository::HasRunningJob()
315 {
316     return !runningJob_.empty();
317 }
318 
IsRunningJob(const std::string & imageId)319 bool PhotoJobRepository::IsRunningJob(const std::string& imageId)
320 {
321     return runningJob_.find(imageId) != runningJob_.end();
322 }
323 
ReportEvent(const DeferredPhotoJobPtr & jobPtr,IDeferredPhotoProcessingSessionIpcCode event)324 void PhotoJobRepository::ReportEvent(const DeferredPhotoJobPtr& jobPtr, IDeferredPhotoProcessingSessionIpcCode event)
325 {
326     DP_CHECK_ERROR_RETURN_LOG(jobPtr == nullptr, "DeferredPhotoJob is nullptr.");
327     int32_t highJobNum = priotyToNum_.find(JobPriority::HIGH)->second;
328     int32_t normalJobNum = priotyToNum_.find(JobPriority::NORMAL)->second;
329     int32_t lowJobNum = priotyToNum_.find(JobPriority::LOW)->second;
330     std::string imageId = jobPtr->GetImageId();
331     DPSEventInfo dpsEventInfo;
332     dpsEventInfo.imageId = imageId;
333     dpsEventInfo.userId = userId_;
334     dpsEventInfo.lowJobNum = lowJobNum;
335     dpsEventInfo.normalJobNum = normalJobNum;
336     dpsEventInfo.highJobNum = highJobNum;
337     dpsEventInfo.discardable = jobPtr->GetDiscardable();
338     dpsEventInfo.photoJobType = jobPtr->GetPhotoJobType();
339     dpsEventInfo.operatorStage = static_cast<uint32_t>(event);
340     uint64_t endTime = GetTimestampMilli();
341     switch (static_cast<int32_t>(event)) {
342         case static_cast<int32_t>(IDeferredPhotoProcessingSessionIpcCode::COMMAND_ADD_IMAGE): {
343             dpsEventInfo.dispatchTimeEndTime = endTime;
344             break;
345         }
346         case static_cast<int32_t>(IDeferredPhotoProcessingSessionIpcCode::COMMAND_REMOVE_IMAGE): {
347             dpsEventInfo.removeTimeBeginTime = endTime;
348             break;
349         }
350         case static_cast<int32_t>(IDeferredPhotoProcessingSessionIpcCode::COMMAND_RESTORE_IMAGE): {
351             dpsEventInfo.restoreTimeBeginTime = endTime;
352             break;
353         }
354         case static_cast<int32_t>(IDeferredPhotoProcessingSessionIpcCode::COMMAND_PROCESS_IMAGE): {
355             dpsEventInfo.processTimeBeginTime = endTime;
356             break;
357         }
358     }
359     DPSEventReport::GetInstance().ReportOperateImage(imageId, userId_, dpsEventInfo);
360 }
361 } // namespace DeferredProcessing
362 } // namespace CameraStandard
363 } // namespace OHOS