1 /*
2 * Copyright (c) 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
16 #include "folding_area_toast.h"
17 #include "common_event_manager.h"
18 #include "common_event_support.h"
19 #include "want.h"
20 #include "parameters.h"
21 #include "util.h"
22 #include "timer_manager.h"
23 #include "input_device_manager.h"
24 #include "input_windows_manager.h"
25 #include "product_type_parser.h"
26 #include "product_name_definition.h"
27
28 #undef MMI_LOG_DOMAIN
29 #define MMI_LOG_DOMAIN MMI_LOG_SERVER
30 #undef MMI_LOG_TAG
31 #define MMI_LOG_TAG "FoldingAreaToast"
32
33 namespace OHOS {
34 namespace MMI {
35 namespace {
36 const std::string OHOS_PERMISSION_FOLDING_AREA_TOUCH = "ohos.permission.NOTIFICATION_CONTROLLER";
37 const std::string FOLDAREA_TOUCH_STATUS = "usual.event.FOLDING_AREA_TOUCH";
38 const std::string FOLDAREA_TOUCH_STATE = "foldingAreaTouchState";
39 const int16_t FOLDAREA_DIM2_START = 1608;
40 const int16_t FOLDAREA_DIM2_END = 1688;
41 const int16_t FOLDAREA_MAX_PRESS_TIMES = 500;
42 const int16_t FOLDAREA_MAX_CLK_DB_TIME = 800;
43 const int16_t FOLDAREA_MAX_CLK_DB_END_TIME = 1500;
44 const int16_t FOLDAREA_MAX_CLK_NUM = 5;
45 const int16_t FOLDAREA_MAX_CLK_SAME_AREA = 100;
46 const std::string PRODUCT_TYPE = OHOS::system::GetParameter("const.build.product", "HYM");
47 } // namespace
48
FoldingAreaToast()49 FoldingAreaToast::FoldingAreaToast()
50 {
51 // init touch device Id.
52 deviceId_ = -1;
53 }
54
55 FoldingAreaToast::~FoldingAreaToast() = default;
56
NotifyFoldingAreaTouchStatus(const int8_t state)57 void FoldingAreaToast::NotifyFoldingAreaTouchStatus(const int8_t state)
58 {
59 OHOS::AAFwk::Want want;
60 want.SetAction(FOLDAREA_TOUCH_STATUS);
61 want.SetParam(FOLDAREA_TOUCH_STATE, state);
62 MMI_HILOGD("TAC detect FoldingAreaTouchStatus state: %{public}d", state);
63 EventFwk::CommonEventData CommonEventData { want };
64 EventFwk::CommonEventPublishInfo publishInfo;
65 std::vector<std::string> permissionVec { OHOS_PERMISSION_FOLDING_AREA_TOUCH };
66 publishInfo.SetSubscriberPermissions(permissionVec);
67 EventFwk::CommonEventManager::PublishCommonEvent(CommonEventData, publishInfo);
68 }
69
FoldingAreaClear(void)70 void FoldingAreaToast::FoldingAreaClear(void)
71 {
72 if (!touchId2FirstDownTimes_.empty()) {
73 touchId2FirstDownTimes_.clear();
74 }
75 if (!touchId2KeepDownTimes_.empty()) {
76 touchId2KeepDownTimes_.clear();
77 }
78 if (!touchId2KeepFrames_.empty()) {
79 touchId2KeepFrames_.clear();
80 }
81 if (!tacTouchs_.empty()) {
82 tacTouchs_.clear();
83 }
84 if (!touchId2clickTouchs_.empty()) {
85 touchId2clickTouchs_.clear();
86 }
87 if (!touchId2touchNum_.empty()) {
88 touchId2touchNum_.clear();
89 }
90 clickInFoldingAreaBeginTimeStamp_ = 0;
91 touchId_ = 0;
92 pointX_ = 0;
93 pointY_ = 0;
94 }
95
FoldingAreaLongPressProcess(void)96 void FoldingAreaToast::FoldingAreaLongPressProcess(void)
97 {
98 if (pointY_ >= FOLDAREA_DIM2_START && pointY_ <= FOLDAREA_DIM2_END) {
99 touchId2KeepFrames_[touchId_]++;
100 } else {
101 touchId2KeepFrames_[touchId_] = 0;
102 }
103 if (touchId2KeepFrames_[touchId_] == 1) {
104 touchId2FirstDownTimes_[touchId_] = GetMillisTime();
105 touchId2KeepDownTimes_[touchId_] = 0;
106 }
107 if (touchId2KeepFrames_[touchId_] > 1) {
108 touchId2KeepDownTimes_[touchId_] = GetMillisTime() - touchId2FirstDownTimes_[touchId_];
109 }
110 if (touchId2KeepDownTimes_.count(touchId_) && touchId2KeepDownTimes_[touchId_] > FOLDAREA_MAX_PRESS_TIMES) {
111 MMI_HILOGD(
112 "TAC detect touch:%d, position = [%d,%d] long press frames %d cost times:%d, in folding area over 0.5s",
113 touchId_, pointX_, pointY_, touchId2KeepFrames_[touchId_], touchId2KeepDownTimes_[touchId_]);
114 NotifyFoldingAreaTouchStatus(1);
115 touchId2KeepFrames_[touchId_] = 0;
116 touchId2KeepDownTimes_[touchId_] = 0;
117 }
118 }
119
FoldingAreaGetTouchid2TouchNum(void)120 void FoldingAreaToast::FoldingAreaGetTouchid2TouchNum(void)
121 {
122 for (auto clickTouch : touchId2clickTouchs_) {
123 uint16_t clickTouchDim1 = clickTouch.second.first;
124 uint16_t clickTouchDim2 = clickTouch.second.second;
125 for (auto tacTouch : tacTouchs_) {
126 uint16_t tacTouchDim1 = tacTouch.first;
127 uint16_t tacTouchDim2 = tacTouch.second;
128 MMI_HILOGD("TAC detect clickTouch position = [%d,%d], tacTouch position = [%d,%d]",
129 clickTouchDim1, clickTouchDim2, tacTouchDim1,
130 tacTouchDim2);
131 if ((tacTouchDim1 >= clickTouchDim1 && (tacTouchDim1 - clickTouchDim1) <= FOLDAREA_MAX_CLK_SAME_AREA) ||
132 (tacTouchDim1 < clickTouchDim1 && (clickTouchDim1 - tacTouchDim1) <= FOLDAREA_MAX_CLK_SAME_AREA)) {
133 touchId2touchNum_[clickTouch.first]++;
134 }
135 }
136 }
137 }
138
FoldingAreaFastClickProcess(void)139 void FoldingAreaToast::FoldingAreaFastClickProcess(void)
140 {
141 if ((pointY_ < FOLDAREA_DIM2_START) || (pointY_ > FOLDAREA_DIM2_END)) {
142 return;
143 }
144 if (tacTouchs_.empty()) {
145 clickInFoldingAreaBeginTimeStamp_ = GetMillisTime();
146 }
147 if (GetMillisTime() < clickInFoldingAreaBeginTimeStamp_ + FOLDAREA_MAX_CLK_DB_TIME) {
148 tacTouchs_.push_back(std::make_pair(pointX_, pointY_));
149 touchId2clickTouchs_[touchId_].first = pointX_;
150 touchId2clickTouchs_[touchId_].second = pointY_;
151 }
152 if (!tacTouchs_.empty() && GetMillisTime() > clickInFoldingAreaBeginTimeStamp_ + FOLDAREA_MAX_CLK_DB_TIME &&
153 GetMillisTime() < clickInFoldingAreaBeginTimeStamp_ + FOLDAREA_MAX_CLK_DB_END_TIME) {
154 MMI_HILOGD("TAC detect tacTouchs_ over 1s, curTimeStamp:%ld", GetMillisTime());
155 FoldingAreaGetTouchid2TouchNum();
156 for (auto touchNum : touchId2touchNum_) {
157 if (touchNum.second >= FOLDAREA_MAX_CLK_NUM) {
158 MMI_HILOGD(
159 "TAC detect touch:%d fast click %d times position = [%d,%d] in 1s in folding area",
160 touchNum.first, touchNum.second, touchId2clickTouchs_[touchNum.first].first,
161 touchId2clickTouchs_[touchNum.first].second);
162 NotifyFoldingAreaTouchStatus(1);
163 }
164 }
165 FoldingAreaClear();
166 }
167 if (!tacTouchs_.empty() && GetMillisTime() > clickInFoldingAreaBeginTimeStamp_ + FOLDAREA_MAX_CLK_DB_END_TIME) {
168 FoldingAreaClear();
169 MMI_HILOGD("TAC detect over 1500ms tacTouchs_ clear");
170 }
171 }
172
FoldingAreaCheckDeviceId(struct libinput_event * event)173 void FoldingAreaToast::FoldingAreaCheckDeviceId(struct libinput_event *event)
174 {
175 if (deviceId_ == -1) {
176 libinput_device* device = libinput_event_get_device(event);
177 if (device != nullptr) {
178 deviceId_ = INPUT_DEV_MGR->FindInputDeviceId(device);
179 }
180 }
181 }
182
FoldingAreaProcess(struct libinput_event * event)183 void FoldingAreaToast::FoldingAreaProcess(struct libinput_event *event)
184 {
185 if (PRODUCT_TYPE != DEVICE_TYPE_FOLD_PC) {
186 return;
187 }
188 FoldingAreaCheckDeviceId(event);
189 libinput_event_type eventType = libinput_event_get_type(event);
190 libinput_event_touch* touch = nullptr;
191 if (eventType == LIBINPUT_EVENT_TOUCH_DOWN || eventType == LIBINPUT_EVENT_TOUCH_UP ||
192 eventType == LIBINPUT_EVENT_TOUCH_MOTION || eventType == LIBINPUT_EVENT_TOUCH_CANCEL) {
193 touch = libinput_event_get_touch_event(event);
194 if (!touch) {
195 FoldingAreaClear();
196 return;
197 }
198 EventTouch touchInfo;
199 int32_t logicalDisplayId = -1;
200 if (!WIN_MGR->TouchPointToDisplayPoint(deviceId_, touch, touchInfo, logicalDisplayId)) {
201 FoldingAreaClear();
202 return;
203 } else {
204 pointX_ = static_cast<uint16_t>(touchInfo.point.x);
205 pointY_ = static_cast<uint16_t>(touchInfo.point.y);
206 auto displayInfo = WIN_MGR->GetPhysicalDisplay(logicalDisplayId);
207 if (!displayInfo || (displayInfo != nullptr && displayInfo->direction != Direction::DIRECTION0)) {
208 FoldingAreaClear();
209 return;
210 }
211 }
212 touchId_ = libinput_event_touch_get_slot(touch);
213 if (eventType == LIBINPUT_EVENT_TOUCH_UP || eventType == LIBINPUT_EVENT_TOUCH_CANCEL) {
214 touchId2KeepFrames_[touchId_] = 0;
215 touchId2KeepDownTimes_[touchId_] = 0;
216 }
217 if (eventType == LIBINPUT_EVENT_TOUCH_DOWN || eventType == LIBINPUT_EVENT_TOUCH_MOTION) {
218 FoldingAreaLongPressProcess();
219 }
220 if (eventType == LIBINPUT_EVENT_TOUCH_DOWN) {
221 FoldingAreaFastClickProcess();
222 }
223 }
224 }
225 } // namespace MMI
226 } // namespace OHOS