1 /*
2 * Copyright (c) 2024-2025 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 "hitrace_meter.h"
22 #include "plugin_mgr.h"
23 #include "res_common_util.h"
24 #include "res_sched_log.h"
25 #include "res_sched_mgr.h"
26 #include "res_type.h"
27 #include "scene_recognizer_mgr.h"
28
29 namespace OHOS {
30 namespace ResourceSchedule {
31 namespace {
32 static const uint32_t AXIS_EVENT_PAD = 0;
33 static const uint32_t AXIS_EVENT_FACTOR = 10;
34 static const char* AXIS_EVENT_TYPE = "axis_event_type";
35 static const char* UP_SPEED_KEY = "up_speed";
36 static uint32_t g_slideState = SlideRecognizeStat::IDLE;
37 static ffrt::recursive_mutex stateMutex;
__anon31cc55fa0202(const nlohmann::json payload) 38 static auto g_reportListFlingLockedEnd = [](const nlohmann::json payload) {
39 std::lock_guard<ffrt::recursive_mutex> lock(stateMutex);
40 if (g_slideState != SlideRecognizeStat::LIST_FLING) {
41 return;
42 }
43 ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_SLIDE_RECOGNIZE,
44 ResType::SlideEventStatus::SLIDE_EVENT_OFF, payload);
45 nlohmann::json extInfo;
46 EventListenerMgr::GetInstance().SendEvent(ResType::EventType::EVENT_DRAW_FRAME_REPORT,
47 ResType::EventValue::EVENT_VALUE_DRAW_FRAME_REPORT_STOP, extInfo);
48 g_slideState = SlideRecognizeStat::IDLE;
49 };
50 }
51
SlideRecognizer()52 SlideRecognizer::SlideRecognizer()
53 {
54 AddAcceptResTypes({
55 ResType::RES_TYPE_SLIDE_RECOGNIZE,
56 ResType::RES_TYPE_SEND_FRAME_EVENT,
57 ResType::RES_TYPE_CLICK_RECOGNIZE,
58 ResType::RES_TYPE_AXIS_EVENT,
59 });
60 }
61
~SlideRecognizer()62 SlideRecognizer::~SlideRecognizer()
63 {
64 RESSCHED_LOGI("~UpdatingSceneRecognizer");
65 }
66
OnDispatchResource(uint32_t resType,int64_t value,const nlohmann::json & payload)67 void SlideRecognizer::OnDispatchResource(uint32_t resType, int64_t value, const nlohmann::json& payload)
68 {
69 switch (resType) {
70 case ResType::RES_TYPE_SLIDE_RECOGNIZE:
71 HandleSlideEvent(value, payload);
72 break;
73 case ResType::RES_TYPE_SEND_FRAME_EVENT:
74 HandleSendFrameEvent(FillRealPidAndUid(payload));
75 break;
76 case ResType::RES_TYPE_CLICK_RECOGNIZE:
77 HandleClickEvent(value, payload);
78 break;
79 case ResType::RES_TYPE_AXIS_EVENT:
80 if (value == ResType::AxisEventStatus::AXIS_EVENT_END) {
81 HandleClickEvent(ResType::ClickEventType::TOUCH_EVENT_UP, payload);
82 }
83 break;
84 default:
85 RESSCHED_LOGD("unkonw resType");
86 break;
87 }
88 }
89
HandleSlideEvent(int64_t value,const nlohmann::json & payload)90 void SlideRecognizer::HandleSlideEvent(int64_t value, const nlohmann::json& payload)
91 {
92 if (value == ResType::SlideEventStatus::SLIDE_EVENT_DETECTING) {
93 HandleSlideDetecting(payload);
94 } else if (value == ResType::SlideEventStatus::SLIDE_EVENT_ON) {
95 HandleListFlingStart(payload);
96 } else if (value == ResType::SlideEventStatus::SLIDE_EVENT_OFF) {
97 HandleSlideOFFEvent();
98 }
99 }
100
HandleSlideOFFEvent()101 void SlideRecognizer::HandleSlideOFFEvent()
102 {
103 std::lock_guard<ffrt::recursive_mutex> lock(stateMutex);
104 if (listFlingEndTask_) {
105 ffrt::skip(listFlingEndTask_);
106 }
107 if (listFlingTimeOutTask_) {
108 ffrt::skip(listFlingTimeOutTask_);
109 }
110 nlohmann::json extInfo;
111 EventListenerMgr::GetInstance().SendEvent(ResType::EventType::EVENT_DRAW_FRAME_REPORT,
112 ResType::EventValue::EVENT_VALUE_DRAW_FRAME_REPORT_STOP, extInfo);
113 g_slideState = SlideRecognizeStat::IDLE;
114 }
115
HandleSlideDetecting(const nlohmann::json & payload)116 void SlideRecognizer::HandleSlideDetecting(const nlohmann::json& payload)
117 {
118 isInTouching_ = true;
119 SceneRecognizerMgr::GetInstance().SubmitTask([this, payload]() {
120 StartDetecting(payload);
121 });
122 }
123
StartDetecting(const nlohmann::json & payload)124 void SlideRecognizer::StartDetecting(const nlohmann::json& payload)
125 {
126 nlohmann::json extInfo;
127 EventListenerMgr::GetInstance().SendEvent(ResType::EventType::EVENT_DRAW_FRAME_REPORT,
128 ResType::EventValue::EVENT_VALUE_DRAW_FRAME_REPORT_START, extInfo);
129 slideDetectingTime_ = ResCommonUtil::GetNowMillTime(true);
130 g_slideState = SlideRecognizeStat::SLIDE_NORMAL_DETECTING;
131 if (!payload.contains("clientPid") || !payload["clientPid"].is_string()) {
132 RESSCHED_LOGE("payload with no clientPid");
133 return;
134 }
135 slidePid_ = payload["clientPid"];
136 if (!payload.contains("callingUid") || !payload["callingUid"].is_string()) {
137 RESSCHED_LOGE("payload with no callingUid");
138 return;
139 }
140 slideUid_ = payload["callingUid"];
141 if (payload.contains("scrTid") && payload["scrTid"].is_string()) {
142 scrTid_ = payload["scrTid"];
143 }
144 }
145
HandleListFlingStart(const nlohmann::json & payload)146 void SlideRecognizer::HandleListFlingStart(const nlohmann::json& payload)
147 {
148 std::lock_guard<ffrt::recursive_mutex> lock(stateMutex);
149 nlohmann::json extInfo;
150 EventListenerMgr::GetInstance().SendEvent(ResType::EventType::EVENT_DRAW_FRAME_REPORT,
151 ResType::EventValue::EVENT_VALUE_DRAW_FRAME_REPORT_START, extInfo);
152 if (listFlingEndTask_) {
153 ffrt::skip(listFlingEndTask_);
154 }
155 listFlingEndTask_ = ffrt::submit_h([payload]() {
156 g_reportListFlingLockedEnd(payload);
157 }, {}, {}, ffrt::task_attr().delay(listFlingEndTime_));
158 if (listFlingTimeOutTask_) {
159 ffrt::skip(listFlingTimeOutTask_);
160 }
161 listFlingTimeOutTask_ = ffrt::submit_h([payload]() {
162 g_reportListFlingLockedEnd(payload);
163 }, {}, {}, ffrt::task_attr().delay(listFlingTimeOutTime_));
164 }
165
HandleSendFrameEvent(const nlohmann::json & payload)166 void SlideRecognizer::HandleSendFrameEvent(const nlohmann::json& payload)
167 {
168 std::lock_guard<ffrt::recursive_mutex> lock(stateMutex);
169 if (g_slideState == SlideRecognizeStat::SLIDE_NORMAL_DETECTING) {
170 if (isInTouching_) {
171 ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_SLIDE_RECOGNIZE,
172 ResType::SlideEventStatus::SLIDE_NORMAL_BEGIN, payload);
173 g_slideState = SlideRecognizeStat::SLIDE_NORMAL;
174 } else {
175 g_slideState = SlideRecognizeStat::IDLE;
176 }
177 nlohmann::json extInfo;
178 EventListenerMgr::GetInstance().SendEvent(ResType::EventType::EVENT_DRAW_FRAME_REPORT,
179 ResType::EventValue::EVENT_VALUE_DRAW_FRAME_REPORT_STOP, extInfo);
180 } else if (g_slideState == SlideRecognizeStat::LIST_FLING) {
181 if (listFlingEndTask_) {
182 ffrt::skip(listFlingEndTask_);
183 }
184 listFlingEndTask_ = ffrt::submit_h([payload]() {
185 g_reportListFlingLockedEnd(payload);
186 }, {}, {}, ffrt::task_attr().delay(listFlingEndTime_));
187 }
188 }
189
ListFlingEnd(const nlohmann::json & payload)190 void SlideRecognizer::ListFlingEnd(const nlohmann::json& payload)
191 {
192 if (g_slideState != SlideRecognizeStat::LIST_FLING) {
193 return;
194 }
195 if (listFlingEndTask_) {
196 ffrt::skip(listFlingEndTask_);
197 }
198 if (listFlingTimeOutTask_) {
199 ffrt::skip(listFlingTimeOutTask_);
200 }
201 listFlingEndTask_ = nullptr;
202 listFlingTimeOutTask_ = nullptr;
203 g_reportListFlingLockedEnd(FillRealPidAndUid(payload));
204 }
205
HandleClickEvent(int64_t value,const nlohmann::json & payload)206 void SlideRecognizer::HandleClickEvent(int64_t value, const nlohmann::json& payload)
207 {
208 std::lock_guard<ffrt::recursive_mutex> lock(stateMutex);
209 if (value == ResType::ClickEventType::TOUCH_EVENT_DOWN) {
210 ListFlingEnd(payload);
211 g_slideState = SlideRecognizeStat::IDLE;
212 isInTouching_ = true;
213 } else if (value == ResType::ClickEventType::TOUCH_EVENT_UP ||
214 value == ResType::ClickEventType::TOUCH_EVENT_PULL_UP) {
215 isInTouching_ = false;
216 }
217 //not in slide stat or slide detecting stat
218 if (g_slideState != SlideRecognizeStat::SLIDE_NORMAL &&
219 g_slideState != SlideRecognizeStat::SLIDE_NORMAL_DETECTING) {
220 return;
221 }
222 // receive up event, silde normal end
223 if (value == ResType::ClickEventType::TOUCH_EVENT_UP ||
224 value == ResType::ClickEventType::TOUCH_EVENT_PULL_UP) {
225 if (g_slideState != SlideRecognizeStat::SLIDE_NORMAL_DETECTING) {
226 ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_SLIDE_RECOGNIZE,
227 ResType::SlideEventStatus::SLIDE_NORMAL_END, payload);
228 }
229 float upSpeed = 0.0;
230 if (!payload.contains("clientPid") || !payload["clientPid"].is_string()) {
231 RESSCHED_LOGE("payload with no clientPid");
232 return;
233 }
234 if (!payload.contains(UP_SPEED_KEY) || !payload[UP_SPEED_KEY].is_string()) {
235 return;
236 }
237 if (!ResCommonUtil::StrToFloat(payload[UP_SPEED_KEY], upSpeed)) {
238 return;
239 }
240 std::string trace_str("TOUCH EVENT UPSPEED: ");
241 trace_str.append(std::to_string(upSpeed));
242 StartTrace(HITRACE_TAG_APP, trace_str, -1);
243 FinishTrace(HITRACE_TAG_APP);
244 if (payload.contains(AXIS_EVENT_TYPE) && payload[AXIS_EVENT_TYPE].is_string() &&
245 payload[AXIS_EVENT_TYPE] == AXIS_EVENT_TYPE) {
246 upSpeed = upSpeed * AXIS_EVENT_FACTOR;
247 }
248 // if up speed large than LIST_FLING_SPEED_LIMIT,start recognize list fling.
249 if (upSpeed > listFlingSpeedLimit_) {
250 nlohmann::json extInfo;
251 EventListenerMgr::GetInstance().SendEvent(ResType::EventType::EVENT_DRAW_FRAME_REPORT,
252 ResType::EventValue::EVENT_VALUE_DRAW_FRAME_REPORT_START, extInfo);
253 ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_SLIDE_RECOGNIZE,
254 ResType::SlideEventStatus::SLIDE_EVENT_ON, FillRealPidAndUid(payload));
255 g_slideState = SlideRecognizeStat::LIST_FLING;
256 }
257 }
258 }
259
FillRealPidAndUid(const nlohmann::json & payload)260 nlohmann::json SlideRecognizer::FillRealPidAndUid(const nlohmann::json& payload)
261 {
262 nlohmann::json payloadM = payload;
263 if (!slidePid_.empty()) {
264 payloadM["clientPid"] = slidePid_;
265 }
266 if (!slideUid_.empty()) {
267 payloadM["callingUid"] = slideUid_;
268 }
269 payloadM["scrTid"] = scrTid_;
270 return payloadM;
271 }
272
SetListFlingTimeoutTime(int64_t value)273 void SlideRecognizer::SetListFlingTimeoutTime(int64_t value)
274 {
275 listFlingTimeOutTime_ = value;
276 }
277
SetListFlingEndTime(int64_t value)278 void SlideRecognizer::SetListFlingEndTime(int64_t value)
279 {
280 listFlingEndTime_ = value;
281 }
282
SetListFlingSpeedLimit(float value)283 void SlideRecognizer::SetListFlingSpeedLimit(float value)
284 {
285 listFlingSpeedLimit_ = value;
286 }
287
GetSlideStatus()288 uint32_t SlideRecognizer::GetSlideStatus()
289 {
290 return g_slideState;
291 }
292 } // namespace ResourceSchedule
293 } // namespace OHOS