• 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;
__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