• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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