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