1 /*
2 * Copyright (c) 2021-2023 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 "key_event_normalize.h"
17
18 #include <linux/input.h>
19 #include <parameters.h>
20
21 #include "input_device_manager.h"
22 #include "input_windows_manager.h"
23 #include "key_map_manager.h"
24 #include "key_unicode_transformation.h"
25
26 #undef MMI_LOG_DOMAIN
27 #define MMI_LOG_DOMAIN MMI_LOG_DISPATCH
28 #undef MMI_LOG_TAG
29 #define MMI_LOG_TAG "KeyEventNormalize"
30
31 namespace OHOS {
32 namespace MMI {
33 namespace {
34 constexpr uint32_t KEYSTATUS { 0 };
35 } // namespace
36
KeyEventNormalize()37 KeyEventNormalize::KeyEventNormalize() {}
38
~KeyEventNormalize()39 KeyEventNormalize::~KeyEventNormalize() {}
40
GetKeyEvent()41 std::shared_ptr<KeyEvent> KeyEventNormalize::GetKeyEvent()
42 {
43 if (keyEvent_ == nullptr) {
44 keyEvent_ = KeyEvent::Create();
45 }
46 return keyEvent_;
47 }
48
Normalize(struct libinput_event * event,std::shared_ptr<KeyEvent> keyEvent)49 int32_t KeyEventNormalize::Normalize(struct libinput_event *event, std::shared_ptr<KeyEvent> keyEvent)
50 {
51 CALL_DEBUG_ENTER;
52 CHKPR(event, PARAM_INPUT_INVALID);
53 CHKPR(keyEvent, ERROR_NULL_POINTER);
54 keyEvent->UpdateId();
55 StartLogTraceId(keyEvent->GetId(), keyEvent->GetEventType(), keyEvent->GetKeyAction());
56 auto data = libinput_event_get_keyboard_event(event);
57 CHKPR(data, ERROR_NULL_POINTER);
58
59 auto device = libinput_event_get_device(event);
60 CHKPR(device, ERROR_NULL_POINTER);
61 int32_t deviceId = INPUT_DEV_MGR->FindInputDeviceId(device);
62 int32_t keyCode = static_cast<int32_t>(libinput_event_keyboard_get_key(data));
63 MMI_HILOGD("The linux input keyCode:%{private}d", keyCode);
64 keyCode = KeyMapMgr->TransferDeviceKeyValue(device, keyCode);
65 int32_t keyAction = (libinput_event_keyboard_get_key_state(data) == 0) ?
66 (KeyEvent::KEY_ACTION_UP) : (KeyEvent::KEY_ACTION_DOWN);
67 keyCode = TransformVolumeKey(device, keyCode, keyAction);
68 auto preAction = keyEvent->GetAction();
69 if (preAction == KeyEvent::KEY_ACTION_UP) {
70 std::optional<KeyEvent::KeyItem> preUpKeyItem = keyEvent->GetKeyItem();
71 if (preUpKeyItem) {
72 keyEvent->RemoveReleasedKeyItems(*preUpKeyItem);
73 } else {
74 MMI_HILOGE("The preUpKeyItem is nullopt");
75 }
76 }
77 uint64_t time = libinput_event_keyboard_get_time_usec(data);
78 keyEvent->SetActionTime(time);
79 keyEvent->SetAction(keyAction);
80 keyEvent->SetDeviceId(deviceId);
81 keyEvent->SetKeyCode(keyCode);
82 keyEvent->SetKeyAction(keyAction);
83 StartLogTraceId(keyEvent->GetId(), keyEvent->GetEventType(), keyEvent->GetKeyAction());
84 if (keyEvent->GetPressedKeys().empty()) {
85 keyEvent->SetActionStartTime(time);
86 }
87
88 KeyEvent::KeyItem item;
89 bool isKeyPressed = (libinput_event_keyboard_get_key_state(data) != KEYSTATUS);
90 item.SetDownTime(time);
91 item.SetKeyCode(keyCode);
92 item.SetDeviceId(deviceId);
93 item.SetPressed(isKeyPressed);
94 item.SetUnicode(KeyCodeToUnicode(keyCode, keyEvent));
95
96 HandleKeyAction(device, item, keyEvent);
97
98 int32_t keyIntention = KeyItemsTransKeyIntention(keyEvent->GetKeyItems());
99 keyEvent->SetKeyIntention(keyIntention);
100 return RET_OK;
101 }
102
HandleKeyAction(struct libinput_device * device,KeyEvent::KeyItem & item,std::shared_ptr<KeyEvent> keyEvent)103 void KeyEventNormalize::HandleKeyAction(struct libinput_device* device, KeyEvent::KeyItem &item,
104 std::shared_ptr<KeyEvent> keyEvent)
105 {
106 CHKPV(device);
107 CHKPV(keyEvent);
108 int32_t keyAction = keyEvent->GetAction();
109 int32_t keyCode = keyEvent->GetKeyCode();
110 if (keyAction == KeyEvent::KEY_ACTION_DOWN) {
111 keyEvent->AddPressedKeyItems(item);
112 }
113 if (keyAction == KeyEvent::KEY_ACTION_UP) {
114 int32_t funcKey = keyEvent->TransitionFunctionKey(keyCode);
115 if (funcKey != KeyEvent::UNKNOWN_FUNCTION_KEY) {
116 int32_t ret = keyEvent->SetFunctionKey(funcKey, libinput_get_funckey_state(device, funcKey));
117 if (ret == funcKey) {
118 MMI_HILOGD("Set function key:%{public}d to state:%{public}d succeed",
119 funcKey, keyEvent->GetFunctionKey(funcKey));
120 }
121 }
122 std::optional<KeyEvent::KeyItem> pressedKeyItem = keyEvent->GetKeyItem(keyCode);
123 if (pressedKeyItem) {
124 item.SetDownTime(pressedKeyItem->GetDownTime());
125 } else {
126 MMI_HILOGE("Find pressed key failed, keyCode:%{private}d", keyCode);
127 }
128 keyEvent->RemoveReleasedKeyItems(item);
129 keyEvent->AddPressedKeyItems(item);
130 }
131 }
132
ResetKeyEvent(struct libinput_device * device)133 void KeyEventNormalize::ResetKeyEvent(struct libinput_device* device)
134 {
135 if (INPUT_DEV_MGR->IsKeyboardDevice(device) || INPUT_DEV_MGR->IsPointerDevice(device)) {
136 if (keyEvent_ == nullptr) {
137 keyEvent_ = KeyEvent::Create();
138 }
139 if (libinput_has_event_led_type(device)) {
140 CHKPV(keyEvent_);
141 const std::vector<int32_t> funcKeys = {
142 KeyEvent::NUM_LOCK_FUNCTION_KEY,
143 KeyEvent::CAPS_LOCK_FUNCTION_KEY,
144 KeyEvent::SCROLL_LOCK_FUNCTION_KEY
145 };
146 for (const auto &funcKey : funcKeys) {
147 keyEvent_->SetFunctionKey(funcKey, libinput_get_funckey_state(device, funcKey));
148 }
149 }
150 }
151 }
152
SetShieldStatus(int32_t shieldMode,bool isShield)153 int32_t KeyEventNormalize::SetShieldStatus(int32_t shieldMode, bool isShield)
154 {
155 std::lock_guard<std::mutex> guard(mtx_);
156 MMI_HILOGI("Last shield mode:%{public}d, set shield mode:%{public}d, status:%{public}d",
157 lastShieldMode_, shieldMode, isShield);
158 auto iter = shieldStatus_.find(lastShieldMode_);
159 if (isShield) {
160 if (lastShieldMode_ == shieldMode) {
161 MMI_HILOGI("Last shield mode equal with shield mode");
162 } else if (iter != shieldStatus_.end()) {
163 iter->second = false;
164 } else {
165 MMI_HILOGI("Last shield mode unset");
166 }
167 lastShieldMode_ = shieldMode;
168 } else if (lastShieldMode_ != shieldMode) {
169 MMI_HILOGI("Shield mode:%{public}d is already false", shieldMode);
170 return RET_OK;
171 } else {
172 MMI_HILOGI("lastShieldMode_ unset");
173 lastShieldMode_ = SHIELD_MODE::UNSET_MODE;
174 }
175 iter = shieldStatus_.find(shieldMode);
176 if (iter == shieldStatus_.end()) {
177 MMI_HILOGE("Find shieldMode:%{public}d failed", shieldMode);
178 return RET_ERR;
179 }
180 iter->second = isShield;
181 MMI_HILOGI("Last shield mode:%{public}d, set shield mode:%{public}d, status:%{public}d",
182 lastShieldMode_, shieldMode, isShield);
183 return RET_OK;
184 }
185
GetShieldStatus(int32_t shieldMode,bool & isShield)186 int32_t KeyEventNormalize::GetShieldStatus(int32_t shieldMode, bool &isShield)
187 {
188 CALL_DEBUG_ENTER;
189 std::lock_guard<std::mutex> guard(mtx_);
190 auto iter = shieldStatus_.find(shieldMode);
191 if (iter == shieldStatus_.end()) {
192 MMI_HILOGE("Find shieldMode:%{public}d failed", shieldMode);
193 return RET_ERR;
194 }
195 isShield = iter->second;
196 MMI_HILOGI("Last shield mode:%{public}d, get shield mode:%{public}d, status:%{public}d",
197 lastShieldMode_, shieldMode, isShield);
198 return RET_OK;
199 }
200
GetCurrentShieldMode()201 int32_t KeyEventNormalize::GetCurrentShieldMode()
202 {
203 std::lock_guard<std::mutex> guard(mtx_);
204 return lastShieldMode_;
205 }
206
SetCurrentShieldMode(int32_t shieldMode)207 void KeyEventNormalize::SetCurrentShieldMode(int32_t shieldMode)
208 {
209 std::lock_guard<std::mutex> guard(mtx_);
210 lastShieldMode_ = shieldMode;
211 }
212
TransformVolumeKey(struct libinput_device * dev,int32_t keyCode,int32_t keyAction) const213 int32_t KeyEventNormalize::TransformVolumeKey(struct libinput_device *dev, int32_t keyCode, int32_t keyAction) const
214 {
215 static std::once_flag flag;
216 static std::map<int32_t, DisplayMode> displayModes {
217 { KeyEvent::KEYCODE_VOLUME_DOWN, DisplayMode::UNKNOWN },
218 { KeyEvent::KEYCODE_VOLUME_UP, DisplayMode::UNKNOWN },
219 };
220 static std::string product;
221 const std::string theProduct { "LEM" };
222
223 std::call_once(flag, []() {
224 product = OHOS::system::GetParameter("const.build.product", "");
225 });
226 if (product != theProduct) {
227 return keyCode;
228 }
229 auto iter = displayModes.find(keyCode);
230 if (iter == displayModes.end()) {
231 return keyCode;
232 }
233 if (keyAction == KeyEvent::KEY_ACTION_DOWN) {
234 iter->second = WIN_MGR->GetDisplayMode();
235 if (iter->second != DisplayMode::SUB) {
236 return keyCode;
237 }
238 } else if (iter->second != DisplayMode::SUB) {
239 return keyCode;
240 }
241 const char *name = libinput_device_get_name(dev);
242 int32_t busType = static_cast<int32_t>(libinput_device_get_id_bustype(dev));
243 MMI_HILOGD("Flip volume keys upon fold: Dev:%{public}s, Bus:%{public}d",
244 name != nullptr ? name : "(null)", busType);
245 if (busType != BUS_HOST) {
246 return keyCode;
247 }
248 return (keyCode == KeyEvent::KEYCODE_VOLUME_DOWN ? KeyEvent::KEYCODE_VOLUME_UP : KeyEvent::KEYCODE_VOLUME_DOWN);
249 }
250 } // namespace MMI
251 } // namespace OHOS
252