1 /*
2 * Copyright (c) 2024 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 #include "slide_recognizer.h"
16
17 #include <mutex>
18
19 #include "event_listener_mgr.h"
20 #include "ffrt_inner.h"
21 #include "plugin_mgr.h"
22 #include "res_common_util.h"
23 #include "res_sched_log.h"
24 #include "res_sched_mgr.h"
25 #include "res_type.h"
26
27 namespace OHOS {
28 namespace ResourceSchedule {
29 namespace {
30 static const std::string UP_SPEED_KEY = "up_speed";
31 static uint32_t g_slideState = SlideRecognizeStat::IDLE;
32 static ffrt::recursive_mutex stateMutex;
33 static auto g_reportListFlingLockedEnd = [](const nlohmann::json payload) {
34 std::lock_guard<ffrt::recursive_mutex> lock(stateMutex);
35 if (g_slideState != SlideRecognizeStat::LIST_FLING) {
36 return;
37 }
38 ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_SLIDE_RECOGNIZE,
39 ResType::SlideEventStatus::SLIDE_EVENT_OFF, payload);
40 nlohmann::json extInfo;
41 EventListenerMgr::GetInstance().SendEvent(ResType::EventType::EVENT_DRAW_FRAME_REPORT,
42 ResType::EventValue::EVENT_VALUE_DRAW_FRAME_REPORT_STOP, extInfo);
43 g_slideState = SlideRecognizeStat::IDLE;
44 };
45 }
46
~SlideRecognizer()47 SlideRecognizer::~SlideRecognizer()
48 {
49 RESSCHED_LOGI("~UpdatingSceneRecognizer");
50 }
51
OnDispatchResource(uint32_t resType, int64_t value, const nlohmann::json& payload)52 void SlideRecognizer::OnDispatchResource(uint32_t resType, int64_t value, const nlohmann::json& payload)
53 {
54 switch (resType) {
55 case ResType::RES_TYPE_SLIDE_RECOGNIZE:
56 HandleSlideEvent(value, payload);
57 break;
58 case ResType::RES_TYPE_SEND_FRAME_EVENT:
59 HandleSendFrameEvent(FillRealPid(payload));
60 break;
61 case ResType::RES_TYPE_CLICK_RECOGNIZE:
62 HandleClickEvent(value, payload);
63 break;
64 default:
65 RESSCHED_LOGD("unkonw resType");
66 break;
67 }
68 }
69
HandleSlideEvent(int64_t value, const nlohmann::json& payload)70 void SlideRecognizer::HandleSlideEvent(int64_t value, const nlohmann::json& payload)
71 {
72 if (value == ResType::SlideEventStatus::SLIDE_EVENT_DETECTING) {
73 HandleSlideDetecting(payload);
74 } else if (value == ResType::SlideEventStatus::SLIDE_EVENT_ON) {
75 HandleListFlingStart(payload);
76 } else if (value == ResType::SlideEventStatus::SLIDE_EVENT_OFF) {
77 HandleSlideOFFEvent();
78 }
79 }
80
HandleSlideOFFEvent()81 void SlideRecognizer::HandleSlideOFFEvent()
82 {
83 std::lock_guard<ffrt::recursive_mutex> lock(stateMutex);
84 if (g_slideState == SlideRecognizeStat::SLIDE_NORMAL_DETECTING) {
85 return;
86 }
87 if (listFlingEndTask_) {
88 ffrt::skip(listFlingEndTask_);
89 }
90 if (listFlingTimeOutTask_) {
91 ffrt::skip(listFlingTimeOutTask_);
92 }
93 nlohmann::json extInfo;
94 EventListenerMgr::GetInstance().SendEvent(ResType::EventType::EVENT_DRAW_FRAME_REPORT,
95 ResType::EventValue::EVENT_VALUE_DRAW_FRAME_REPORT_STOP, extInfo);
96 g_slideState = SlideRecognizeStat::IDLE;
97 }
98
HandleSlideDetecting(const nlohmann::json& payload)99 void SlideRecognizer::HandleSlideDetecting(const nlohmann::json& payload)
100 {
101 if (g_slideState == SlideRecognizeStat::LIST_FLING) {
102 if (listFlingEndTask_) {
103 ffrt::skip(listFlingEndTask_);
104 }
105 if (listFlingTimeOutTask_) {
106 ffrt::skip(listFlingTimeOutTask_);
107 }
108 listFlingEndTask_ = nullptr;
109 listFlingTimeOutTask_ = nullptr;
110 g_reportListFlingLockedEnd(FillRealPid(payload));
111 }
112 nlohmann::json extInfo;
113 EventListenerMgr::GetInstance().SendEvent(ResType::EventType::EVENT_DRAW_FRAME_REPORT,
114 ResType::EventValue::EVENT_VALUE_DRAW_FRAME_REPORT_START, extInfo);
115 slideDetectingTime_ = ResCommonUtil::GetNowMillTime();
116 g_slideState = SlideRecognizeStat::SLIDE_NORMAL_DETECTING;
117 if (!payload.contains("clientPid") || !payload["clientPid"].is_string()) {
118 RESSCHED_LOGE("payload with no clientPid");
119 return;
120 }
121 slidePid_ = payload["clientPid"];
122 }
123
HandleListFlingStart(const nlohmann::json& payload)124 void SlideRecognizer::HandleListFlingStart(const nlohmann::json& payload)
125 {
126 std::lock_guard<ffrt::recursive_mutex> lock(stateMutex);
127 if (g_slideState == SlideRecognizeStat::LIST_FLING) {
128 return;
129 }
130 nlohmann::json extInfo;
131 EventListenerMgr::GetInstance().SendEvent(ResType::EventType::EVENT_DRAW_FRAME_REPORT,
132 ResType::EventValue::EVENT_VALUE_DRAW_FRAME_REPORT_START, extInfo);
133 g_slideState = SlideRecognizeStat::LIST_FLING;
134 if (listFlingEndTask_) {
135 ffrt::skip(listFlingEndTask_);
136 }
137 listFlingEndTask_ = ffrt::submit_h([payload]() {
138 g_reportListFlingLockedEnd(payload);
139 }, {}, {}, ffrt::task_attr().delay(listFlingEndTime_));
140 if (listFlingTimeOutTask_) {
141 ffrt::skip(listFlingTimeOutTask_);
142 }
143 listFlingTimeOutTask_ = ffrt::submit_h([payload]() {
144 g_reportListFlingLockedEnd(payload);
145 }, {}, {}, ffrt::task_attr().delay(listFlingTimeOutTime_));
146 }
147
HandleSendFrameEvent(const nlohmann::json& payload)148 void SlideRecognizer::HandleSendFrameEvent(const nlohmann::json& payload)
149 {
150 std::lock_guard<ffrt::recursive_mutex> lock(stateMutex);
151 if (g_slideState == SlideRecognizeStat::SLIDE_NORMAL_DETECTING) {
152 int64_t nowTime = ResCommonUtil::GetNowMillTime();
153 if (nowTime - slideDetectingTime_ < slideNormalDecectingTime_) {
154 ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_SLIDE_RECOGNIZE,
155 ResType::SlideEventStatus::SLIDE_NORMAL_BEGIN, payload);
156 g_slideState = SlideRecognizeStat::SLIDE_NORMAL;
157 } else {
158 g_slideState = SlideRecognizeStat::IDLE;
159 }
160 nlohmann::json extInfo;
161 EventListenerMgr::GetInstance().SendEvent(ResType::EventType::EVENT_DRAW_FRAME_REPORT,
162 ResType::EventValue::EVENT_VALUE_DRAW_FRAME_REPORT_STOP, extInfo);
163 } else if (g_slideState == SlideRecognizeStat::LIST_FLING) {
164 if (listFlingEndTask_) {
165 ffrt::skip(listFlingEndTask_);
166 }
167 listFlingEndTask_ = ffrt::submit_h([payload]() {
168 g_reportListFlingLockedEnd(payload);
169 }, {}, {}, ffrt::task_attr().delay(listFlingEndTime_));
170 }
171 }
172
HandleClickEvent(int64_t value, const nlohmann::json& payload)173 void SlideRecognizer::HandleClickEvent(int64_t value, const nlohmann::json& payload)
174 {
175 std::lock_guard<ffrt::recursive_mutex> lock(stateMutex);
176 //not in slide stat
177 if (g_slideState != SlideRecognizeStat::SLIDE_NORMAL) {
178 return;
179 }
180 if (value == ResType::ClickEventType::TOUCH_EVENT_DOWN) {
181 g_slideState = SlideRecognizeStat::IDLE;
182 return;
183 }
184 // receive up event, silde normal end
185 if (value == ResType::ClickEventType::TOUCH_EVENT_UP ||
186 value == ResType::ClickEventType::TOUCH_EVENT_PULL_UP) {
187 ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_SLIDE_RECOGNIZE,
188 ResType::SlideEventStatus::SLIDE_NORMAL_END, payload);
189 float upSpeed = 0.0;
190 if (!payload.contains("clientPid") || !payload["clientPid"].is_string()) {
191 RESSCHED_LOGE("payload with no clientPid");
192 return;
193 }
194 slidePid_ = payload["clientPid"];
195 if (!payload.contains(UP_SPEED_KEY) || !payload[UP_SPEED_KEY].is_string()) {
196 return;
197 }
198 // if up speed large than LIST_FLING_SPEED_LIMIT,start recognize list fling.
199 if (ResCommonUtil::StrToFloat(payload[UP_SPEED_KEY], upSpeed) && upSpeed > listFlingSpeedLimit_) {
200 nlohmann::json extInfo;
201 EventListenerMgr::GetInstance().SendEvent(ResType::EventType::EVENT_DRAW_FRAME_REPORT,
202 ResType::EventValue::EVENT_VALUE_DRAW_FRAME_REPORT_START, extInfo);
203 ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_SLIDE_RECOGNIZE,
204 ResType::SlideEventStatus::SLIDE_EVENT_ON, payload);
205 }
206 }
207 }
208
FillRealPid(const nlohmann::json& payload)209 nlohmann::json SlideRecognizer::FillRealPid(const nlohmann::json& payload)
210 {
211 if (slidePid_.empty()) {
212 return payload;
213 }
214 nlohmann::json payloadM = payload;
215 payloadM["clientPid"] = slidePid_;
216 return payloadM;
217 }
218
SetListFlingTimeoutTime(int64_t value)219 void SlideRecognizer::SetListFlingTimeoutTime(int64_t value)
220 {
221 listFlingTimeOutTime_ = value;
222 }
223
SetListFlingEndTime(int64_t value)224 void SlideRecognizer::SetListFlingEndTime(int64_t value)
225 {
226 listFlingEndTime_ = value;
227 }
228
SetListFlingSpeedLimit(float value)229 void SlideRecognizer::SetListFlingSpeedLimit(float value)
230 {
231 listFlingSpeedLimit_ = value;
232 }
233
SetSlideNormalDetectingTime(int64_t value)234 void SlideRecognizer::SetSlideNormalDetectingTime(int64_t value)
235 {
236 slideNormalDecectingTime_ = value;
237 }
238 } // namespace ResourceSchedule
239 } // namespace OHOS