• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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