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 backgroundStrategy_->NotifyHdiStatusChanged(status);
186 TryDoSchedule();
187 return;
188 }
189
NotifyMediaLibStatusChanged(MediaLibraryStatus status)190 void DeferredPhotoController::NotifyMediaLibStatusChanged(MediaLibraryStatus status)
191 {
192 backgroundStrategy_->NotifyMediaLibStatusChanged(status);
193 if (status == MediaLibraryStatus::MEDIA_LIBRARY_AVAILABLE) {
194 TryDoSchedule();
195 }
196 return;
197 }
198
NotifyCameraStatusChanged(CameraSessionStatus status)199 void DeferredPhotoController::NotifyCameraStatusChanged(CameraSessionStatus status)
200 {
201 backgroundStrategy_->NotifyCameraStatusChanged(status);
202 if (status == CameraSessionStatus::SYSTEM_CAMERA_OPEN || status == CameraSessionStatus::NORMAL_CAMERA_OPEN) {
203 photoProcessor_->Interrupt();
204 }
205 if (status == CameraSessionStatus::SYSTEM_CAMERA_CLOSED || status == CameraSessionStatus::NORMAL_CAMERA_CLOSED) {
206 TryDoSchedule();
207 }
208 return;
209 }
210
211 //来自任务仓库的事件
OnPhotoJobChanged(bool priorityChanged,bool statusChanged,DeferredPhotoJobPtr jobPtr)212 void DeferredPhotoController::OnPhotoJobChanged(bool priorityChanged, bool statusChanged, DeferredPhotoJobPtr jobPtr)
213 {
214 DP_INFO_LOG("entered, priorityChanged: %{public}d, statusChanged: %{public}d , imageId: %s",
215 priorityChanged, statusChanged, jobPtr->GetImageId().c_str());
216 if (priorityChanged && statusChanged) {
217 if (jobPtr->GetPrePriority() == PhotoJobPriority::HIGH && jobPtr->GetPreStatus() == PhotoJobStatus::RUNNING) {
218 StartWaitForUser();
219 }
220 }
221 TryDoSchedule();
222 return;
223 }
224
StartWaitForUser()225 void DeferredPhotoController::StartWaitForUser()
226 {
227 DP_INFO_LOG("entered");
228 isWaitForUser_ = true;
229 GetGlobalWatchdog().StartMonitor(callbackHandle_, DURATIONMS_500, [this](uint32_t handle) {
230 isWaitForUser_ = false;
231 DP_INFO_LOG("DeferredPhotoController, wait for user ended, handle: %{public}d, try do schedule",
232 static_cast<int>(handle));
233 TryDoSchedule();
234 });
235 DP_INFO_LOG("DeferredPhotoController, wait for user started, handle: %{public}d",
236 static_cast<int>(callbackHandle_));
237 }
238
StopWaitForUser()239 void DeferredPhotoController::StopWaitForUser()
240 {
241 DP_INFO_LOG("entered");
242 isWaitForUser_ = false;
243 GetGlobalWatchdog().StopMonitor(callbackHandle_);
244 }
245
NotifyScheduleState(bool workAvailable)246 void DeferredPhotoController::NotifyScheduleState(bool workAvailable)
247 {
248 DP_INFO_LOG("entered, workAvailable: %{public}d", workAvailable);
249 DpsStatus scheduleState = DpsStatus::DPS_SESSION_STATE_IDLE;
250 if (workAvailable || photoJobRepository_->GetRunningJobCounts() > 0) {
251 scheduleState = DpsStatus::DPS_SESSION_STATE_RUNNING;
252 } else {
253 if (photoJobRepository_->GetOfflineJobSize() == 0) {
254 scheduleState = DpsStatus::DPS_SESSION_STATE_IDLE;
255 } else {
256 if (backgroundStrategy_->GetHdiStatus() != HdiStatus::HDI_READY) {
257 scheduleState = DpsStatus::DPS_SESSION_STATE_SUSPENDED;
258 } else {
259 scheduleState = DpsStatus::DPS_SESSION_STATE_RUNNALBE;
260 }
261 }
262 }
263 DP_INFO_LOG("entered, scheduleState_: %{public}d, scheduleState: %{public}d", scheduleState_, scheduleState);
264 if (scheduleState != scheduleState_) {
265 scheduleState_ = scheduleState;
266 photoProcessor_->NotifyScheduleState(scheduleState_);
267 }
268 }
269 } // namespace DeferredProcessing
270 } // namespace CameraStandard
271 } // namespace OHOS