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