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_controller.h"
17
18 #include "dp_utils.h"
19 #include "dp_log.h"
20 #include "events_monitor.h"
21 #include "dps_event_report.h"
22 #include <cstdint>
23
24 namespace OHOS {
25 namespace CameraStandard {
26
27 namespace {
28 constexpr int32_t DURATIONMS_500 = 500;
29 }
30
31 namespace DeferredProcessing {
32
33 class DeferredPhotoController::EventsListener : public IEventsListener {
34 public:
EventsListener(DeferredPhotoController * controller)35 explicit EventsListener(DeferredPhotoController* controller)
36 : controller_(controller)
37 {
38 DP_DEBUG_LOG("entered");
39 }
~EventsListener()40 ~EventsListener()
41 {
42 DP_DEBUG_LOG("entered");
43 controller_ = nullptr;
44 }
45
OnEventChange(EventType event,int32_t value)46 void OnEventChange(EventType event, int32_t value) override
47 {
48 DP_INFO_LOG("entered, event: %{public}d", event);
49 switch (event) {
50 case EventType::CAMERA_SESSION_STATUS_EVENT:
51 controller_->NotifyCameraStatusChanged(static_cast<CameraSessionStatus>(value));
52 break;
53 case EventType::HDI_STATUS_EVENT:
54 controller_->NotifyHdiStatusChanged(static_cast<HdiStatus>(value));
55 break;
56 case EventType::MEDIA_LIBRARY_STATUS_EVENT:
57 controller_->NotifyMediaLibStatusChanged(static_cast<MediaLibraryStatus>(value));
58 break;
59 case EventType::SYSTEM_PRESSURE_LEVEL_EVENT:
60 controller_->NotifyPressureLevelChanged(static_cast<SystemPressureLevel>(value));
61 break;
62 default:
63 break;
64 }
65 DPSEventReport::GetInstance().SetEventType(event);
66 }
67
68 private:
69 DeferredPhotoController* controller_;
70 };
71
72 class DeferredPhotoController::PhotoJobRepositoryListener : public IPhotoJobRepositoryListener {
73 public:
PhotoJobRepositoryListener(DeferredPhotoController * controller)74 explicit PhotoJobRepositoryListener(DeferredPhotoController* controller)
75 : controller_(controller)
76 {
77 DP_DEBUG_LOG("entered");
78 }
~PhotoJobRepositoryListener()79 ~PhotoJobRepositoryListener()
80 {
81 DP_DEBUG_LOG("entered");
82 controller_ = nullptr;
83 }
84
OnPhotoJobChanged(bool priorityChanged,bool statusChanged,DeferredPhotoJobPtr jobPtr)85 void OnPhotoJobChanged(bool priorityChanged, bool statusChanged, DeferredPhotoJobPtr jobPtr) override
86 {
87 controller_->OnPhotoJobChanged(priorityChanged, statusChanged, jobPtr);
88 }
89
90 private:
91 DeferredPhotoController* controller_;
92 };
93
DeferredPhotoController(const int32_t userId,std::shared_ptr<PhotoJobRepository> repository,std::shared_ptr<DeferredPhotoProcessor> processor)94 DeferredPhotoController::DeferredPhotoController(const int32_t userId, std::shared_ptr<PhotoJobRepository> repository,
95 std::shared_ptr<DeferredPhotoProcessor> processor)
96 : userId_(userId),
97 callbackHandle_(0),
98 isWaitForUser_(false),
99 scheduleState_(DpsStatus::DPS_SESSION_STATE_IDLE),
100 photoJobRepository_(repository),
101 photoProcessor_(processor),
102 userInitiatedStrategy_(nullptr),
103 backgroundStrategy_(nullptr),
104 eventsListener_(nullptr),
105 photoJobRepositoryListener_(nullptr)
106 {
107 DP_DEBUG_LOG("entered, userid: %{public}d", userId_);
108 //创建策略
109 userInitiatedStrategy_ = std::make_unique<UserInitiatedStrategy>(repository);
110 backgroundStrategy_ = std::make_unique<BackgroundStrategy>(repository);
111 //注册事件监听
112 eventsListener_ = std::make_shared<EventsListener>(this);
113 EventsMonitor::GetInstance().RegisterEventsListener(userId_, {EventType::CAMERA_SESSION_STATUS_EVENT,
114 EventType::HDI_STATUS_EVENT, EventType::MEDIA_LIBRARY_STATUS_EVENT, EventType::SYSTEM_PRESSURE_LEVEL_EVENT},
115 eventsListener_);
116 //注册任务监听
117 photoJobRepositoryListener_ = std::make_shared<PhotoJobRepositoryListener>(this);
118 photoJobRepository_->RegisterJobListener(photoJobRepositoryListener_);
119 }
120
~DeferredPhotoController()121 DeferredPhotoController::~DeferredPhotoController()
122 {
123 DP_DEBUG_LOG("entered, userid: %{public}d", userId_);
124 photoProcessor_ = nullptr;
125 photoJobRepository_ = nullptr;
126 userInitiatedStrategy_ = nullptr;
127 backgroundStrategy_ = nullptr;
128 eventsListener_ = nullptr;
129 }
130
Initialize()131 void DeferredPhotoController::Initialize()
132 {
133 DP_DEBUG_LOG("entered, userid: %{public}d", userId_);
134 }
135
TryDoSchedule()136 void DeferredPhotoController::TryDoSchedule()
137 {
138 DP_INFO_LOG("entered");
139 std::lock_guard<std::recursive_mutex> lock(mutex_);
140 auto work = userInitiatedStrategy_->GetWork();
141 DP_INFO_LOG("userInitiatedStrategy_ get work: %{public}d", work != nullptr);
142 if (work != nullptr) {
143 StopWaitForUser();
144 }
145 if (work == nullptr && !isWaitForUser_) {
146 work = backgroundStrategy_->GetWork();
147 DP_INFO_LOG("backgroundStrategy_ get work: %{public}d", work != nullptr);
148 }
149 DP_INFO_LOG("all strategy get work: %{public}d", work != nullptr);
150 NotifyScheduleState(work != nullptr);
151 if (work == nullptr) {
152 if (photoJobRepository_->GetRunningJobCounts() == 0) {
153 // 重置底层性能模式,避免功耗增加
154 SetDefaultExecutionMode();
155 }
156 return;
157 }
158 if ((photoJobRepository_->GetRunningJobCounts()) < (photoProcessor_->GetConcurrency(work->GetExecutionMode()))) {
159 PostProcess(work);
160 }
161 return;
162 }
163
PostProcess(std::shared_ptr<DeferredPhotoWork> work)164 void DeferredPhotoController::PostProcess(std::shared_ptr<DeferredPhotoWork> work)
165 {
166 DP_DEBUG_LOG("entered");
167 photoProcessor_->PostProcess(work);
168 }
169
SetDefaultExecutionMode()170 void DeferredPhotoController::SetDefaultExecutionMode()
171 {
172 DP_DEBUG_LOG("entered");
173 photoProcessor_->SetDefaultExecutionMode();
174 }
175
NotifyPressureLevelChanged(SystemPressureLevel level)176 void DeferredPhotoController::NotifyPressureLevelChanged(SystemPressureLevel level)
177 {
178 backgroundStrategy_->NotifyPressureLevelChanged(level);
179 TryDoSchedule();
180 return;
181 }
182
NotifyHdiStatusChanged(HdiStatus status)183 void DeferredPhotoController::NotifyHdiStatusChanged(HdiStatus status)
184 {
185 userInitiatedStrategy_->NotifyHdiStatusChanged(status);
186 backgroundStrategy_->NotifyHdiStatusChanged(status);
187 TryDoSchedule();
188 return;
189 }
190
NotifyMediaLibStatusChanged(MediaLibraryStatus status)191 void DeferredPhotoController::NotifyMediaLibStatusChanged(MediaLibraryStatus status)
192 {
193 userInitiatedStrategy_->NotifyMediaLibStatusChanged(status);
194 backgroundStrategy_->NotifyMediaLibStatusChanged(status);
195 if (status == MediaLibraryStatus::MEDIA_LIBRARY_AVAILABLE) {
196 TryDoSchedule();
197 }
198 return;
199 }
200
NotifyCameraStatusChanged(CameraSessionStatus status)201 void DeferredPhotoController::NotifyCameraStatusChanged(CameraSessionStatus status)
202 {
203 userInitiatedStrategy_->NotifyCameraStatusChanged(status);
204 backgroundStrategy_->NotifyCameraStatusChanged(status);
205 if (status == CameraSessionStatus::SYSTEM_CAMERA_OPEN || status == CameraSessionStatus::NORMAL_CAMERA_OPEN) {
206 photoProcessor_->Interrupt();
207 }
208 if (status == CameraSessionStatus::SYSTEM_CAMERA_CLOSED || status == CameraSessionStatus::NORMAL_CAMERA_CLOSED) {
209 TryDoSchedule();
210 }
211 return;
212 }
213
214 //来自任务仓库的事件
OnPhotoJobChanged(bool priorityChanged,bool statusChanged,DeferredPhotoJobPtr jobPtr)215 void DeferredPhotoController::OnPhotoJobChanged(bool priorityChanged, bool statusChanged, DeferredPhotoJobPtr jobPtr)
216 {
217 DP_INFO_LOG("entered, priorityChanged: %{public}d, statusChanged: %{public}d , imageId: %s",
218 priorityChanged, statusChanged, jobPtr->GetImageId().c_str());
219 if (priorityChanged && statusChanged) {
220 if (jobPtr->GetPrePriority() == PhotoJobPriority::HIGH && jobPtr->GetPreStatus() == PhotoJobStatus::RUNNING) {
221 StartWaitForUser();
222 }
223 }
224 TryDoSchedule();
225 return;
226 }
227
StartWaitForUser()228 void DeferredPhotoController::StartWaitForUser()
229 {
230 DP_INFO_LOG("entered");
231 isWaitForUser_ = true;
232 GetGlobalWatchdog().StartMonitor(callbackHandle_, DURATIONMS_500, [this](uint32_t handle) {
233 isWaitForUser_ = false;
234 DP_INFO_LOG("DeferredPhotoController, wait for user ended, handle: %{public}d, try do schedule",
235 static_cast<int>(handle));
236 TryDoSchedule();
237 });
238 DP_INFO_LOG("DeferredPhotoController, wait for user started, handle: %{public}d",
239 static_cast<int>(callbackHandle_));
240 }
241
StopWaitForUser()242 void DeferredPhotoController::StopWaitForUser()
243 {
244 DP_INFO_LOG("entered");
245 isWaitForUser_ = false;
246 GetGlobalWatchdog().StopMonitor(callbackHandle_);
247 }
248
NotifyScheduleState(bool workAvailable)249 void DeferredPhotoController::NotifyScheduleState(bool workAvailable)
250 {
251 DP_INFO_LOG("entered, workAvailable: %{public}d", workAvailable);
252 DpsStatus scheduleState = DpsStatus::DPS_SESSION_STATE_IDLE;
253 if (workAvailable || photoJobRepository_->GetRunningJobCounts() > 0) {
254 scheduleState = DpsStatus::DPS_SESSION_STATE_RUNNING;
255 } else {
256 if (photoJobRepository_->GetOfflineJobSize() == 0) {
257 scheduleState = DpsStatus::DPS_SESSION_STATE_IDLE;
258 } else {
259 if (backgroundStrategy_->GetHdiStatus() != HdiStatus::HDI_READY) {
260 scheduleState = DpsStatus::DPS_SESSION_STATE_SUSPENDED;
261 } else {
262 scheduleState = DpsStatus::DPS_SESSION_STATE_RUNNALBE;
263 }
264 }
265 }
266 DP_INFO_LOG("entered, scheduleState_: %{public}d, scheduleState: %{public}d", scheduleState_, scheduleState);
267 if (scheduleState != scheduleState_) {
268 scheduleState_ = scheduleState;
269 photoProcessor_->NotifyScheduleState(scheduleState_);
270 }
271 }
272 } // namespace DeferredProcessing
273 } // namespace CameraStandard
274 } // namespace OHOS