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;
__anon9c329c500202(const nlohmann::json payload) 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     // receive up event, silde normal end
181     if (value == ResType::ClickEventType::TOUCH_EVENT_UP ||
182         value == ResType::ClickEventType::TOUCH_EVENT_PULL_UP) {
183         ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_SLIDE_RECOGNIZE,
184             ResType::SlideEventStatus::SLIDE_NORMAL_END, payload);
185         float upSpeed = 0.0;
186         if (!payload.contains("clientPid") || !payload["clientPid"].is_string()) {
187             RESSCHED_LOGE("payload with no clientPid");
188             return;
189         }
190         slidePid_ = payload["clientPid"];
191         if (!payload.contains(UP_SPEED_KEY) || !payload[UP_SPEED_KEY].is_string()) {
192             return;
193         }
194         // if up speed large than LIST_FLING_SPEED_LIMIT,start recognize list fling.
195         if (ResCommonUtil::StrToFloat(payload[UP_SPEED_KEY], upSpeed) && upSpeed > listFlingSpeedLimit_) {
196             nlohmann::json extInfo;
197             EventListenerMgr::GetInstance().SendEvent(ResType::EventType::EVENT_DRAW_FRAME_REPORT,
198                 ResType::EventValue::EVENT_VALUE_DRAW_FRAME_REPORT_START, extInfo);
199             ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_SLIDE_RECOGNIZE,
200                 ResType::SlideEventStatus::SLIDE_EVENT_ON, payload);
201         }
202     }
203 }
204 
FillRealPid(const nlohmann::json & payload)205 nlohmann::json SlideRecognizer::FillRealPid(const nlohmann::json& payload)
206 {
207     if (slidePid_.empty()) {
208         return payload;
209     }
210     nlohmann::json payloadM = payload;
211     payloadM["clientPid"] = slidePid_;
212     return payloadM;
213 }
214 
SetListFlingTimeoutTime(int64_t value)215 void SlideRecognizer::SetListFlingTimeoutTime(int64_t value)
216 {
217     listFlingTimeOutTime_ = value;
218 }
219 
SetListFlingEndTime(int64_t value)220 void SlideRecognizer::SetListFlingEndTime(int64_t value)
221 {
222     listFlingEndTime_ = value;
223 }
224 
SetListFlingSpeedLimit(float value)225 void SlideRecognizer::SetListFlingSpeedLimit(float value)
226 {
227     listFlingSpeedLimit_ = value;
228 }
229 
SetSlideNormalDetectingTime(int64_t value)230 void SlideRecognizer::SetSlideNormalDetectingTime(int64_t value)
231 {
232     slideNormalDecectingTime_ = value;
233 }
234 } // namespace ResourceSchedule
235 } // namespace OHOS