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;
__anon40896f580202(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 RESSCHED_LOGI("~UpdatingSceneRecognizer");
55 }
56
OnDispatchResource(uint32_t resType,int64_t value,const nlohmann::json & payload)57 void SlideRecognizer::OnDispatchResource(uint32_t resType, int64_t value, const nlohmann::json& payload)
58 {
59 switch (resType) {
60 case ResType::RES_TYPE_SLIDE_RECOGNIZE:
61 HandleSlideEvent(value, payload);
62 break;
63 case ResType::RES_TYPE_SEND_FRAME_EVENT:
64 HandleSendFrameEvent(FillRealPidAndUid(payload));
65 break;
66 case ResType::RES_TYPE_CLICK_RECOGNIZE:
67 HandleClickEvent(value, payload);
68 break;
69 case ResType::RES_TYPE_AXIS_EVENT:
70 if (value == ResType::AxisEventStatus::AXIS_EVENT_END) {
71 HandleClickEvent(ResType::ClickEventType::TOUCH_EVENT_UP, payload);
72 }
73 break;
74 default:
75 RESSCHED_LOGD("unkonw resType");
76 break;
77 }
78 }
79
HandleSlideEvent(int64_t value,const nlohmann::json & payload)80 void SlideRecognizer::HandleSlideEvent(int64_t value, const nlohmann::json& payload)
81 {
82 if (value == ResType::SlideEventStatus::SLIDE_EVENT_DETECTING) {
83 HandleSlideDetecting(payload);
84 } else if (value == ResType::SlideEventStatus::SLIDE_EVENT_ON) {
85 HandleListFlingStart(payload);
86 } else if (value == ResType::SlideEventStatus::SLIDE_EVENT_OFF) {
87 HandleSlideOFFEvent();
88 }
89 }
90
HandleSlideOFFEvent()91 void SlideRecognizer::HandleSlideOFFEvent()
92 {
93 std::lock_guard<ffrt::recursive_mutex> lock(stateMutex);
94 if (listFlingEndTask_) {
95 ffrt::skip(listFlingEndTask_);
96 }
97 if (listFlingTimeOutTask_) {
98 ffrt::skip(listFlingTimeOutTask_);
99 }
100 nlohmann::json extInfo;
101 EventListenerMgr::GetInstance().SendEvent(ResType::EventType::EVENT_DRAW_FRAME_REPORT,
102 ResType::EventValue::EVENT_VALUE_DRAW_FRAME_REPORT_STOP, extInfo);
103 g_slideState = SlideRecognizeStat::IDLE;
104 }
105
HandleSlideDetecting(const nlohmann::json & payload)106 void SlideRecognizer::HandleSlideDetecting(const nlohmann::json& payload)
107 {
108 if (g_slideState == SlideRecognizeStat::LIST_FLING) {
109 if (listFlingEndTask_) {
110 ffrt::skip(listFlingEndTask_);
111 }
112 if (listFlingTimeOutTask_) {
113 ffrt::skip(listFlingTimeOutTask_);
114 }
115 listFlingEndTask_ = nullptr;
116 listFlingTimeOutTask_ = nullptr;
117 g_reportListFlingLockedEnd(FillRealPidAndUid(payload));
118 }
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 }
142
HandleListFlingStart(const nlohmann::json & payload)143 void SlideRecognizer::HandleListFlingStart(const nlohmann::json& payload)
144 {
145 std::lock_guard<ffrt::recursive_mutex> lock(stateMutex);
146 if (g_slideState == SlideRecognizeStat::LIST_FLING) {
147 return;
148 }
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 g_slideState = SlideRecognizeStat::LIST_FLING;
153 if (listFlingEndTask_) {
154 ffrt::skip(listFlingEndTask_);
155 }
156 listFlingEndTask_ = ffrt::submit_h([payload]() {
157 g_reportListFlingLockedEnd(payload);
158 }, {}, {}, ffrt::task_attr().delay(listFlingEndTime_));
159 if (listFlingTimeOutTask_) {
160 ffrt::skip(listFlingTimeOutTask_);
161 }
162 listFlingTimeOutTask_ = ffrt::submit_h([payload]() {
163 g_reportListFlingLockedEnd(payload);
164 }, {}, {}, ffrt::task_attr().delay(listFlingTimeOutTime_));
165 }
166
HandleSendFrameEvent(const nlohmann::json & payload)167 void SlideRecognizer::HandleSendFrameEvent(const nlohmann::json& payload)
168 {
169 std::lock_guard<ffrt::recursive_mutex> lock(stateMutex);
170 if (g_slideState == SlideRecognizeStat::SLIDE_NORMAL_DETECTING) {
171 int64_t nowTime = ResCommonUtil::GetNowMillTime(true);
172 if (nowTime - slideDetectingTime_ < slideNormalDecectingTime_) {
173 ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_SLIDE_RECOGNIZE,
174 ResType::SlideEventStatus::SLIDE_NORMAL_BEGIN, payload);
175 g_slideState = SlideRecognizeStat::SLIDE_NORMAL;
176 } else {
177 g_slideState = SlideRecognizeStat::IDLE;
178 }
179 nlohmann::json extInfo;
180 EventListenerMgr::GetInstance().SendEvent(ResType::EventType::EVENT_DRAW_FRAME_REPORT,
181 ResType::EventValue::EVENT_VALUE_DRAW_FRAME_REPORT_STOP, extInfo);
182 } else if (g_slideState == SlideRecognizeStat::LIST_FLING) {
183 if (listFlingEndTask_) {
184 ffrt::skip(listFlingEndTask_);
185 }
186 listFlingEndTask_ = ffrt::submit_h([payload]() {
187 g_reportListFlingLockedEnd(payload);
188 }, {}, {}, ffrt::task_attr().delay(listFlingEndTime_));
189 }
190 }
191
HandleClickEvent(int64_t value,const nlohmann::json & payload)192 void SlideRecognizer::HandleClickEvent(int64_t value, const nlohmann::json& payload)
193 {
194 std::lock_guard<ffrt::recursive_mutex> lock(stateMutex);
195 //not in slide stat or slide detecting stat
196 if (g_slideState != SlideRecognizeStat::SLIDE_NORMAL &&
197 g_slideState != SlideRecognizeStat::SLIDE_NORMAL_DETECTING) {
198 return;
199 }
200 if (value == ResType::ClickEventType::TOUCH_EVENT_DOWN) {
201 g_slideState = SlideRecognizeStat::IDLE;
202 return;
203 }
204 // receive up event, silde normal end
205 if (value == ResType::ClickEventType::TOUCH_EVENT_UP ||
206 value == ResType::ClickEventType::TOUCH_EVENT_PULL_UP) {
207 if (g_slideState != SlideRecognizeStat::SLIDE_NORMAL_DETECTING) {
208 ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_SLIDE_RECOGNIZE,
209 ResType::SlideEventStatus::SLIDE_NORMAL_END, payload);
210 }
211 float upSpeed = 0.0;
212 if (!payload.contains("clientPid") || !payload["clientPid"].is_string()) {
213 RESSCHED_LOGE("payload with no clientPid");
214 return;
215 }
216 if (!payload.contains(UP_SPEED_KEY) || !payload[UP_SPEED_KEY].is_string()) {
217 return;
218 }
219 if (!ResCommonUtil::StrToFloat(payload[UP_SPEED_KEY], upSpeed)) {
220 return;
221 }
222 std::string trace_str("TOUCH EVENT UPSPEED: ");
223 trace_str.append(std::to_string(upSpeed));
224 StartTrace(HITRACE_TAG_APP, trace_str, -1);
225 FinishTrace(HITRACE_TAG_APP);
226 if (payload.contains(AXIS_EVENT_TYPE) && payload[AXIS_EVENT_TYPE].is_string() &&
227 payload[AXIS_EVENT_TYPE] == AXIS_EVENT_TYPE) {
228 upSpeed = upSpeed * AXIS_EVENT_FACTOR;
229 }
230 // if up speed large than LIST_FLING_SPEED_LIMIT,start recognize list fling.
231 if (upSpeed > listFlingSpeedLimit_) {
232 nlohmann::json extInfo;
233 EventListenerMgr::GetInstance().SendEvent(ResType::EventType::EVENT_DRAW_FRAME_REPORT,
234 ResType::EventValue::EVENT_VALUE_DRAW_FRAME_REPORT_START, extInfo);
235 ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_SLIDE_RECOGNIZE,
236 ResType::SlideEventStatus::SLIDE_EVENT_ON, FillRealPidAndUid(payload));
237 g_slideState = SlideRecognizeStat::LIST_FLING;
238 }
239 }
240 }
241
FillRealPidAndUid(const nlohmann::json & payload)242 nlohmann::json SlideRecognizer::FillRealPidAndUid(const nlohmann::json& payload)
243 {
244 nlohmann::json payloadM = payload;
245 if (!slidePid_.empty()) {
246 payloadM["clientPid"] = slidePid_;
247 }
248 if (!slideUid_.empty()) {
249 payloadM["callingUid"] = slideUid_;
250 }
251 return payloadM;
252 }
253
SetListFlingTimeoutTime(int64_t value)254 void SlideRecognizer::SetListFlingTimeoutTime(int64_t value)
255 {
256 listFlingTimeOutTime_ = value;
257 }
258
SetListFlingEndTime(int64_t value)259 void SlideRecognizer::SetListFlingEndTime(int64_t value)
260 {
261 listFlingEndTime_ = value;
262 }
263
SetListFlingSpeedLimit(float value)264 void SlideRecognizer::SetListFlingSpeedLimit(float value)
265 {
266 listFlingSpeedLimit_ = value;
267 }
268
SetSlideNormalDetectingTime(int64_t value)269 void SlideRecognizer::SetSlideNormalDetectingTime(int64_t value)
270 {
271 slideNormalDecectingTime_ = value;
272 }
273 } // namespace ResourceSchedule
274 } // namespace OHOS