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