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->SetSourceType(InputEvent::SOURCE_TYPE_UNKNOWN);
82 keyEvent->SetKeyCode(keyCode);
83 keyEvent->SetKeyAction(keyAction);
84 StartLogTraceId(keyEvent->GetId(), keyEvent->GetEventType(), keyEvent->GetKeyAction());
85 if (keyEvent->GetPressedKeys().empty()) {
86 keyEvent->SetActionStartTime(time);
87 }
88
89 KeyEvent::KeyItem item;
90 bool isKeyPressed = (libinput_event_keyboard_get_key_state(data) != KEYSTATUS);
91 item.SetDownTime(time);
92 item.SetKeyCode(keyCode);
93 item.SetDeviceId(deviceId);
94 item.SetPressed(isKeyPressed);
95 item.SetUnicode(KeyCodeToUnicode(keyCode, keyEvent));
96
97 HandleKeyAction(device, item, keyEvent);
98
99 int32_t keyIntention = KeyItemsTransKeyIntention(keyEvent->GetKeyItems());
100 keyEvent->SetKeyIntention(keyIntention);
101 return RET_OK;
102 }
103
HandleKeyAction(struct libinput_device * device,KeyEvent::KeyItem & item,std::shared_ptr<KeyEvent> keyEvent)104 void KeyEventNormalize::HandleKeyAction(struct libinput_device* device, KeyEvent::KeyItem &item,
105 std::shared_ptr<KeyEvent> keyEvent)
106 {
107 CHKPV(device);
108 CHKPV(keyEvent);
109 int32_t keyAction = keyEvent->GetAction();
110 int32_t keyCode = keyEvent->GetKeyCode();
111 if (keyAction == KeyEvent::KEY_ACTION_DOWN) {
112 keyEvent->AddPressedKeyItems(item);
113 }
114 if (keyAction == KeyEvent::KEY_ACTION_UP) {
115 int32_t funcKey = keyEvent->TransitionFunctionKey(keyCode);
116 if (funcKey != KeyEvent::UNKNOWN_FUNCTION_KEY) {
117 int32_t ret = keyEvent->SetFunctionKey(funcKey, libinput_get_funckey_state(device, funcKey));
118 if (ret == funcKey) {
119 MMI_HILOGD("Set function key:%{public}d to state:%{public}d succeed",
120 funcKey, keyEvent->GetFunctionKey(funcKey));
121 }
122 }
123 std::optional<KeyEvent::KeyItem> pressedKeyItem = keyEvent->GetKeyItem(keyCode);
124 if (pressedKeyItem) {
125 item.SetDownTime(pressedKeyItem->GetDownTime());
126 } else {
127 MMI_HILOGE("Find pressed key failed, keyCode:%{private}d", keyCode);
128 }
129 keyEvent->RemoveReleasedKeyItems(item);
130 keyEvent->AddPressedKeyItems(item);
131 }
132 }
133
ResetKeyEvent(struct libinput_device * device)134 void KeyEventNormalize::ResetKeyEvent(struct libinput_device* device)
135 {
136 if (INPUT_DEV_MGR->IsKeyboardDevice(device) || INPUT_DEV_MGR->IsPointerDevice(device)) {
137 if (keyEvent_ == nullptr) {
138 keyEvent_ = KeyEvent::Create();
139 }
140 if (libinput_has_event_led_type(device)) {
141 CHKPV(keyEvent_);
142 const std::vector<int32_t> funcKeys = {
143 KeyEvent::NUM_LOCK_FUNCTION_KEY,
144 KeyEvent::CAPS_LOCK_FUNCTION_KEY,
145 KeyEvent::SCROLL_LOCK_FUNCTION_KEY
146 };
147 for (const auto &funcKey : funcKeys) {
148 keyEvent_->SetFunctionKey(funcKey, libinput_get_funckey_state(device, funcKey));
149 }
150 }
151 }
152 }
153
SetShieldStatus(int32_t shieldMode,bool isShield)154 int32_t KeyEventNormalize::SetShieldStatus(int32_t shieldMode, bool isShield)
155 {
156 std::lock_guard<std::mutex> guard(mtx_);
157 MMI_HILOGI("Last shield mode:%{public}d, set shield mode:%{public}d, status:%{public}d",
158 lastShieldMode_, shieldMode, isShield);
159 auto iter = shieldStatus_.find(lastShieldMode_);
160 if (isShield) {
161 if (lastShieldMode_ == shieldMode) {
162 MMI_HILOGI("Last shield mode equal with shield mode");
163 } else if (iter != shieldStatus_.end()) {
164 iter->second = false;
165 } else {
166 MMI_HILOGI("Last shield mode unset");
167 }
168 lastShieldMode_ = shieldMode;
169 } else if (lastShieldMode_ != shieldMode) {
170 MMI_HILOGI("Shield mode:%{public}d is already false", shieldMode);
171 return RET_OK;
172 } else {
173 MMI_HILOGI("lastShieldMode_ unset");
174 lastShieldMode_ = SHIELD_MODE::UNSET_MODE;
175 }
176 iter = shieldStatus_.find(shieldMode);
177 if (iter == shieldStatus_.end()) {
178 MMI_HILOGE("Find shieldMode:%{public}d failed", shieldMode);
179 return RET_ERR;
180 }
181 iter->second = isShield;
182 MMI_HILOGI("Last shield mode:%{public}d, set shield mode:%{public}d, status:%{public}d",
183 lastShieldMode_, shieldMode, isShield);
184 return RET_OK;
185 }
186
GetShieldStatus(int32_t shieldMode,bool & isShield)187 int32_t KeyEventNormalize::GetShieldStatus(int32_t shieldMode, bool &isShield)
188 {
189 CALL_DEBUG_ENTER;
190 std::lock_guard<std::mutex> guard(mtx_);
191 auto iter = shieldStatus_.find(shieldMode);
192 if (iter == shieldStatus_.end()) {
193 MMI_HILOGE("Find shieldMode:%{public}d failed", shieldMode);
194 return RET_ERR;
195 }
196 isShield = iter->second;
197 MMI_HILOGI("Last shield mode:%{public}d, get shield mode:%{public}d, status:%{public}d",
198 lastShieldMode_, shieldMode, isShield);
199 return RET_OK;
200 }
201
GetCurrentShieldMode()202 int32_t KeyEventNormalize::GetCurrentShieldMode()
203 {
204 std::lock_guard<std::mutex> guard(mtx_);
205 return lastShieldMode_;
206 }
207
SetCurrentShieldMode(int32_t shieldMode)208 void KeyEventNormalize::SetCurrentShieldMode(int32_t shieldMode)
209 {
210 std::lock_guard<std::mutex> guard(mtx_);
211 lastShieldMode_ = shieldMode;
212 }
213
TransformVolumeKey(struct libinput_device * dev,int32_t keyCode,int32_t keyAction) const214 int32_t KeyEventNormalize::TransformVolumeKey(struct libinput_device *dev, int32_t keyCode, int32_t keyAction) const
215 {
216 static std::once_flag flag;
217 static std::map<int32_t, DisplayMode> displayModes {
218 { KeyEvent::KEYCODE_VOLUME_DOWN, DisplayMode::UNKNOWN },
219 { KeyEvent::KEYCODE_VOLUME_UP, DisplayMode::UNKNOWN },
220 };
221 static std::string product;
222 const std::string theProduct { "LEM" };
223
224 std::call_once(flag, []() {
225 product = OHOS::system::GetParameter("const.build.product", "");
226 });
227 if (product != theProduct) {
228 return keyCode;
229 }
230 auto iter = displayModes.find(keyCode);
231 if (iter == displayModes.end()) {
232 return keyCode;
233 }
234 if (keyAction == KeyEvent::KEY_ACTION_DOWN) {
235 iter->second = WIN_MGR->GetDisplayMode();
236 if (iter->second != DisplayMode::SUB) {
237 return keyCode;
238 }
239 } else if (iter->second != DisplayMode::SUB) {
240 return keyCode;
241 }
242 const char *name = libinput_device_get_name(dev);
243 int32_t busType = static_cast<int32_t>(libinput_device_get_id_bustype(dev));
244 MMI_HILOGD("Flip volume keys upon fold: Dev:%{public}s, Bus:%{public}d",
245 name != nullptr ? name : "(null)", busType);
246 if (busType != BUS_HOST) {
247 return keyCode;
248 }
249 return (keyCode == KeyEvent::KEYCODE_VOLUME_DOWN ? KeyEvent::KEYCODE_VOLUME_UP : KeyEvent::KEYCODE_VOLUME_DOWN);
250 }
251 } // namespace MMI
252 } // namespace OHOS
253