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 "video_strategy_center.h"
17 
18 #include "battery_level_strategy.h"
19 #include "dp_log.h"
20 #include "dps_event_report.h"
21 #include "events_info.h"
22 #include "events_monitor.h"
23 #include "ivideo_state_change_listener.h"
24 #include "video_battery_level_state.h"
25 #include "video_battery_state.h"
26 #include "video_camera_state.h"
27 #include "video_charging_state.h"
28 #include "video_hal_state.h"
29 #include "video_media_library_state.h"
30 #include "video_photo_process_state.h"
31 #include "video_screen_state.h"
32 #include "video_temperature_state.h"
33 
34 namespace OHOS {
35 namespace CameraStandard {
36 namespace DeferredProcessing {
37 namespace {
38     constexpr uint32_t SINGLE_TIME_LIMIT = 0b1;
39     constexpr uint32_t TOTAL_TIME_LIMIT = 0b10;
40     constexpr int32_t DEFAULT_TIME = 0;
41 }
42 
43 class VideoStrategyCenter::EventsListener : public IEventsListener {
44 public:
EventsListener(const std::weak_ptr<VideoStrategyCenter> & strategyCenter)45     explicit EventsListener(const std::weak_ptr<VideoStrategyCenter>& strategyCenter)
46         : strategyCenter_(strategyCenter)
47     {
48         DP_DEBUG_LOG("entered");
49     }
50 
~EventsListener()51     ~EventsListener()
52     {
53         DP_DEBUG_LOG("entered");
54     }
55 
OnEventChange(EventType event,int32_t value)56     void OnEventChange(EventType event, int32_t value) override
57     {
58         DP_DEBUG_LOG("entered, event: %{public}d", event);
59         auto strategy = strategyCenter_.lock();
60         DP_CHECK_ERROR_RETURN_LOG(strategy == nullptr, "VideoStrategyCenter is nullptr.");
61         strategy->HandleEventChanged(event, value);
62         DPSEventReport::GetInstance().SetEventType(event);
63     }
64 
65 private:
66     std::weak_ptr<VideoStrategyCenter> strategyCenter_;
67 };
68 
VideoStrategyCenter(const int32_t userId,const std::shared_ptr<VideoJobRepository> & repository)69 VideoStrategyCenter::VideoStrategyCenter(const int32_t userId, const std::shared_ptr<VideoJobRepository>& repository)
70     : userId_(userId), videoJobRepository_(repository)
71 {
72     DP_INFO_LOG("entered");
73 }
74 
~VideoStrategyCenter()75 VideoStrategyCenter::~VideoStrategyCenter()
76 {
77     DP_INFO_LOG("entered");
78     eventsListener_ = nullptr;
79     eventHandlerList_.clear();
80     scheduleStateList_.clear();
81     videoJobRepository_ = nullptr;
82 }
83 
Initialize()84 void VideoStrategyCenter::Initialize()
85 {
86     DP_INFO_LOG("entered");
87     InitHandleEvent();
88     InitScheduleState();
89     eventsListener_ = std::make_shared<EventsListener>(weak_from_this());
90     EventsMonitor::GetInstance().RegisterEventsListener(userId_, {
91         EventType::CAMERA_SESSION_STATUS_EVENT,
92         EventType::HDI_STATUS_EVENT,
93         EventType::MEDIA_LIBRARY_STATUS_EVENT,
94         EventType::THERMAL_LEVEL_STATUS_EVENT,
95         EventType::SCREEN_STATUS_EVENT,
96         EventType::BATTERY_STATUS_EVENT,
97         EventType::BATTERY_LEVEL_STATUS_EVENT,
98         EventType::CHARGING_STATUS_EVENT,
99         EventType::PHOTO_PROCESS_STATUS_EVENT},
100         eventsListener_);
101 }
102 
InitHandleEvent()103 void VideoStrategyCenter::InitHandleEvent()
104 {
105     DP_INFO_LOG("entered");
106     eventHandlerList_.insert({CAMERA_SESSION_STATUS_EVENT, [this](int32_t value){HandleCameraEvent(value);}});
107     eventHandlerList_.insert({HDI_STATUS_EVENT, [this](int32_t value){HandleHalEvent(value);}});
108     eventHandlerList_.insert({MEDIA_LIBRARY_STATUS_EVENT, [this](int32_t value){HandleMedialLibraryEvent(value);}});
109     eventHandlerList_.insert({SCREEN_STATUS_EVENT, [this](int32_t value){HandleScreenEvent(value);}});
110     eventHandlerList_.insert({CHARGING_STATUS_EVENT, [this](int32_t value){HandleChargingEvent(value);}});
111     eventHandlerList_.insert({BATTERY_STATUS_EVENT, [this](int32_t value){HandleBatteryEvent(value);}});
112     eventHandlerList_.insert({BATTERY_LEVEL_STATUS_EVENT, [this](int32_t value){HandleBatteryLevelEvent(value);}});
113     eventHandlerList_.insert({THERMAL_LEVEL_STATUS_EVENT, [this](int32_t value){HandleTemperatureEvent(value);}});
114     eventHandlerList_.insert({PHOTO_PROCESS_STATUS_EVENT, [this](int32_t value){HandlePhotoProcessEvent(value);}});
115 }
116 
InitScheduleState()117 void VideoStrategyCenter::InitScheduleState()
118 {
119     DP_INFO_LOG("entered");
120     auto state = EventsInfo::GetInstance().GetChargingState();
121     isCharging_ = state == ChargingStatus::CHARGING;
122     scheduleStateList_.insert({CAMERA_STATE,
123         std::make_shared<VideoCameraState>(CameraSessionStatus::SYSTEM_CAMERA_CLOSED)});
124     scheduleStateList_.insert({HDI_STATE,
125         std::make_shared<VideoHalState>(HdiStatus::HDI_READY)});
126     scheduleStateList_.insert({MEDIA_LIBRARY_STATE,
127         std::make_shared<VideoMediaLibraryState>(MediaLibraryStatus::MEDIA_LIBRARY_AVAILABLE)});
128     scheduleStateList_.insert({SCREEN_STATE,
129         std::make_shared<VideoScreenState>(EventsInfo::GetInstance().GetScreenState())});
130     scheduleStateList_.insert({CHARGING_STATE,
131         std::make_shared<VideoChargingState>(state)});
132     scheduleStateList_.insert({BATTERY_STATE,
133         std::make_shared<VideoBatteryState>(EventsInfo::GetInstance().GetBatteryState())});
134     scheduleStateList_.insert({BATTERY_LEVEL_STATE,
135         std::make_shared<VideoBatteryLevelState>(EventsInfo::GetInstance().GetBatteryLevel())});
136     scheduleStateList_.insert({THERMAL_LEVEL_STATE,
137         std::make_shared<VideoTemperatureState>(ConvertThermalLevel(EventsInfo::GetInstance().GetThermalLevel()))});
138     scheduleStateList_.insert({PHOTO_PROCESS_STATE,
139         std::make_shared<VideoPhotoProcessState>(PhotoProcessStatus::IDLE)});
140     for (const auto& item : scheduleStateList_) {
141         if (item.second == nullptr) {
142             DP_ERR_LOG("schedule state init failed, type: %{public}d", item.first);
143             continue;
144         }
145         item.second->Initialize();
146     }
147 }
148 
HandleEventChanged(EventType event,int32_t value)149 void VideoStrategyCenter::HandleEventChanged(EventType event, int32_t value)
150 {
151     DP_INFO_LOG("entered, eventType: %{public}d, value: %{public}d", event, value);
152     auto item = eventHandlerList_.find(event);
153     if (item != eventHandlerList_.end()) {
154         item->second(value);
155     } else {
156         DP_WARNING_LOG("not support handle event: %{public}d", event);
157     }
158 }
159 
RegisterStateChangeListener(const std::weak_ptr<IVideoStateChangeListener> & listener)160 void VideoStrategyCenter::RegisterStateChangeListener(const std::weak_ptr<IVideoStateChangeListener>& listener)
161 {
162     videoStateChangeListener_ = listener;
163 }
164 
GetWork()165 DeferredVideoWorkPtr VideoStrategyCenter::GetWork()
166 {
167     auto jobPtr = GetJob();
168     ExecutionMode mode = GetExecutionMode();
169     if ((jobPtr != nullptr) && (mode != ExecutionMode::DUMMY)) {
170         return std::make_shared<DeferredVideoWork>(jobPtr, mode, isCharging_);
171     }
172     return nullptr;
173 }
174 
GetJob()175 DeferredVideoJobPtr VideoStrategyCenter::GetJob()
176 {
177     return videoJobRepository_->GetJob();
178 }
179 
GetExecutionMode()180 ExecutionMode VideoStrategyCenter::GetExecutionMode()
181 {
182     if (isCharging_) {
183         DP_CHECK_RETURN_RET(IsReady(), ExecutionMode::LOAD_BALANCE);
184     } else {
185         DP_CHECK_RETURN_RET(IsReady() && IsTimeReady(), ExecutionMode::LOAD_BALANCE);
186     }
187     return ExecutionMode::DUMMY;
188 }
189 
HandleCameraEvent(int32_t value)190 void VideoStrategyCenter::HandleCameraEvent(int32_t value)
191 {
192     DP_DEBUG_LOG("CameraEvent value: %{public}d", value);
193     UpdateValue(ScheduleType::CAMERA_STATE, value);
194 }
195 
HandleHalEvent(int32_t value)196 void VideoStrategyCenter::HandleHalEvent(int32_t value)
197 {
198     DP_DEBUG_LOG("HalEvent value: %{public}d", value);
199     UpdateValue(ScheduleType::HDI_STATE, value);
200 }
201 
HandleMedialLibraryEvent(int32_t value)202 void VideoStrategyCenter::HandleMedialLibraryEvent(int32_t value)
203 {
204     DP_DEBUG_LOG("MedialLibraryEvent value: %{public}d", value);
205     UpdateValue(ScheduleType::MEDIA_LIBRARY_STATE, value);
206 }
207 
HandleScreenEvent(int32_t value)208 void VideoStrategyCenter::HandleScreenEvent(int32_t value)
209 {
210     DP_DEBUG_LOG("ScreenEvent value: %{public}d", value);
211     DP_CHECK_EXECUTE(value == ScreenStatus::SCREEN_ON, UpdateSingleTime(true));
212     UpdateValue(ScheduleType::SCREEN_STATE, value);
213 }
214 
HandleChargingEvent(int32_t value)215 void VideoStrategyCenter::HandleChargingEvent(int32_t value)
216 {
217     DP_DEBUG_LOG("ChargingEvent value: %{public}d", value);
218     isCharging_ = value == ChargingStatus::CHARGING;
219     DP_CHECK_EXECUTE(isCharging_, UpdateAvailableTime(true, DEFAULT_TIME));
220     UpdateValue(ScheduleType::CHARGING_STATE, value);
221 }
HandleBatteryEvent(int32_t value)222 void VideoStrategyCenter::HandleBatteryEvent(int32_t value)
223 {
224     DP_DEBUG_LOG("BatteryEvent value: %{public}d", value);
225     UpdateValue(ScheduleType::BATTERY_STATE, value);
226 }
227 
HandleBatteryLevelEvent(int32_t value)228 void VideoStrategyCenter::HandleBatteryLevelEvent(int32_t value)
229 {
230     DP_DEBUG_LOG("BatteryLevelEvent value: %{public}d", value);
231     UpdateValue(ScheduleType::BATTERY_LEVEL_STATE, value);
232 }
233 
HandleTemperatureEvent(int32_t value)234 void VideoStrategyCenter::HandleTemperatureEvent(int32_t value)
235 {
236     DP_DEBUG_LOG("TemperatureEvent value: %{public}d", value);
237     auto level = ConvertThermalLevel(value);
238     UpdateValue(ScheduleType::THERMAL_LEVEL_STATE, level);
239 }
240 
HandlePhotoProcessEvent(int32_t value)241 void VideoStrategyCenter::HandlePhotoProcessEvent(int32_t value)
242 {
243     DP_DEBUG_LOG("PhotoProcessEvent value: %{public}d", value);
244     auto state = ConvertProcessState(value);
245     UpdateValue(ScheduleType::PHOTO_PROCESS_STATE, state);
246 }
247 
UpdateValue(ScheduleType type,int32_t value)248 void VideoStrategyCenter::UpdateValue(ScheduleType type, int32_t value)
249 {
250     auto scheduleState = GetScheduleState(type);
251     DP_CHECK_ERROR_RETURN_LOG(scheduleState == nullptr, "UpdateValue failed.");
252     if (scheduleState->UpdateSchedulerInfo(type, value)) {
253         auto info = ReevaluateSchedulerInfo();
254         isNeedStop_ = info.isNeedStop;
255         auto listener = videoStateChangeListener_.lock();
256         DP_CHECK_ERROR_RETURN_LOG(listener == nullptr, "VideoStateChangeListener is nullptr.");
257         listener->OnSchedulerChanged(type, info);
258     }
259 }
260 
UpdateSingleTime(bool isOk)261 void VideoStrategyCenter::UpdateSingleTime(bool isOk)
262 {
263     if (isOk) {
264         isTimeOk_ &= ~SINGLE_TIME_LIMIT;
265     } else {
266         isTimeOk_ |= SINGLE_TIME_LIMIT;
267     }
268     DP_INFO_LOG("process time type: 0x%{public}x", isTimeOk_);
269 }
270 
UpdateAvailableTime(bool isNeedReset,int32_t useTime)271 void VideoStrategyCenter::UpdateAvailableTime(bool isNeedReset, int32_t useTime)
272 {
273     if (isNeedReset) {
274         availableTime_ = TOTAL_PROCESS_TIME;
275     } else {
276         availableTime_ -= useTime;
277     }
278 
279     if (availableTime_ > 0) {
280         isTimeOk_ &= ~TOTAL_TIME_LIMIT;
281     } else {
282         availableTime_ = 0;
283         isTimeOk_ |= TOTAL_TIME_LIMIT;
284     }
285     DP_INFO_LOG("available process time: %{public}d, type: 0x%{public}x", availableTime_, isTimeOk_);
286 }
287 
ReevaluateSchedulerInfo()288 ScheduleInfo VideoStrategyCenter::ReevaluateSchedulerInfo()
289 {
290     ScheduleInfo cameraInfo = GetScheduleInfo(ScheduleType::CAMERA_STATE);
291     ScheduleInfo halInfo = GetScheduleInfo(ScheduleType::HDI_STATE);
292     ScheduleInfo mediaLibraryInfo = GetScheduleInfo(ScheduleType::MEDIA_LIBRARY_STATE);
293     ScheduleInfo screenInfo = GetScheduleInfo(ScheduleType::SCREEN_STATE);
294     ScheduleInfo temperatureInfo = GetScheduleInfo(ScheduleType::THERMAL_LEVEL_STATE);
295     ScheduleInfo photoProcessInfo = GetScheduleInfo(ScheduleType::PHOTO_PROCESS_STATE);
296     ScheduleInfo chargingInfo = GetScheduleInfo(ScheduleType::CHARGING_STATE);
297     if (cameraInfo.isNeedStop || halInfo.isNeedStop || mediaLibraryInfo.isNeedStop ||
298         screenInfo.isNeedStop || temperatureInfo.isNeedStop || photoProcessInfo.isNeedStop) {
299         DP_INFO_LOG("video stop schedule, hdi : %{public}d, mediaLibrary: %{public}d, camear: %{public}d, "
300             "screen: %{public}d, temperatureInfo: %{public}d, photoProcessInfo: %{public}d",
301             halInfo.isNeedStop, mediaLibraryInfo.isNeedStop, cameraInfo.isNeedStop,
302             screenInfo.isNeedStop, temperatureInfo.isNeedStop, photoProcessInfo.isNeedStop);
303         return {true, chargingInfo.isCharging};
304     }
305 
306     if (chargingInfo.isCharging) {
307         DP_CHECK_RETURN_RET_LOG(videoJobRepository_->GetRunningJobCounts() > 0,
308             chargingInfo, "has video job running.");
309 
310         DP_INFO_LOG("video try schedule in charging.");
311         return GetScheduleInfo(ScheduleType::BATTERY_LEVEL_STATE);
312     }
313 
314     DP_INFO_LOG("video try schedule in normal.");
315     return GetScheduleInfo(ScheduleType::BATTERY_STATE);
316 }
317 
GetScheduleInfo(ScheduleType type)318 ScheduleInfo VideoStrategyCenter::GetScheduleInfo(ScheduleType type)
319 {
320     ScheduleInfo defaultInfo = {true, false};
321     auto scheduleState = GetScheduleState(type);
322     DP_CHECK_ERROR_RETURN_RET_LOG(scheduleState == nullptr, defaultInfo, "not find schedule type: %{public}d", type);
323     return scheduleState->GetScheduleInfo(type);
324 }
325 
GetScheduleState(ScheduleType type)326 std::shared_ptr<ISchedulerVideoState> VideoStrategyCenter::GetScheduleState(ScheduleType type)
327 {
328     auto item = scheduleStateList_.find(type);
329     DP_CHECK_ERROR_RETURN_RET_LOG(item == scheduleStateList_.end(), nullptr,
330         "can not find ScheduleState by ScheduleType: %{public}d", type);
331 
332     auto scheduleState = item->second;
333     DP_CHECK_ERROR_PRINT_LOG(scheduleState == nullptr, "ScheduleState get by EventType: %{public}d is nullptr", type);
334     return scheduleState;
335 }
336 
337 } // namespace DeferredProcessing
338 } // namespace CameraStandard
339 } // namespace OHOS